/*
 * Goblin Games storefront styles — "Punchboard": stone, metal and board-game art.
 *
 * Ported from the Claude Design canvas (see ARTEFACTS.md for the URL and the
 * working files). Same layout and copy as before; only the character changes.
 *
 * The ground is cool stone, not warm parchment. Geometry is precise rather than
 * tactile: ONE 3px radius everywhere, 1px hairlines, no pills, no chips, no hard
 * offset shadows. Things that used to be tiles or badges — the section headings,
 * the language switcher, the footer's social links — are plain text now, carried
 * by weight, case and tracking. What holds them on the artwork is the paper halo,
 * not a plate: see The paper halo below. The hero's standfirst is the exception
 * and is neither: it is the ticker strip along the top of the band.
 *
 * Two faces: Geologica (a squarish technical grotesque with real Cyrillic) for
 * headings, prices and category names; Inter for body and UI. Both self-hosted at
 * the bottom of this file.
 *
 * Layout rhythm: the page ground is a seamless line-art scatter of board-game
 * pieces (assets/img/bg-body.webp) tiled on white. Homepage sections either paint
 * an opaque white band over it or let it through, so the rhythm is patterned vs
 * plain — which is why a band's 1px top and bottom hairlines are load bearing.
 * Which sections do which is driven by the `band` key in inc/homepage.php, not
 * guessed from the section type.
 *
 * Colours, fonts and spacing come from theme.json as CSS custom properties
 * (--wp--preset--color--*, --wp--preset--font-family--*). Reference those tokens
 * rather than hardcoding hex values, so a change in theme.json flows through.
 */

:root {
	--goblin-gold: var(--wp--preset--color--accent-1);
	--goblin-stone: var(--wp--preset--color--accent-2);
	--goblin-red: var(--wp--preset--color--accent-3);
	--goblin-gray: var(--wp--preset--color--accent-4);
	--goblin-stone-deep: var(--wp--preset--color--accent-5);
	--goblin-ink: var(--wp--preset--color--contrast);

	/* Hairline greys and the darker ink. Not in the theme.json palette on purpose:
	 * they are structural edges, not colours anyone should pick in the editor. */
	--goblin-ink-soft: #414951;
	--goblin-edge: #d7dbdf;
	--goblin-edge-dark: #bcc3c9;

	/* The colour the ground tile is laid over. bg-body.webp is a TRANSPARENT
	 * line-art pattern — the drawing lives in its alpha channel, not its RGB — so
	 * this is the page's actual background colour, showing through every gap in the
	 * pattern. White: the pieces are meant to read as line art drawn on the page,
	 * and any tint under them turns the ground into a tinted field with faint marks
	 * on it instead. Change this one value to retone the whole page. */
	--goblin-ground: var(--wp--preset--color--base, #fff);

	/* How wide one tile of the ground pattern is drawn. The file is 1536px across;
	 * drawing it smaller repeats it more often and shrinks the pieces, which reads
	 * as texture rather than as illustration. Height follows from `auto`, so the
	 * tile never distorts and the seam stays a seam. */
	--goblin-ground-size: 768px;

	/* And how strongly it reads. The artwork is drawn at full strength in the file;
	 * this fades the whole layer towards the ground colour underneath, so the
	 * pieces stay a texture you notice only if you look for them and never compete
	 * with a product photograph or a line of type sitting on them. It is an opacity
	 * on the pattern and not a white veil painted back over it, so retoning the page
	 * is still the single change to --goblin-ground above. */
	--goblin-ground-strength: 0.35;

	/* The cart bag, painted through a mask so it inherits `currentColor`. */
	--goblin-cart-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z'/%3E%3Cpath d='M3 6h18'/%3E%3Cpath d='M16 10a4 4 0 0 1-8 0'/%3E%3C/svg%3E");

	/* The gallery's full-screen trigger, painted through a mask so it inherits
	 * `currentColor` — same arrangement as the cart bag above. */
	--goblin-zoom-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20.5 20.5 16 16'/%3E%3C/svg%3E");

	--goblin-green: #6f9a34;
	--goblin-gold-ink: #96690b;
	--goblin-red-ink: #8a161a;

	/* The hero ticker's strip. Fixed rather than content-derived because the hero's
	 * own top padding has to clear it, and one number both can read is simpler than
	 * making the band's height depend on a font that loads late. Kept close to the
	 * type's own height on purpose — it is a rule with words in it, not a bar. */
	--goblin-ticker-h: 26px;

	/* How long the crawl takes to travel one group. A group is ~2900px wide (see
	 * GOBLIN_TICKER_GROUP_CHARS, which is what keeps that roughly constant), so this
	 * is about 48px/s — slow enough to read a passing word without following it. */
	--goblin-ticker-duration: 60s;

	--goblin-ui: var(--wp--preset--font-family--body, system-ui, sans-serif);
	--goblin-display: var(--wp--preset--font-family--display, var(--goblin-ui));

	/* One radius for the whole site. The old 10px/6px pair and the 999px pills are
	 * gone — rounding was doing decorative work this design gives to the hairlines. */
	--goblin-radius: 3px;

	--goblin-gap: clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
	--goblin-shadow: 0 1px 2px rgba(27, 31, 36, 0.05), 0 8px 20px rgba(27, 31, 36, 0.06);
	--goblin-shadow-lift: 0 2px 4px rgba(27, 31, 36, 0.07), 0 16px 32px rgba(27, 31, 36, 0.12);
}

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

/* The page ground: a seamless line-art scatter of board-game pieces, tiled over
 * --goblin-ground at --goblin-ground-size.
 *
 * bg-body.webp is TRANSPARENT — the drawing is in the alpha channel and the RGB
 * underneath is meaningless filler. Two consequences worth knowing before touching
 * it. First, the background-color is not a fallback here, it is the page's actual
 * colour and it shows through every gap in the pattern. Second, anything that
 * flattens the file to RGB (an image tool's default "convert", a naive re-encode)
 * throws the picture away and leaves a flat grey field — which is exactly what
 * happened once already during this port. So the file is never the place to make
 * the pattern lighter: --goblin-ground-strength is.
 *
 * The other two background images (hero, footer) are opaque, and every one of the
 * three is WebP-only — half the bytes of the equivalent JPEG, and universally
 * supported since 2020. Each has a solid tone painted under it, so on anything
 * that cannot decode a WebP the band still gets its correct value and every halo,
 * scrim and ink choice below still reads. */
body {
	/* The containing block for the pattern layer below. */
	position: relative;
	margin: 0;
	color: var(--goblin-ink);
	background: var(--goblin-ground);
	font-family: var(--wp--preset--font-family--body, sans-serif);
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
}

/* The ground pattern, on a layer of its own rather than as body's
 * background-image. `opacity` is the only way to fade a transparent tile without
 * re-encoding it — a background-color cannot be laid over a background-image in
 * the same box, and painting a translucent white veil on top instead would mean
 * two values to keep in step every time the ground is retoned.
 *
 * `z-index: -1` puts it above the canvas and below everything in flow, so a white
 * band still paints over it (in-flow block backgrounds paint after negative
 * z-index children) with no z-index needed anywhere else. `min-height` is for
 * short pages, where body's own box stops above the fold. */
body::before {
	content: ""; position: absolute; inset: 0; z-index: -1;
	min-height: 100vh; pointer-events: none;
	background: url("../img/bg-body.webp") repeat;
	background-size: var(--goblin-ground-size) auto;
	opacity: var(--goblin-ground-strength);
}

img { max-width: 100%; height: auto; }

a { color: var(--goblin-red); text-underline-offset: 2px; }
a:hover { color: var(--goblin-red-ink); }

/* Geologica for headings. The theme ran Inter-only after Ruslan Display was
 * dropped (see ARTEFACTS.md) — the objection then was ornamental Slavic-Cyrillic
 * letterforms, not a second face as such. Geologica is a technical grotesque with
 * a real, unstylised Cyrillic, so Macedonian headlines read as signage rather
 * than as fantasy novel covers. Weight 600, not 700: the face is squarer and
 * denser than Inter, so bold is heavier than it looks in the type tester. */
h1, h2, h3, h4 {
	font-family: var(--goblin-display);
	line-height: 1.15;
	font-weight: 600;
	letter-spacing: -0.02em;
	margin: 0 0 0.6em;
}

.goblin-container {
	width: min(100% - 2rem, var(--wp--custom--layout--wide-size, 1280px));
	margin-inline: auto;
}

/* ---------- Hero ticker ----------
 * The shop's standfirst as a crawling band across the top of the hero: an ink
 * strip, white tracked small caps, the line repeated with a gold dot between
 * every pass, moving right to left and never stopping.
 *
 * It replaced `.goblin-eyebrow`, which was the same sentence as one static line —
 * first under the headline, then above it, then above the wordmark, and on a plate
 * and then a paper halo to survive the artwork at each spot. On its own strip it
 * needs none of that: the strip is opaque, so the type is simply white on ink.
 *
 * Absolutely positioned rather than in flow, because the hero's body sits inside
 * `.goblin-container` and this has to run edge to edge. `.goblin-section--hero` is
 * the positioned ancestor (and already clips with `overflow: hidden`), so
 * `inset: 0 0 auto 0` on a child of `.goblin-hero` lands on the band's full width.
 *
 * The loop is two identical groups translated left by exactly -50%: at the end of
 * the run group 2 is where group 1 began, so the jump back to 0 is invisible. That
 * holds only while a group is at least as wide as the band, which is why
 * goblin_render_hero_ticker() computes the repeat count from the copy's length
 * instead of fixing it — and, since that makes every group about the same width,
 * why one constant duration here reads as one constant speed for any subtitle.
 */
/* --goblin-ink-soft, not --goblin-ink: at full ink the strip reads as a black bar
 * laid across the artwork, and a 26px black rule directly under a white header is
 * the heaviest thing on the page before the reader has seen anything. One step up
 * into slate keeps white type at ~8:1 and lets the strip sit on the band rather
 * than cut it. */
.goblin-ticker {
	position: absolute; inset: 0 0 auto 0; z-index: 2;
	display: flex; align-items: center;
	height: var(--goblin-ticker-h); overflow: hidden;
	background: var(--goblin-ink-soft);
}
.goblin-ticker__track {
	display: flex; flex: none;
	animation: goblin-ticker-crawl var(--goblin-ticker-duration) linear infinite;
}
/* The nudge is an optical correction, not a fix for a layout bug: the item's box
 * is centred in the strip to the pixel (measured), but the line box reserves
 * descender room that all-caps text never uses, so the glyphs read as sitting
 * high. ~1px down at this size. It goes on the group because the track's own
 * transform is the crawl. */
.goblin-ticker__group {
	display: flex; flex: none; white-space: nowrap;
	transform: translateY(0.09em);
}
.goblin-ticker__item {
	font-family: var(--goblin-ui);
	font-size: clamp(0.64rem, 0.61rem + 0.12vw, 0.72rem);
	font-weight: 700; letter-spacing: 0.22em; line-height: 1;
	text-transform: uppercase; color: #fff;
}
/* The separator hangs off each item rather than sitting between them, so there is
 * exactly one everywhere — including across the seam where group 2 follows group 1,
 * where a `+` selector would have produced none. */
.goblin-ticker__item::after {
	content: "\2022"; margin: 0 0.85em 0 0.55em;
	letter-spacing: 0; color: var(--goblin-gold);
}
@keyframes goblin-ticker-crawl {
	from { transform: translateX(0); }
	to { transform: translateX(-50%); }
}

.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px;
	overflow: hidden; clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}
.goblin-skip-link:focus {
	position: fixed; top: 0.5rem; left: 0.5rem; z-index: 1000;
	width: auto; height: auto; clip: auto;
	padding: 0.5rem 0.9rem; background: #fff; border-radius: var(--goblin-radius);
}

:focus-visible { outline: 2px solid var(--goblin-gold); outline-offset: 2px; }

/* ---------- The paper halo ----------
 * Ink text that sits directly on the tabletop artwork — the hero headline, every
 * section heading, the rails' "see more" label — carries a white outline so it
 * separates from whatever is behind it, and the headings take a hard offset shadow
 * on top of that.
 *
 * The hero's standfirst used to be a fourth member of this list and fought it at
 * every size: too small for an outline to carry, so it went onto an opaque plate,
 * then back to a halo once it moved somewhere quieter. It is the ticker now, on a
 * strip of its own, and needs neither.
 *
 * `paint-order: stroke fill` is what makes this safe to do at these widths: the
 * stroke is painted first and the fill covers its inward half, so the glyph keeps
 * its true weight and the visible halo is half the declared width. Without it the
 * stroke paints OVER the fill and a 5px outline swallows the letter whole — hence
 * the @supports gate. Every browser since ~2018 passes it; anything that does not
 * simply gets unhaloed text, which is legible on the white bands and merely low
 * contrast on the ground.
 *
 * Applied on white bands too, deliberately: the halo is invisible there and the
 * offset shadow is the same on both, so a heading does not change character when
 * a section is moved from one band to the other.
 */
@supports (paint-order: stroke) {
	.goblin-hero__title,
	.goblin-section__title,
	.goblin-rail__more-label {
		-webkit-text-stroke-color: #fff;
		paint-order: stroke fill;
	}
	.goblin-hero .goblin-hero__title {
		-webkit-text-stroke-width: clamp(5px, 4.26px + 0.19vw, 7px);
		text-shadow: 5px 5px 0 rgba(27, 31, 36, 0.22);
	}
	.goblin-section__title {
		-webkit-text-stroke-width: clamp(4px, 3.63px + 0.1vw, 5px);
		text-shadow: 3px 3px 0 rgba(27, 31, 36, 0.16);
	}
	/* Heavier than its size would suggest: it is the smallest ink text in the
	 * design that sits straight on the ground pattern, and at 3px the line art was
	 * still reading through the counters. No offset shadow though — it is a label
	 * under a button, not a heading, and the offset would make it compete with the
	 * row it is closing. */
	.goblin-rail__more-label { -webkit-text-stroke-width: 4.5px; }
}

/* ---------- Header ----------
 * Two rows: brand + search + actions on white, then the primary nav on its own
 * stone band. With 11 top-level categories the nav needs the whole row — sharing
 * one flex line with the logo and the account links wrapped it three deep.
 */
.goblin-header {
	background: #fff;
	position: sticky; top: 0; z-index: 50;
	box-shadow: 0 1px 0 var(--goblin-edge);
}
.goblin-header__inner {
	display: flex; align-items: center; gap: 1.5rem;
	padding-block: 0.95rem;
}
.goblin-header__brand { flex: 0 0 auto; }
/* The letterless mark (`logo-mark.png`), not the horizontal wordmark — the hero
 * already carries the lettering, so the header only needs the face. It ships as a
 * trimmed transparent PNG rather than the JPG the wordmark uses, so no baked-in
 * white box appears if this band ever stops being #fff. */
/* `flex`, not `inline-flex`. As an inline-level box the anchor sat on a text
 * baseline, so its line box reserved descender space *below* it — the brand div
 * came out 51.6px tall around a 44px logo and the mark rode 3.8px above the
 * centre the search field and the account links share. Block-level removes the
 * line box entirely. Same reason the img is `display: block`. */
.goblin-header__logo { display: flex; }
.goblin-header__logo img { height: 44px; width: auto; display: block; }

/* Header search — a stone field with a magnifier, square-cornered like everything
 * else; submit is hidden (enter to search). */
.goblin-header__search { flex: 1 1 auto; max-width: 26rem; }
.goblin-header__search .search-form { display: flex; align-items: center; margin: 0; }
.goblin-header__search label { display: block; flex: 1 1 auto; margin: 0; }
.goblin-header__search .search-field {
	width: 100%;
	background: var(--goblin-stone) no-repeat 0.85rem center / 1rem;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b747d' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.2-4.2'/%3E%3C/svg%3E");
	color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	padding: 0.65rem 0.9rem 0.65rem 2.4rem; font-family: inherit;
	/* 16px, and not a rem, at every width — iOS Safari zooms the whole page in when
	 * a focused input is under 16px and does not zoom back out, leaving the page
	 * stuck wider than the viewport for the rest of the visit. Set here rather than
	 * in the mobile block because an iPad in landscape is past the 900px breakpoint
	 * and still does it. `1rem` is the same number today but is hostage to the root
	 * size; the threshold is absolute, so the value is too. */
	font-size: 16px;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.goblin-header__search .search-field::placeholder { color: var(--goblin-gray); }
.goblin-header__search .search-field:hover { border-color: var(--goblin-edge-dark); }
.goblin-header__search .search-field:focus {
	outline: none; background-color: #fff; border-color: var(--goblin-gold);
}
.goblin-header__search .search-submit {
	position: absolute; width: 1px; height: 1px;
	overflow: hidden; clip: rect(1px, 1px, 1px, 1px); white-space: nowrap;
}

.goblin-header__actions { display: flex; align-items: center; gap: 1.25rem; flex: 0 0 auto; }
.goblin-header__link {
	text-decoration: none; color: var(--goblin-ink); white-space: nowrap;
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 600;
}
.goblin-header__link:hover { color: var(--goblin-red); }
/* Cart: a bag glyph with the line count as a round badge on its corner. The count
 * used to be a block set after the link, which on a phone cost as much width as
 * the glyph itself and pushed the language switcher off the row. Over the corner
 * it costs nothing — the badge overhangs into the flex gap.
 *
 * The glyph is a mask rather than a background image so it takes `currentColor`
 * and turns red with the label on hover; as a background-image the two halves of
 * the link would hover apart. */
.goblin-cart {
	display: inline-flex; align-items: center; gap: 0.45rem;
	text-decoration: none; color: var(--goblin-ink);
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 700;
}
.goblin-cart:hover { color: var(--goblin-red); }
.goblin-cart__icon {
	order: -1;   /* label leads in the DOM, for the announcement; bag leads on screen */
	position: relative; flex: 0 0 auto;
	width: 22px; height: 22px;
}
/* The mask goes on a pseudo-element, not on .goblin-cart__icon itself: a mask
 * clips an element's descendants too, and the badge is one — masked directly, the
 * count came out as a red crescent trimmed to the bag's outline. */
.goblin-cart__icon::before {
	content: ""; position: absolute; inset: 0;
	background: currentColor;
	-webkit-mask: center / contain no-repeat var(--goblin-cart-glyph);
	mask: center / contain no-repeat var(--goblin-cart-glyph);
}
.goblin-cart__count {
	position: absolute; top: -7px; right: -9px;
	background: var(--goblin-red); color: #fff; border-radius: 999px;
	min-width: 16px; height: 16px; padding: 0 4px;
	box-sizing: border-box; text-align: center;
	font-size: 0.62rem; font-weight: 700; line-height: 16px; letter-spacing: 0;
	/* The badge sits on the glyph; the ring is the header's own white, so the two
	 * shapes read as separate marks rather than one blot. */
	box-shadow: 0 0 0 2px #fff;
}
/* An empty cart gets no badge — header.php prints nothing rather than a "0", and
 * `:empty` is the test so a fragment refresh that blanks the node hides it too. */
.goblin-cart__count:empty { display: none; }

/* ---------- Primary nav band ----------
 * The band is a rail (see the Rail block below): eleven top-level categories
 * wrapped onto a second row on narrow desktops, which made the header jump a
 * line. It now stays one row and scrolls sideways instead. The <ul> itself is the
 * rail's track, so `.goblin-menu` carries the scrolling — hence the extra
 * `overflow: visible` reset in the mobile block, where the same list becomes a
 * stacked panel.
 */
.goblin-header__nav {
	background: var(--goblin-stone-deep);
	border-top: 1px solid var(--goblin-edge);
	border-bottom: 1px solid var(--goblin-edge);
}
.goblin-header__nav .goblin-rail { --goblin-rail-fade: var(--goblin-stone-deep); }
.goblin-menu {
	list-style: none; margin: 0; padding: 0;
	display: flex; flex-wrap: nowrap; column-gap: 6px; row-gap: 0;
	font-family: var(--goblin-ui); font-size: 0.88rem;
	/* Room for the focus ring, which the track's overflow would otherwise clip,
	 * and a landing zone so tabbing never parks an item under an arrow. */
	padding-block: 3px; scroll-padding-inline: 3rem;
}
.goblin-menu > li { position: relative; flex: 0 0 auto; }
/* "My account" and "Wishlist" are injected into this list by header.php so the
 * mobile panel can show them as ordinary rows. The desktop rail is not where they
 * belong — the header row above already has them — so they only exist below 900px.
 * See the mobile block in the Responsive section. */
.goblin-menu > .goblin-menu__account { display: none; }
.goblin-menu > li > a {
	display: block; position: relative; padding: 0.75rem 9px;
	white-space: nowrap;
	text-decoration: none; color: var(--goblin-ink); font-weight: 600;
}
.goblin-menu > li > a::after {
	content: ""; position: absolute; inset: auto 9px 6px 9px; height: 2px;
	background: var(--goblin-gold);
	transform: scaleX(0); transform-origin: left; transition: transform 0.16s ease;
}
.goblin-menu > li > a:hover,
.goblin-menu > li.current-menu-item > a { color: var(--goblin-ink); }
.goblin-menu > li > a:hover::after,
.goblin-menu > li:focus-within > a::after,
.goblin-menu > li.current-menu-item > a::after { transform: scaleX(1); }

/* Hover dropdowns for submenus (depth 2).
 *
 * A scroll container clips, so inside the rail an absolutely positioned dropdown
 * would be cut off at the row's bottom edge. `position: fixed` escapes ancestor
 * overflow; initMenuFlyouts() in goblin.js marks the list `is-flyout` and places
 * each panel under its item. They stay DOM children of their <li>, so the
 * :hover / :focus-within chain below is untouched. Without JS the rule never
 * applies and the panels stay absolute (clipped — the mobile menu already needs
 * JS, and every category page lists its own subcategories). */
@media (min-width: 901px) {
	.goblin-menu.is-flyout .sub-menu { position: fixed; top: 0; left: 0; }
}
.goblin-menu .sub-menu {
	list-style: none; margin: 0; padding: 0.4rem 0;
	position: absolute; top: 100%; left: -0.9rem; z-index: 60;
	min-width: 230px; background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow-lift);
	display: none;
}
.goblin-menu .menu-item-has-children:hover > .sub-menu,
.goblin-menu .menu-item-has-children:focus-within > .sub-menu { display: block; }
.goblin-menu .sub-menu a {
	display: block; padding: 0.4rem 0.9rem;
	text-decoration: none; color: var(--goblin-ink); font-weight: 500;
}
.goblin-menu .sub-menu a:hover { background: var(--goblin-stone); color: var(--goblin-red); }

/* ---------- Language switcher ----------
 * A <details> dropdown: only the current language shows in the header bar, the
 * others drop below. Three codes side by side ate too much of the header line,
 * which is tight on mobile. <details>/<summary> gives the open/close behaviour
 * and keyboard support for free; goblin.js only adds outside-click/Escape.
 *
 * The trigger is plain tracked-out text now, not a bordered chip — same move as
 * the hero ticker and the footer's social links. */
.goblin-langs { position: relative; font-family: var(--goblin-ui); flex: 0 0 auto; }
.goblin-langs__current {
	display: inline-flex; align-items: center; gap: 0.3rem;
	font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
	color: var(--goblin-ink); cursor: pointer; list-style: none; white-space: nowrap;
}
.goblin-langs__current::-webkit-details-marker { display: none; }
.goblin-langs__current::after {
	content: ""; width: 0.36rem; height: 0.36rem; margin-top: -0.15rem;
	border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg); opacity: 0.55;
	transition: transform 0.15s ease;
}
.goblin-langs__current:hover { color: var(--goblin-red); }
.goblin-langs[open] > .goblin-langs__current { color: var(--goblin-red); }
.goblin-langs[open] > .goblin-langs__current::after { transform: rotate(-135deg); margin-top: 0.15rem; }
.goblin-langs__menu {
	position: absolute; z-index: 40; top: calc(100% + 0.5rem); right: 0;
	display: grid; min-width: 100%; padding: 0.25rem;
	background: #fff; border: 1px solid var(--goblin-edge);
	border-radius: var(--goblin-radius); box-shadow: var(--goblin-shadow);
}
.goblin-langs__item {
	display: block; padding: 0.35rem 0.6rem; border-radius: 2px;
	font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
	color: var(--goblin-gray); text-decoration: none; white-space: nowrap;
}
.goblin-langs__item:hover { background: var(--goblin-stone); color: var(--goblin-ink); }

/* ---------- Mobile nav toggle (hamburger) ---------- */
.goblin-nav-toggle {
	display: none;
	/* `flex: 0 0 auto` because it shares the header row with a flexible search
	 * field: as a shrinkable item the button squeezed to ~20px on a 360px phone. */
	flex: 0 0 auto;
	width: 38px; height: 38px; padding: 0; cursor: pointer;
	background: transparent; border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	align-items: center; justify-content: center;
}
.goblin-nav-toggle__bars, .goblin-nav-toggle__bars::before, .goblin-nav-toggle__bars::after {
	content: ""; display: block; width: 18px; height: 2px; background: var(--goblin-ink);
	transition: transform 0.18s ease, opacity 0.18s ease;
}
.goblin-nav-toggle__bars { position: relative; }
.goblin-nav-toggle__bars::before { position: absolute; top: -6px; }
.goblin-nav-toggle__bars::after { position: absolute; top: 6px; }
.goblin-nav-toggle[aria-expanded="true"] .goblin-nav-toggle__bars { background: transparent; }
.goblin-nav-toggle[aria-expanded="true"] .goblin-nav-toggle__bars::before { transform: translateY(6px) rotate(45deg); }
.goblin-nav-toggle[aria-expanded="true"] .goblin-nav-toggle__bars::after { transform: translateY(-6px) rotate(-45deg); }

/* ---------- Sections and bands ----------
 * A section either paints a white band over the tabletop or lets it through.
 * Which one is computed in goblin_render_homepage() (inc/homepage.php), not set
 * per section and not inferred from the section type: the sections that show a
 * band alternate, starting on white, and the hero and the carousel are outside
 * that count because neither shows a band at all.
 */
.goblin-section { padding-block: clamp(34px, 1.43rem + 2.86vw, 64px); }
.goblin-section--band-white {
	background: #fff;
	border-block: 1px solid var(--goblin-edge);
}
.goblin-section--band-ground { background: transparent; }

/* The heading is plain text held between two hairlines — the rules are the
 * heading's own ::before/::after and the text is the anonymous flex item between
 * them, so this needs no extra wrapper in the markup. */
.goblin-section__title {
	display: flex; align-items: center;
	gap: clamp(14px, 8.8px + 1.33vw, 28px);
	margin: 0 0 clamp(22px, 17.5px + 1.14vw, 34px);
	font-size: clamp(1.18rem, 0.97rem + 0.87vw, 1.75rem);
	font-weight: 600; letter-spacing: -0.02em;
}
.goblin-section__title::before,
.goblin-section__title::after {
	content: ""; flex: 1 1 auto; border-top: 1px solid var(--goblin-edge-dark);
}

/* ---------- Hero ----------
 * A lit stone band with the tabletop scene multiplied into it: a diagonal sheen
 * across the middle, gold overhead, red and green light pooling in the bottom
 * corners, over a stone-to-white vertical wash.
 *
 * `isolation` + a negative z-index on the artwork layer keeps it above the
 * section's own gradients but below the content, with no z-index on the content.
 * `mix-blend-mode: multiply` is why the artwork needs no scrim of its own: it
 * darkens the band rather than replacing it, so the gradients still read through.
 */
.goblin-section--hero {
	position: relative; isolation: isolate; overflow: hidden;
	padding-block: 0;
	border-bottom: 1px solid var(--goblin-edge-dark);
	background:
		linear-gradient(104deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.5) 47%, rgba(255, 255, 255, 0) 62%),
		radial-gradient(54% 42% at 50% -8%, rgba(231, 166, 20, 0.18), rgba(231, 166, 20, 0) 70%),
		radial-gradient(30% 32% at 5% 106%, rgba(176, 30, 35, 0.05), rgba(176, 30, 35, 0) 66%),
		radial-gradient(28% 30% at 96% 106%, rgba(111, 154, 52, 0.07), rgba(111, 154, 52, 0) 66%),
		linear-gradient(180deg, #e5e9ec 0%, #eef0f2 58%, #f4f5f6 100%);
}
.goblin-section--hero::before {
	content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
	background: url("../img/bg-hero.webp") center / cover no-repeat;
	mix-blend-mode: multiply;
	opacity: 0.62;
}

/* The ticker is absolutely positioned and takes no space, so the top padding is
 * doing two jobs: clearing the strip and setting the gap under it. Written as the
 * sum of the two rather than as one number with a `max()` floor, so the clamp is
 * the *visible* gap above the wordmark and reads as one — 44px on a phone, 72px on
 * a wide band — whatever the strip's height is later set to.
 *
 * The bottom stays a shade heavier than that gap: the shop-facts strip used to sit
 * under the headline and hold the band open, and it is a footer band now. This is
 * some of that height given back as space — some, not all, so the headline is not
 * left sitting on the carousel's top edge. */
.goblin-hero {
	padding-top: calc(var(--goblin-ticker-h) + clamp(40px, 25px + 3.8vw, 72px));
	padding-bottom: clamp(42px, 23.6px + 4.72vw, 84px);
}

/* A flex column, not a centred text flow. It holds the wordmark and the headline;
 * the standfirst that used to sit in here with them is the ticker strip above the
 * band now. (Back when all three were inline-blocks, the wordmark and the
 * standfirst shared one line box as soon as the band was wide enough for both,
 * which on desktop read as a logo pushed left of a right-shifted line — a column
 * is what fixes that structurally.) */
.goblin-hero__inner {
	display: flex; flex-direction: column; align-items: center; text-align: center;
	/* Tight on purpose: wordmark and headline are one masthead, and at the old
	 * 16–22px they read as separate things stacked in a band. The band's own
	 * padding is untouched — this closes the gap between the children, it does not
	 * shrink the hero. */
	gap: clamp(6px, 4.5px + 0.39vw, 10px);
}

/* The wordmark leads the hero. We reuse the white logo and invert it rather than
 * the black one: the black asset is a JPG with a baked-in white background, which
 * would paint a white box on the band. Inverting the transparent white PNG gives
 * the same black artwork with the transparency intact — and the doubled white
 * drop-shadow is that mark's share of the paper halo the headings get in CSS. */
.goblin-hero__logo img {
	display: block; width: auto;
	height: clamp(62px, 43.6px + 4.72vw, 104px);
	filter: invert(1) drop-shadow(0 0 4px #fff) drop-shadow(0 0 4px #fff);
}

/* Two classes on purpose: theme.json's heading rule (`:root :where(h1)`) is also
 * specificity 0,1,0, so a single class would be a source-order coin flip. */
.goblin-hero .goblin-hero__title {
	font-family: var(--goblin-display);
	font-weight: 600; letter-spacing: -0.032em;
	color: var(--goblin-ink); line-height: 1.0; margin: 0;
	font-size: clamp(2.4rem, 1.58rem + 3.35vw, 4.6rem); text-wrap: balance;
}

/* ---------- Carousel ----------
 * The one section that runs edge to edge: goblin_print_section() skips the
 * container for it, so the frame is the viewport.
 *
 * The scrolling is the browser's — a snapping overflow row, which is why a swipe
 * and a trackpad work before any JS loads. There are deliberately no arrows: the
 * dot row under the frame is both the control and the position readout, and a
 * second affordance saying the same thing would only crowd the artwork. The
 * scrollbar is hidden the same way the rail hides its own.
 *
 * It advances itself every 5s (initCarousel in goblin.js), which pauses on hover
 * and focus and does not run at all under `prefers-reduced-motion`.
 */
.goblin-section--full { padding-block: 0; }
.goblin-section--full > .goblin-carousel { margin-block: 0; }

/* The hero sits *on* this band, not beside it: the carousel is recessed into the
 * page so the section above reads as the lid over an opening.
 *
 * The shadows hang on an overlay pseudo-element rather than on the section
 * itself, because an inset `box-shadow` paints over an element's background but
 * *under* its content — and here the content is a full-bleed photograph, so a
 * shadow set on the section would be hidden by the very thing it has to fall on.
 *
 * The top edge is the deep one; the other three are only enough to close the
 * frame. Light comes from above, so the lip that casts is the hero's bottom edge,
 * and matching all four sides would read as a vignette on the artwork instead of
 * as a recess. Each shadow is offset well past its own blur with a negative
 * spread pulling it back, which is what keeps it a band along one edge rather
 * than a haze creeping into the middle of the slide.
 *
 * `isolation` on the section is what lets the overlay take a z-index without a
 * fight: the dots and the CTA have none of their own, so they keep painting in
 * source order underneath it, and the overlay passes clicks straight through to
 * them.
 */
.goblin-section--carousel { position: relative; isolation: isolate; }
.goblin-section--carousel::after {
	content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
	box-shadow:
		inset 0 22px 26px -14px rgba(24, 28, 32, 0.62),
		inset 0 -12px 20px -14px rgba(24, 28, 32, 0.3),
		inset 16px 0 22px -20px rgba(24, 28, 32, 0.4),
		inset -16px 0 22px -20px rgba(24, 28, 32, 0.4);
}

.goblin-carousel { position: relative; }
.goblin-carousel__track {
	display: flex; flex-wrap: nowrap;
	overflow-x: auto; overflow-y: hidden;
	scroll-snap-type: x mandatory;
	/* A sideways gesture that runs out of row must not turn into a page swipe. */
	overscroll-behavior-x: contain;
	scrollbar-width: none; -ms-overflow-style: none;
}
.goblin-carousel__track::-webkit-scrollbar { width: 0; height: 0; }

.goblin-carousel__slide {
	position: relative; flex: 0 0 100%; scroll-snap-align: center;
	display: block; text-decoration: none;
}
/* 2:1 is the shape the settings screen asks for (1200 × 600), but honoured
 * literally across a full-bleed band it makes a 1280px-tall slide on a 2560px
 * monitor — a promo strip that fills the whole fold. The cap is the source
 * image's own height, so the frame stops growing exactly where the artwork would
 * start being upscaled, and object-fit crops the sides beyond that. */
.goblin-carousel__image {
	display: block; width: 100%; height: auto;
	aspect-ratio: 2 / 1; max-height: min(60vh, 600px); object-fit: cover;
}

/* The button sits centred along the bottom of the frame, on the same axis as the
 * dots below it — a full-bleed band has no content column to align to, and the
 * hero above it is centred too. The bottom offset clears the dot row rather than
 * merely missing it: the two are different controls, and reading them as one
 * stacked cluster is what made the button look glued to the dots. */
.goblin-carousel__cta {
	position: absolute; inset: auto auto clamp(46px, 2.2rem + 2.4vw, 78px) 0;
	width: min(100% - 2rem, var(--wp--custom--layout--wide-size, 1280px));
	left: 50%; transform: translateX(-50%);
	display: flex; justify-content: center;
}

.goblin-carousel__dots {
	position: absolute; left: 0; right: 0; bottom: clamp(8px, 0.4rem + 0.6vw, 16px);
	display: flex; justify-content: center; gap: 10px;
}
.goblin-carousel__dot {
	width: 10px; height: 10px; padding: 0; border-radius: 50%;
	border: 2px solid var(--goblin-ink); background: #fff;
	cursor: pointer; transition: background-color 0.15s ease, transform 0.15s ease;
}
.goblin-carousel__dot:hover { transform: scale(1.15); }
.goblin-carousel__dot[aria-current="true"] { background: var(--goblin-ink); }

@media (max-width: 640px) {
	/* Portrait phones: a 2:1 crop of a 1200×600 slide leaves the artwork tiny. Give
	   the frame more height and let object-fit take the sides. */
	.goblin-carousel__image { aspect-ratio: 3 / 2; }
}

/* ---------- Buttons ----------
 * Flat gold with a single contact shadow. The previous skin gave it a 2px solid
 * underedge and a wide gold glow, which is the one tactile flourish this design
 * has no room for. */
.goblin-btn {
	display: inline-flex; align-items: center; gap: 12px; font-family: var(--goblin-ui);
	font-weight: 700; letter-spacing: 0.01em; padding: 16px 34px; min-height: 48px;
	border-radius: var(--goblin-radius); border: 0;
	cursor: pointer; font-size: 0.98rem; text-decoration: none;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.goblin-btn--gold {
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
}
.goblin-btn--gold:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}
.goblin-btn__arrow { transition: transform 0.16s ease; }
.goblin-btn:hover .goblin-btn__arrow { transform: translateX(4px); }

/* The plate button: white sheet, 2px ink edge, hard offset shadow. Those three
 * moves are the hero title's `text-shadow: 5px 5px 0` promoted from type to box,
 * which is what makes a carousel slide read as the same design language as the
 * band above it rather than as a banner dropped in. (The hero's standfirst was
 * built the same way for a while; it is the ticker strip now — see Hero ticker —
 * and this is the only plate left in the design.)
 * Hover presses it: the button steps into half its shadow. */
/* Smaller than the gold CTA it shares a base class with: that one is the single
 * action in an empty hero band, this one sits over artwork the reader is already
 * looking at, and at hero size it stopped being a label on the image and started
 * being a second banner.
 *
 * It takes the display face rather than the UI one — Geologica is the squarish
 * grotesque the headings use, and at its heaviest (the axis tops out at 700) in
 * small caps it is the blockiest thing the theme owns, which is what a plate with
 * a hard offset shadow wants sitting inside it. */
.goblin-btn--plate {
	background: #fff; color: var(--goblin-ink);
	border: 2px solid var(--goblin-ink);
	box-shadow: 3px 3px 0 var(--goblin-ink);
	padding: 10px 20px; min-height: 0; gap: 9px;
	font-family: var(--goblin-display); font-weight: 700;
	font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em;
	transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.goblin-btn--plate:hover {
	background: #fff; color: var(--goblin-ink);
	transform: translate(2px, 2px);
	box-shadow: 1px 1px 0 var(--goblin-ink);
}

.goblin-button {
	display: inline-block; padding: 0.6rem 1.1rem; border-radius: var(--goblin-radius);
	background: var(--goblin-red); color: #fff; text-decoration: none; font-weight: 600;
}
.goblin-button:hover { background: var(--goblin-red-ink); color: #fff; }

/* ---------- Grid + cards ---------- */
.goblin-grid {
	display: grid;
	grid-template-columns: repeat(var(--goblin-cols, 3), minmax(0, 1fr));
	gap: var(--goblin-gap);
}

/* No hover animation, the same as the product card below and for the same
 * reason. These sit eight to a grid and four to an archive row, and a pointer
 * crossing that grid on its way somewhere set off a run of tiles lifting and
 * dropping one after another — motion the reader did not ask for, from a card
 * they were only passing over. The lift also moved the tile off its own gap,
 * which on a two-up phone grid is a card visibly nudging its neighbour's
 * alignment.
 *
 * What is left is the border going one step darker, applied instantly: there is
 * no `transition` here on purpose, so nothing eases. That is the whole hover
 * vocabulary on both cards now — which is also why the `prefers-reduced-motion`
 * block near the end of this file no longer has a transform to cancel. */
.goblin-card {
	position: relative; display: flex; flex-direction: column;
	background: #fff; border: 1px solid var(--goblin-edge);
	border-radius: var(--goblin-radius); overflow: hidden;
	text-decoration: none; color: var(--goblin-ink);
	box-shadow: var(--goblin-shadow);
}
.goblin-card:hover {
	border-color: var(--goblin-edge-dark);
	color: var(--goblin-ink);
}

/* Fixed-ratio media so every card in a row lines up. `min-height: 0` is load
 * bearing: as a flex item the default `min-height: auto` lets a tall image's
 * intrinsic height beat `aspect-ratio`, which used to leave rows ragged. */
.goblin-card__media {
	position: relative; display: block; flex: 0 0 auto;
	aspect-ratio: 4 / 3; min-height: 0; overflow: hidden;
	background: #fff; border-bottom: 1px solid var(--goblin-edge);
}
/* Category art is a mix of square product shots, wide banners and portraits —
 * `contain` shows all of it instead of cropping into the subject. No hover zoom:
 * this skin moves the whole card, not the picture inside it. */
.goblin-card__media img {
	position: absolute; inset: 0; display: block;
	width: 100%; height: 100%; padding: 16px;
	object-fit: contain;
}
.goblin-card__placeholder {
	display: block; width: 100%; height: 100%;
	background: linear-gradient(135deg, var(--goblin-stone), var(--goblin-stone-deep));
}
/* The body is stone, not white — it is what separates a category tile from the
 * white product card next to it now that both share one border and one radius.
 *
 * It is also the product card's text block in miniature, and for the same
 * reason: it reserves two lines of name and pins the count to the bottom of
 * them. Without that, a one-line tile and a two-line tile beside it put their
 * counts on different baselines and ended their stone bands at different
 * heights, so the row read as two cards that had been cut wrong — a 61px body
 * next to a 79px one, with the shorter card's white showing beneath its own
 * stone. Two lines is the reservation because that is what a category name
 * takes: "Magic: The Gathering" on a phone is two, and nothing in the taxonomy
 * is three.
 *
 * The height is arithmetic from the tokens above rather than a measured number,
 * so the phone step near the end of this file only has to restate the two type
 * sizes and the padding, and the height follows. Every term in the sum is a
 * token for that reason — including the 3px gap, which is the closest the name
 * and the count are ever allowed to get.
 *
 * `flex: 1 1 auto` is insurance rather than layout: with the name clamped, every
 * body in a row is already the same height, but if a card is ever stretched by
 * something taller beside it the stone grows to the card's own bottom edge
 * instead of leaving a white strip under it. */
.goblin-card {
	--goblin-cat-label-size: 1.02rem;
	--goblin-cat-label-lh: 1.25;
	/* Written out rather than inherited: the count used to take the root's 1.6
	 * line-height by accident, and a height calculated from a number nobody set
	 * is a height that moves when someone touches the body copy. Same value, now
	 * on purpose. */
	--goblin-cat-sub-size: 0.78rem;
	--goblin-cat-sub-lh: 1.6;
	--goblin-cat-body-pt: 13px;
	--goblin-cat-body-px: 15px;
	--goblin-cat-body-pb: 15px;
	--goblin-cat-body-gap: 3px;
}
.goblin-card__body {
	display: flex; flex-direction: column; gap: var(--goblin-cat-body-gap);
	flex: 1 1 auto;
	background: var(--goblin-stone);
	padding: var(--goblin-cat-body-pt) var(--goblin-cat-body-px) var(--goblin-cat-body-pb);
	min-height: calc(
		2 * var(--goblin-cat-label-lh) * var(--goblin-cat-label-size)
		+ var(--goblin-cat-sub-lh) * var(--goblin-cat-sub-size)
		+ var(--goblin-cat-body-pt) + var(--goblin-cat-body-pb) + var(--goblin-cat-body-gap)
	);
}
/* Two lines, then an ellipsis — the count the block above reserves room for. */
.goblin-card__label {
	display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
	font-family: var(--goblin-display);
	font-weight: 600;
	font-size: var(--goblin-cat-label-size); line-height: var(--goblin-cat-label-lh);
	letter-spacing: -0.012em;
}
/* Bottom of the block, whatever the name above did — one straight line of counts
 * across the row. */
.goblin-card__subtitle {
	display: block; margin-top: auto; color: var(--goblin-gray);
	font-family: var(--goblin-ui); font-weight: 500;
	font-size: var(--goblin-cat-sub-size); line-height: var(--goblin-cat-sub-lh);
}

/* ---------- Product cards ---------- */
/* `position: relative` is load bearing, not decoration: WooCommerce price HTML
 * contains a `.screen-reader-text` span, which is absolutely positioned. Without
 * a positioned ancestor inside the rail it anchors to `.goblin-rail`, escapes
 * the track's scroll clip at its static position (~3000px in) and stretches the
 * whole document to that width. Making the card the containing block keeps it in. */
/* No hover animation, deliberately — as on .goblin-card above, which used to be
 * the exception and no longer is. A rail is a row of these under a moving
 * pointer: crossing it used to set off a run of cards lifting and dropping one
 * after another, which is motion the reader did not ask for and which fights the
 * horizontal movement the row is actually about. The hover cue that is left is
 * the border going one step darker, applied instantly (there is no `transition`
 * here on purpose, so nothing animates). */
.goblin-product-card {
	/* The card's type scale, as numbers the text block's height is derived from —
	 * see .goblin-product-card__text. The mobile block near the end of this file
	 * re-declares the two sizes and the height follows on its own. */
	--goblin-card-title-size: 0.92rem;
	--goblin-card-title-lh: 1.35;
	/* The price is set at the title's size: it is the second thing read, not the
	 * first, so it does not outgrow the name — but it had been shrunk to buy width
	 * for a sale pair that printed the currency twice, and the old price no longer
	 * does. Written as the title's own token so the mobile step below moves both. */
	--goblin-card-price-size: var(--goblin-card-title-size);
	--goblin-card-price-lh: 1.3;
	/* One inset for the whole card body, because the price and the button beneath
	 * it have to start on the same vertical line — they were 11px and 14px on a
	 * phone, and a price three pixels adrift of its own button is the kind of thing
	 * you see before you can say what is wrong. */
	--goblin-card-pad-x: 14px;

	position: relative; display: flex; flex-direction: column; background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	overflow: hidden; box-shadow: var(--goblin-shadow);
}
.goblin-product-card:hover { border-color: var(--goblin-edge-dark); }
.goblin-product-card__link {
	display: flex; flex-direction: column; flex: 1 1 auto;
	text-decoration: none; color: var(--goblin-ink);
}
.goblin-product-card__media {
	position: relative; display: block; flex: 0 0 auto;
	aspect-ratio: 1 / 1; min-height: 0; overflow: hidden;
	background: #fff; border-bottom: 1px solid var(--goblin-edge);
}
.goblin-product-card__media img {
	position: absolute; inset: 0; display: block;
	width: 100%; height: 100%; padding: 14px;
	object-fit: contain;
}
/* ---------- The card's text block ----------
 * Title and price together in a box that is always tall enough for three lines
 * of title, with both of them at the *top* of it.
 *
 * Reserving the three lines is what makes every card on the site the same height
 * — the media above it is a square of the card's width, so a fixed text block
 * fixes the whole card.
 *
 * The two of them are pinned to opposite ends of it. The title is at the top,
 * directly under the image it names, so names start on one line across a row
 * whatever their length. The price is at the bottom, directly above the button,
 * so prices and buttons make two more straight lines across that row. A short
 * name leaves its slack in the middle, between the two, where it is the one place
 * on the card nothing has to line up.
 *
 * The height is arithmetic rather than a measured number, so changing the type
 * scale below moves it: three title lines, one price line, the 3px that is the
 * closest the two are ever allowed to get, and the padding.
 */
.goblin-product-card__text {
	display: flex; flex-direction: column;
	flex: 1 1 auto;
	padding: 12px var(--goblin-card-pad-x) 13px;
	min-height: calc(
		3 * var(--goblin-card-title-lh) * var(--goblin-card-title-size)
		+ var(--goblin-card-price-lh) * var(--goblin-card-price-size)
		+ 12px + 13px + 3px
	);
}
.goblin-product-card__title {
	/* Three lines, then an ellipsis — the count the block above reserves room for. */
	display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
	font-weight: 600;
	font-size: var(--goblin-card-title-size); line-height: var(--goblin-card-title-lh);
}
/* The price is the one number on the card, so it is set in the display face —
 * Geologica's figures are squarer and line up in a column better than Inter's.
 * It is set smaller than the title on purpose: the name is what the reader is
 * scanning for, and a price in bigger type than the thing it prices reads as a
 * discount sticker on every card in the row. */
.goblin-product-card__price {
	/* A flex row so the sale pair can be ordered and spaced. It also drops the
	 * whitespace Woo leaves between `<del>` and `<ins>` — whitespace-only text
	 * between flex items makes no item — so `gap` is the whole gap, rather than
	 * a margin plus a word space that together read as twice what was written. */
	display: flex; flex-wrap: wrap; align-items: baseline; gap: 5px;
	margin-top: auto; padding-top: 3px;
	font-family: var(--goblin-display); font-weight: 600;
	font-size: var(--goblin-card-price-size); line-height: var(--goblin-card-price-lh);
	color: var(--goblin-ink);
}
/* What you pay comes first; what it used to cost trails it. Woo prints them the
 * other way round, which puts the number that is *not* the price in the reading
 * position. `order` moves the boxes and leaves the document alone, which is what
 * we want here — both are `aria-hidden`, and the screen-reader spans Woo prints
 * beside them ("Original price was…", "Current price is…") stay in their
 * original, spoken order. */
.goblin-product-card__price ins {
	order: 1; color: var(--goblin-red); font-weight: 600; text-decoration: none;
}
.goblin-product-card__price del {
	order: 2;
	color: var(--goblin-gray); font-weight: 500;
	font-size: calc(var(--goblin-card-price-size) - 0.08rem);
}
/* The old price is a comparison, not an amount to act on, so it drops the
 * currency: "12.000 ден 13.500" says everything "12.000 ден 13.500 ден" does in a
 * card's width, and the width is what a two-column phone listing is short of. */
.goblin-product-card__price del .woocommerce-Price-currencySymbol { display: none; }
.goblin-product-card__price .amount { white-space: nowrap; }
/* Badges. The stack is what is positioned, not the badge — a product can wear
 * two at once (a discounted new arrival), and stacking two absolutely positioned
 * spans in the same corner means giving one of them a `top` that knows how tall
 * the other is. The column does that by existing.
 *
 * `align-items: flex-start` so each badge is as wide as its own word: stretched
 * to the column they would be as wide as the longest, and "New" padded out to the
 * width of "Sold out" reads as a button. */
.goblin-badges {
	position: absolute; top: 9px; left: 9px; z-index: 2;
	display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
	pointer-events: none;
}
.goblin-badge {
	padding: 3px 8px 4px; border-radius: 2px;
	font-family: var(--goblin-ui); font-size: 0.64rem; font-weight: 700;
	letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.5;
}
.goblin-badge--sale { background: var(--goblin-red); color: #fff; }
/* Ink, not red: sold out is not a warning and not an offer, it is a fact about
 * the thing — and the red is the discount's colour on this site, which is the one
 * meaning it must not borrow. */
.goblin-badge--sold-out { background: var(--goblin-ink); color: #fff; }
/* Gold is the shop's own accent, the hero CTA's colour, and the darkest ink the
 * theme owns sits on it legibly — which a white "New" on gold does not. */
.goblin-badge--new { background: var(--goblin-gold); color: #241a05; }

/* ---------- The card's cart control ----------
 * Part of every card, on the homepage rails as much as on the listings. It is a
 * sibling of the card's link, never inside it, so the card had to become a
 * column: link on top (growing, which is what keeps the row of cards a level
 * bottom edge), cart control beneath.
 *
 * One slot holding two controls that take turns: WooCommerce's add-to-cart button
 * until the product is in the cart, the stepper for as long as it is. They are
 * never both up, so the slot is sized once — `--goblin-card-control-h` is on both
 * of them, and a card neither grows nor reflows as the reader buys from it. That
 * is the whole reason for the shared slot: a rail you are shopping across must
 * not move under the pointer.
 *
 * The button is WooCommerce's own markup, so it is styled by where it sits
 * rather than by a class of ours. `a.button` and not `> a` on purpose: Woo's
 * sheet dresses `.woocommerce a.button` at two classes and one element, and a
 * shorter selector here would lose to it whatever the source order.
 */
.goblin-product-card__cart {
	--goblin-card-control-h: 34px;
	display: flex; align-items: stretch;
	padding: 0 var(--goblin-card-pad-x) 14px;
}

/* Both halves ship `hidden` at some point and `display: flex` beats the `hidden`
 * attribute's UA rule, so for each of them the attribute has to be said twice —
 * exactly as the rail's arrows do.
 *
 * The button's half is hidden by its `__add` wrapper and not by the button: a
 * listing's button is dressed by `.woocommerce ul.products li.product .button`,
 * four classes and two elements, which beats anything sane written against
 * `a.button` here — so `[hidden]` on the button held on the homepage and lost on
 * every category page. The wrapper is a class of ours that Woo has never styled,
 * so it simply wins. */
.goblin-product-card__add {
	display: flex; flex: 1 1 auto; min-width: 0;
}
.goblin-product-card__add[hidden] { display: none; }
.goblin-qty {
	display: flex; align-items: stretch; justify-content: space-between;
	flex: 1 1 auto; min-height: var(--goblin-card-control-h);
	background: #fff; overflow: hidden;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
.goblin-qty[hidden] { display: none; }
.goblin-qty__step {
	flex: 0 0 auto; width: 34px; padding: 0; border: 0; background: transparent;
	font-family: var(--goblin-ui); font-size: 0.95rem; line-height: 1;
	color: var(--goblin-ink); cursor: pointer;
}
.goblin-qty__step:hover:not(:disabled) { background: var(--goblin-stone); }
.goblin-qty__step:disabled { opacity: 0.3; cursor: default; }
/* The figures are the display face for the same reason the price is. */
.goblin-qty__input {
	flex: 1 1 auto; width: auto; min-width: 0;
	padding: 0; border: 0; background: transparent;
	font-family: var(--goblin-display); font-size: 0.88rem; font-weight: 600;
	color: var(--goblin-ink); text-align: center;
	appearance: textfield; -moz-appearance: textfield;
}
.goblin-qty__input::-webkit-outer-spin-button,
.goblin-qty__input::-webkit-inner-spin-button { appearance: none; -webkit-appearance: none; margin: 0; }

/* The same gold as the hero's CTA, at the size a card can carry. `min-width: 0`
 * lets a long label — "Додај во кошница" is two words wider than "Add to cart" —
 * wrap inside the button rather than push the card wider. */
.goblin-product-card__add > a.button {
	flex: 1 1 auto; min-width: 0;
	align-items: center; justify-content: center; text-align: center;
	min-height: var(--goblin-card-control-h); padding: 6px 10px;
	border: 0; border-radius: var(--goblin-radius);
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.76rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-decoration: none;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
/* The two properties Woo's listing rule reaches this button with, taken back by
 * weight. `.woocommerce ul.products li.product .button` is four classes and two
 * elements; nothing legible written from `.goblin-product-card__add` gets past
 * that, and the alternative — padding a selector out with repeated classes until
 * the arithmetic works — is a puzzle for whoever reads it next. Both properties
 * are ones the card has to decide for itself: the `margin-top: 1em` pushes the
 * button out of a slot that is sized to hold it, and the `display` decides
 * whether the label centres. Everything else Woo sets here the card is happy to
 * take. */
.goblin-product-card__add > a.button {
	margin: 0 !important;
	display: flex !important;
}
.goblin-product-card__add > a.button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}
/* Woo's two states, in this theme's terms. Both of its own ::after glyphs are
 * set in the WooCommerce icon font and positioned against its padding, so they
 * are replaced rather than inherited: a tick that stays after the add is the
 * confirmation this card gets, since the "View cart" link is suppressed below
 * and the header's tally is across the page. */
.goblin-product-card__add > a.button.loading {
	opacity: 0.55; padding-right: 10px; pointer-events: none;
}
.goblin-product-card__add > a.button.loading::after { content: none; }
.goblin-product-card__add > a.button.added::after {
	content: "\2713"; font-family: var(--goblin-ui); margin-left: 0.5em; vertical-align: baseline;
}
/* Woo appends a "View cart" link after the button unless it finds one of these
 * already there; goblin_render_add_to_cart() prints an empty one so it never
 * does. `display: none` and not just `hidden`, because Woo's own sheet sets
 * `.added_to_cart { display: inline-block }` — and because it also takes the
 * link out of the tab order in the case where some future Woo appends one anyway. */
.goblin-product-card__add .added_to_cart { display: none; }

/* This used to stack the stepper over the button below the three-column
 * breakpoint, because a two-cards-wide listing could not hold them side by side —
 * the button was left with about 50px and "Додај во кошница" ran out of it. The
 * shared slot retired that: only one of them is ever up, and it is full width at
 * every size, so the narrow card has the same room the wide one does. */

/* ---------- The wishlist heart ----------
 * The same control twice: an icon in the card's top-right corner, and an icon
 * with its name beside it under a product's price (inc/wishlist.php).
 *
 * Top-*right* because the badges are top-left and the two must never argue over
 * a corner — a sold-out product on sale already stacks two badges down the left,
 * and this is the one thing on the card the reader can press without leaving the
 * page they are on.
 *
 * The outline and the fill are one path (goblin_icon('heart')). `fill` is a CSS
 * property here beating the SVG's own `fill="none"` presentation attribute, which
 * is what lets the pressed state be a fill rather than a second icon. */
.goblin-wish { margin: 0; }
.goblin-wish__btn {
	display: inline-flex; align-items: center; gap: 9px;
	background: none; border: 0; padding: 0;
	color: var(--goblin-ink); cursor: pointer;
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 600;
	transition: color 0.15s ease;
}
.goblin-wish__btn svg { width: 22px; height: 22px; flex: 0 0 auto; fill: none; }
.goblin-wish__btn:hover { color: var(--goblin-red); }
/* Pressed: the heart fills and stays red, whatever the pointer is doing. It is
 * a state, so it does not depend on hover to be visible. */
.goblin-wish__btn[aria-pressed="true"] { color: var(--goblin-red); }
.goblin-wish__btn[aria-pressed="true"] svg { fill: currentColor; }
.goblin-wish__btn:disabled { opacity: 0.55; cursor: default; }
/* The button under the price sits on the same left edge as everything else in the
 * summary, with the buy control's own gap above it. */
.woocommerce div.product .summary .goblin-wish { margin-top: 14px; }

/* ---------- The heart on a card ----------
 * Absolute over the media, so it takes no row of its own and the card's height is
 * still the image plus the text block plus the cart row.
 *
 * A white disc under it, not a bare glyph: the media is a product shot on white
 * and the heart would be an outline floating on it, but the shots are not *all*
 * white — a dark box art would swallow an ink outline entirely. The disc is what
 * makes the control legible on every one of nine thousand photographs.
 *
 * `pointer-events` is given back explicitly. The badge stack above sets
 * `pointer-events: none` on its own wrapper, not on anything here, but this sits
 * in the same corner region of a card whose link covers the whole face — and the
 * form is a sibling of that link, so it has to be clickable in its own right. */
.goblin-wish--compact {
	position: absolute; top: 7px; right: 7px; z-index: 3;
	pointer-events: auto;
}
.goblin-wish--compact .goblin-wish__btn {
	width: 32px; height: 32px; padding: 0;
	align-items: center; justify-content: center; gap: 0;
	background: rgba(255, 255, 255, 0.92);
	border: 1px solid var(--goblin-edge); border-radius: 50%;
	box-shadow: var(--goblin-shadow);
}
.goblin-wish--compact .goblin-wish__btn svg { width: 17px; height: 17px; }
.goblin-wish--compact .goblin-wish__btn:hover { background: #fff; border-color: var(--goblin-red); }
/* Icon only — the name is still in the accessible tree, and is what the button is
 * announced as. `clip-path` rather than `display: none`, which would take it out
 * of that tree and leave the button nameless. */
.goblin-wish--compact .goblin-wish__label {
	position: absolute; width: 1px; height: 1px; overflow: hidden;
	clip-path: inset(50%); white-space: nowrap;
}

/* ---------- The wishlist page ----------
 * The listing grid, unchanged — see the [goblin_wishlist] shortcode. Only the
 * empty state is its own thing. */
.goblin-wishlist-empty {
	padding: clamp(28px, 2rem + 3vw, 60px) 0;
	text-align: center;
}
.goblin-wishlist-empty p { margin: 0 0 6px; color: var(--goblin-ink-soft); }
.goblin-wishlist-empty p + p { margin-bottom: 22px; }

/* ---------- Product listings ----------
 * Shop, category and tag archives, product search, related products, up-sells,
 * cross-sells, [products]: all of them are Woo's <ul> full of <li>s, and every
 * one of those <li>s is now the card above — see woocommerce/content-product.php.
 * The row of them is a grid here rather than Woo's float grid.
 *
 * woocommerce/loop-start.php drops Woo's `columns-N` class from the <ul>, which
 * is what makes this a handful of rules instead of a specificity fight: every
 * float rule in woocommerce-layout.css and woocommerce-smallscreen.css that
 * would otherwise reimpose a two- or four-column float grid is written against
 * `[class*="columns-"]`, and none of them match any more. The column count is
 * this file's to set, and it steps at the same widths the rest of the theme does.
 *
 * Woo's stylesheets stay enqueued, and by now they dress almost nothing: the
 * cart, the checkout and the account pages have all been restyled since this was
 * written, and each of those three dequeues `woocommerce-smallscreen` on its own
 * page. What is left to the plugin is `order-pay` and `order-received` (issue
 * #7) and the odd control nothing has needed yet.
 */
.goblin-products {
	display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--goblin-gap);
	margin: 0 0 clamp(24px, 1rem + 2vw, 44px); padding: 0;
	list-style: none;
}
/* Woo's two clearfix boxes are grid items here, and each takes a cell — left in,
 * they push the first card of the listing into the second column. Killed at the
 * specificity Woo sets them with (`.woocommerce ul.products::before`, two classes
 * and two elements) rather than the one this class alone would give, which loses
 * to it whatever the source order. The bare pair is for the search page, where
 * the grid is a <div> outside any `.woocommerce` wrapper. */
.goblin-products::before,
.goblin-products::after,
.woocommerce ul.goblin-products::before,
.woocommerce ul.goblin-products::after,
.woocommerce-page ul.goblin-products::before,
.woocommerce-page ul.goblin-products::after { content: none; }
/* Above two-across the column count is not stepped at breakpoints any more — it
 * is whatever fits at a readable card width, which is the thing the steps were
 * really approximating. 205px is that width, and it is not a new number: the old
 * three-column rule drew a 208px card at exactly 700px, the narrowest card this
 * theme has ever put on a listing, and the floor is set just under it so that
 * this rule still fits three columns there rather than dropping to two over a
 * couple of pixels. From 700 it simply keeps fitting more as the page widens,
 * ending at five, because the container stops at 1280 and a sixth column would
 * need 1330.
 *
 * What it replaces was three fixed steps whose *maximum* nobody had looked at.
 * A card only ever hit its readable minimum at the bottom of each band and grew
 * from there: 315px at 1015px wide, 341px at 1440. That was invisible while the
 * category sidenav was taking ~300px off the left of every listing — the sidebar
 * was doing the job a measure should have been doing (see inc/setup.php), and
 * removing it left the listing dividing the whole container by four.
 *
 * Now the card runs between 205px and about 273px everywhere from a tablet up,
 * and lands on 240px on any monitor 1312px or wider — which is to say, on
 * essentially every desktop. At 240px the card is 212px of text inside its 14px
 * insets, about 26 characters a line at the 0.92rem title, so the three lines
 * the block reserves still hold a real product name; the one name in a 24-card
 * page that clips at 240px clipped at 341px too.
 *
 * `auto-fill` and NOT `auto-fit`: they differ only when the row is short of
 * items, and that is exactly the case that matters here. auto-fit collapses the
 * empty tracks and lets `1fr` stretch what is left, so a category holding two
 * products would draw them 640px wide. auto-fill keeps the empty tracks, so a
 * short row is card-sized cards packed at the left, like every other row. */
@media (min-width: 700px) {
	.goblin-products { grid-template-columns: repeat(auto-fill, minmax(205px, 1fr)); }
}

/* Undo what woocommerce-layout.css says about a loop item, and let the card fill
 * the cell so a row of them shares one height. */
.woocommerce ul.products li.product,
.woocommerce-page ul.products li.product {
	float: none; clear: none; width: auto; margin: 0; padding: 0;
	display: flex;
}
/* Both cards, because a listing holds both: `li.product` above is also what
 * wc_get_product_cat_class() puts on a category tile, so the shop page's
 * categories are flex items on the same terms as its products. */
.goblin-products > li.product > .goblin-product-card,
.goblin-products > li.product > .goblin-card { flex: 1 1 auto; }

/* ---------- Pagination ----------
 * The theme had never styled this, so what shipped was WooCommerce's own default:
 * 26x32px hairline boxes, the numbers in the theme's red because they are links,
 * and the current page in Woo's lilac (#e9e6ed on #816f98) — a colour from no
 * palette this site owns. Worse, the boxes were transparent, so the ground's
 * line-art pattern ran straight through the one control on the page that says
 * where you are in 106 products.
 *
 * They are tiles now, and deliberately the same tile as `.goblin-rail__nav`: a
 * white plate, one hairline border, the shared radius and the card shadow, going
 * gold under the pointer. That is already this site's vocabulary for "a control
 * that moves you through a list", and a pager is that control — it just happens
 * to be the one at the bottom of a listing rather than the one at the edge of a
 * row. Bigger than the rail's 38px, at 44, because these are the end of the page
 * rather than an overlay on it, and 44 is the touch target a phone wants.
 *
 * Two markups, one appearance. WooCommerce prints `ul.page-numbers > li > a`;
 * core's the_posts_pagination() — which index.php and search.php call — prints
 * `.nav-links > a` with no list at all. Both are selected below, so a search
 * result page and a category page paginate identically.
 *
 * The selectors carry `.woocommerce nav.woocommerce-pagination` in full because
 * Woo's own are that long: its `ul li span.current` rule is three classes and
 * four elements, and anything shorter here loses to it no matter the load order.
 * Its `<ul>` border, its per-`<li>` divider rules and its floats are all undone
 * rather than worked around — the row is a flex line with a real gap now, which
 * is where the space between the tiles comes from.
 */
.woocommerce nav.woocommerce-pagination ul.page-numbers,
.woocommerce-page nav.woocommerce-pagination ul.page-numbers,
nav.woocommerce-pagination ul.page-numbers,
.navigation.pagination .nav-links {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
	gap: 10px;
	margin: 0; padding: 0; border: 0;
	list-style: none;
	white-space: normal;
}
.woocommerce nav.woocommerce-pagination,
.woocommerce-page nav.woocommerce-pagination,
nav.woocommerce-pagination,
.navigation.pagination {
	margin-block: clamp(8px, 0.5rem + 1vw, 20px) clamp(28px, 1.5rem + 2vw, 52px);
	text-align: center;
}
/* Woo floats its list items and hangs a divider off each one. Neither survives a
 * flex row: the floats do nothing and the dividers double the gap on one side.
 * The `<li>`'s own `display` is deliberately not set — it is a flex item of the
 * row above, and the tile inside it is sized by the rule below, so whatever Woo
 * says the li is has no effect on the result. */
.woocommerce nav.woocommerce-pagination ul li,
.woocommerce-page nav.woocommerce-pagination ul li,
nav.woocommerce-pagination ul li {
	float: none; margin: 0; padding: 0;
	border: 0; overflow: visible;
}

/* The tile. `span` as well as `a` so the current page and the disabled ends are
 * the same object as the links they sit between — only their colours differ. */
.woocommerce nav.woocommerce-pagination ul li a.page-numbers,
.woocommerce nav.woocommerce-pagination ul li span.page-numbers,
.woocommerce-page nav.woocommerce-pagination ul li a.page-numbers,
.woocommerce-page nav.woocommerce-pagination ul li span.page-numbers,
nav.woocommerce-pagination ul li a.page-numbers,
nav.woocommerce-pagination ul li span.page-numbers,
.navigation.pagination .nav-links a.page-numbers,
.navigation.pagination .nav-links span.page-numbers {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 44px; height: 44px; padding: 0 12px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-display); font-size: 0.95rem; font-weight: 600;
	line-height: 1; color: var(--goblin-ink); text-decoration: none;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.woocommerce nav.woocommerce-pagination ul li a.page-numbers:hover,
.woocommerce nav.woocommerce-pagination ul li a.page-numbers:focus-visible,
.woocommerce-page nav.woocommerce-pagination ul li a.page-numbers:hover,
.woocommerce-page nav.woocommerce-pagination ul li a.page-numbers:focus-visible,
nav.woocommerce-pagination ul li a.page-numbers:hover,
nav.woocommerce-pagination ul li a.page-numbers:focus-visible,
.navigation.pagination .nav-links a.page-numbers:hover,
.navigation.pagination .nav-links a.page-numbers:focus-visible {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}
/* Where you are: the filled tile, so the row reads at a glance instead of asking
 * the reader to find the one number that is not a link. */
.woocommerce nav.woocommerce-pagination ul li span.page-numbers.current,
.woocommerce nav.woocommerce-pagination ul li a.page-numbers.current,
.woocommerce-page nav.woocommerce-pagination ul li span.page-numbers.current,
.woocommerce-page nav.woocommerce-pagination ul li a.page-numbers.current,
nav.woocommerce-pagination ul li span.page-numbers.current,
.navigation.pagination .nav-links span.page-numbers.current {
	background: var(--goblin-ink); border-color: var(--goblin-ink); color: #fff;
	box-shadow: none;
}
/* The gap marker is not a destination, so it is not a tile — just the ellipsis. */
.woocommerce nav.woocommerce-pagination ul li span.page-numbers.dots,
.woocommerce-page nav.woocommerce-pagination ul li span.page-numbers.dots,
nav.woocommerce-pagination ul li span.page-numbers.dots,
.navigation.pagination .nav-links span.page-numbers.dots {
	min-width: 0; padding: 0 2px;
	background: none; border: 0; box-shadow: none;
	color: var(--goblin-gray);
}
/* The arrows are square, like the numbers beside them. Their label is an arrow in
 * both markups now (goblin_pagination_arrows(), inc/helpers.php) with the name
 * behind it in a clipped span, so there is no word to make room for — dropping
 * the inline padding lets the shared min-width decide the tile and the row comes
 * out even. The UI face rather than the display one because `←` is a glyph, not
 * a figure, and Geologica draws it noticeably wider. */
.woocommerce nav.woocommerce-pagination ul li a.prev.page-numbers,
.woocommerce nav.woocommerce-pagination ul li a.next.page-numbers,
.woocommerce-page nav.woocommerce-pagination ul li a.prev.page-numbers,
.woocommerce-page nav.woocommerce-pagination ul li a.next.page-numbers,
nav.woocommerce-pagination ul li a.prev.page-numbers,
nav.woocommerce-pagination ul li a.next.page-numbers,
.navigation.pagination .nav-links a.prev.page-numbers,
.navigation.pagination .nav-links a.next.page-numbers {
	padding-inline: 0;
	font-family: var(--goblin-ui); font-size: 1rem; font-weight: 700;
}

/* ---------- The pager on a phone ----------
 * inc/setup.php already cut WooCommerce's seventeen tiles to nine. Nine still
 * does not fit a 375px screen: at 44px and a 10px gap the row is 476px against
 * about 343px of usable width, so it wrapped to a second line.
 *
 * Two things bring it back to one row. The tile goes to 40px on a 8px gap —
 * still a thumb-sized target, just not the desktop's — and the two numbers
 * flanking the current page drop out, which is the cheapest thing to lose
 * because the arrows either side already go exactly there. What is left is
 * `← 1 … 8 … 48 →`: how to step, how to jump to either end, and where you are.
 *
 * The trim is conditional on the row actually being long, via `:has()` — a pager
 * with no eighth item is one whose pages all fit on the row anyway, and hiding a
 * neighbour there would print "1 2 3 5" with a hole in the middle rather than
 * saving a line. So a five-page category still shows all five.
 *
 * Both markups again, and they differ in shape here: Woo wraps each item in an
 * `<li>`, core's the_posts_pagination() makes them direct children of
 * `.nav-links`. Hence the two pairs — same rule, one counting list items and one
 * counting the links themselves.
 */
@media (max-width: 560px) {
	.woocommerce nav.woocommerce-pagination ul.page-numbers,
	.woocommerce-page nav.woocommerce-pagination ul.page-numbers,
	nav.woocommerce-pagination ul.page-numbers,
	.navigation.pagination .nav-links { gap: 8px; }

	.woocommerce nav.woocommerce-pagination ul li a.page-numbers,
	.woocommerce nav.woocommerce-pagination ul li span.page-numbers,
	.woocommerce-page nav.woocommerce-pagination ul li a.page-numbers,
	.woocommerce-page nav.woocommerce-pagination ul li span.page-numbers,
	nav.woocommerce-pagination ul li a.page-numbers,
	nav.woocommerce-pagination ul li span.page-numbers,
	.navigation.pagination .nav-links a.page-numbers,
	.navigation.pagination .nav-links span.page-numbers {
		min-width: 40px; height: 40px; padding: 0 9px;
	}

	/* The neighbours used to be dropped here on a row of eight items or more, to
	 * keep nine tiles on one phone line. It hid the wrong two: on page 3 of 9 the
	 * row became `< 1 [3] ... 9 >`, so 2 and 4 — the only pages most readers ever
	 * want from page 3 — were the ones with no link, while 1 and 9 kept theirs.
	 * The arrows still moved a page at a time, which is what made it look like a
	 * broken pager rather than a deliberate one.
	 *
	 * Nothing is hidden now. The row is already `flex-wrap: wrap`, so on a screen
	 * too narrow for one line it takes two, and every page stays reachable. */
}

/* ---------- Rail ----------
 * One reusable horizontal scroller: a row that never wraps and never shows a
 * scrollbar. Used by the product sliders (`--products`) and the category band
 * (`--nav`); print one with goblin_render_rail() (inc/helpers.php), behaviour in
 * initRail() (assets/js/goblin.js) — drag, trackpad, arrows, opt-in mouse wheel.
 *
 * With the scrollbar gone the affordances are the arrows and the edge fades, and
 * both are state-driven: the buttons ship `hidden` and JS reveals them only when
 * the row really overflows, `is-scrollable` / `is-start` / `is-end` fade the
 * edges. So a row that fits looks like plain content, with no dead controls.
 *
 * The track is a flex row. Do NOT use `grid-auto-flow: column` here: Chrome lets
 * the off-screen columns escape `overflow-x: auto`, which pushed the whole
 * document to ~2x the viewport width and broke every full-bleed band.
 */
.goblin-rail { position: relative; }
.goblin-rail__track {
	display: flex; flex-wrap: nowrap;
	overflow-x: auto; overflow-y: hidden;
	/* A sideways gesture that runs out of row must not turn into a page swipe. */
	overscroll-behavior-x: contain;
	scrollbar-width: none; -ms-overflow-style: none;
}
.goblin-rail__track::-webkit-scrollbar { width: 0; height: 0; }
/* While dragging: the row follows the pointer exactly — snapping off (it re-snaps
 * on release) and no text selection, which otherwise highlights half the row. */
.goblin-rail.is-dragging .goblin-rail__track {
	cursor: grabbing; scroll-snap-type: none; user-select: none;
}
.goblin-rail__nav {
	position: absolute; top: 50%; transform: translateY(-50%); z-index: 4;
	display: flex; align-items: center; justify-content: center;
	width: 38px; height: 38px; padding: 0 0 2px; cursor: pointer;
	border-radius: var(--goblin-radius); border: 1px solid var(--goblin-edge);
	background: #fff; box-shadow: var(--goblin-shadow);
	font-size: 1.25rem; line-height: 1; color: var(--goblin-ink);
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.goblin-rail__nav:hover:not(:disabled) {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}
/* A disabled button only ever appears on a rail that opted into
 * data-goblin-rail-arrows="persist"; everywhere else — every rail in the theme
 * today — initRail() hides the one with nowhere to go, so a row parked at its
 * left end shows a single arrow and a row that fits shows none. Kept because the
 * state belongs to the component, not to its current callers. */
.goblin-rail__nav:disabled { opacity: 0.32; cursor: default; }
.goblin-rail__nav--prev { left: 0; }
.goblin-rail__nav--next { right: 0; }
.goblin-rail__nav[hidden] { display: none; }

/* The scroll readout. Not a control — it takes no pointer events and carries
 * aria-hidden — just a hairline saying how much row there is and where in it we
 * are. Printed only where goblin_render_rail() was asked for one, and revealed
 * by initRail() once the row overflows. It is the only one of the affordances
 * that says how MUCH row there is; the arrows only say there is more. */
.goblin-rail__scrollbar {
	position: relative; overflow: hidden;
	width: min(240px, 55%); height: 3px; margin: 16px auto 0;
	border-radius: 2px; background: var(--goblin-edge);
	pointer-events: none;
}
.goblin-rail__scrollbar[hidden] { display: none; }
/* Width and offset are both set from JS as percentages of this track, so the bar
 * is exactly as wide a fraction of it as the visible slice is of the whole row. */
.goblin-rail__scrollbar-bar {
	display: block; width: 100%; height: 100%;
	border-radius: inherit; background: var(--goblin-ink-soft);
}

/* The way out of a twelve-card slice: the last thing in the row, so the reader
 * arrives at it by scrolling to the end rather than by hunting for a link above.
 * A button and a line of text on the bare band — NOT a card. It was one at first
 * and that was the mistake: a card-shaped thing in a row of cards reads as one
 * more product, and a blank one at that. With no panel around it the row simply
 * runs out and offers a way on, which is what it is. Its label therefore sits on
 * the tabletop artwork like the headings do, and takes the same paper halo. */
/* `flex: 0 0 auto` overrides the fixed card width every other child of the track
 * takes: sized like a card it left the button floating half a card-width from the
 * last product, as if a card were missing there. It is as wide as its own label
 * plus a gutter now, so it reads as the row running out.
 *
 * `scroll-snap-align: end` for the same reason: mandatory snapping on a narrow
 * last child would otherwise land on the previous card's start and scroll the
 * button back out of sight. Aligned to its end, the last snap position is the
 * row's own maximum scroll. */
.goblin-rail__more {
	flex: 0 0 auto; scroll-snap-align: end;
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	gap: 14px; padding-inline: clamp(0.9rem, 0.5rem + 1.4vw, 1.75rem);
	text-align: center; text-decoration: none; color: var(--goblin-ink);
}
.goblin-rail__more:hover { color: var(--goblin-ink); }
.goblin-rail__more-mark {
	display: flex; align-items: center; justify-content: center;
	width: 46px; height: 46px; border-radius: var(--goblin-radius);
	background: #fff; border: 1px solid var(--goblin-edge-dark);
	font-size: 1.4rem; line-height: 1;
	transition: background-color 0.16s ease, border-color 0.16s ease, color 0.16s ease;
}
.goblin-rail__more:hover .goblin-rail__more-mark {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}
.goblin-rail__more-label {
	font-family: var(--goblin-display); font-weight: 600; font-size: 1rem;
	line-height: 1.25; letter-spacing: -0.012em;
}
/* Edge fades: opt in by setting `--goblin-rail-fade` to whatever colour sits
 * behind the rail. Left unset they paint transparent-to-transparent, i.e.
 * nothing — better than a white smudge over the tabletop. */
.goblin-rail::before,
.goblin-rail::after {
	content: ""; position: absolute; top: 0; bottom: 0; z-index: 3;
	width: 3.25rem; pointer-events: none;
	opacity: 0; transition: opacity 0.15s ease;
}
.goblin-rail::before { left: 0; background: linear-gradient(90deg, var(--goblin-rail-fade, transparent) 40%, transparent); }
.goblin-rail::after { right: 0; background: linear-gradient(270deg, var(--goblin-rail-fade, transparent) 40%, transparent); }
.goblin-rail.is-scrollable:not(.is-start)::before,
.goblin-rail.is-scrollable:not(.is-end)::after { opacity: 1; }

/* Product sliders: fixed-width cards that snap, and the arrows pulled out past
 * the container edge so they sit clear of the cards' own borders. */
.goblin-rail--products .goblin-rail__track {
	gap: var(--goblin-gap);
	scroll-snap-type: x mandatory;
	padding-bottom: 6px;
}
.goblin-rail--products .goblin-rail__track > * {
	/* `position: relative` so absolutely positioned descendants stay clipped by the
	 * track — see the note on .goblin-product-card. */
	position: relative;
	flex: 0 0 clamp(160px, 44vw, 200px);
	min-width: 0; scroll-snap-align: start;
}
@media (min-width: 700px) {
	.goblin-rail--products .goblin-rail__track > * { flex-basis: 22%; min-width: 210px; }
}
/* Matched to the listing's five-column card at the same width, so a product is
 * the same size on the homepage as on the category page it links into. 19% of the
 * 1280px container is 243px against the grid's 240px — the three pixels are the
 * rail's gap arithmetic differing from the grid's, and are not worth a calc().
 * Five and a bit cards show, which is what the rail wants: the part card at the
 * right edge is the thing that says the row runs on. */
@media (min-width: 1280px) {
	.goblin-rail--products .goblin-rail__track > * { flex-basis: 19%; }
}
/* The arrows ride on the card's image, not on its middle: the card runs image →
 * title → price → cart row, so its centre is down in the type. A share of the
 * rail's height rather than a length because the image is a square of the card's
 * width, and that width is a clamp here and a percentage of the container above
 * 700px — one expression this rule could reuse does not exist. 26% keeps the
 * button inside the image from the narrowest phone (60% down it) to the widest
 * desktop (45%); it was 40% when the card ended at the price. The desktop end of
 * that range moved from 42% when the card narrowed to 243px: a shorter card is a
 * smaller image under an unchanged text block, so a fixed share of the card's
 * height lands further down it. The trend is towards the middle of the image, so
 * the fraction still has room. */
.goblin-rail--products .goblin-rail__nav { top: 26%; }
.goblin-rail--products .goblin-rail__nav--prev { left: -14px; }
.goblin-rail--products .goblin-rail__nav--next { right: -14px; }

/* ---------- Pages other than the homepage ----------
 * Nothing needed. Inner pages — archives, product pages, content pages, search,
 * 404 — sit straight on the page ground like the homepage's unbanded sections do.
 * They briefly carried an opaque white sheet here, back when the ground was a
 * tinted field and a category listing could not be read off it; with the ground
 * white and the pattern drawn on it in hairlines, that sheet only stripped the
 * site's character out of every page that is not the homepage. Reinstate it per
 * template if some future page really needs to interrupt the ground. */

/* ---------- Archive header ----------
 * Breadcrumb, title, result count and sort: four stacked rows of WordPress and
 * WooCommerce defaults that nothing in this theme had ever touched. On a 375px
 * phone they came to 201px — a quarter of the viewport spent before the first
 * product, with the trail on a deep category wrapping to two lines of 0.92rem
 * underlined links and a 32px title under it.
 *
 * Nothing here is a new idea; it is the block set at the size it is worth. The
 * trail is the smallest type on the page because it is the thing you read last,
 * the title is sized for a phone rather than left at the browser's 2em, and the
 * count and the sort share one row (the box for that is in inc/setup.php).
 */

/* A little air above the trail. The container opens flush against the header's
 * category band — the sidenav's flex row had the same 0px and nobody noticed
 * while a 300px sidebar was the first thing under it. With the block tightened
 * the breadcrumb now starts on the band's own bottom edge, which reads as the
 * two touching rather than as a tight layout. This is the only thing in this
 * section that adds height, and it adds the least that reads as deliberate. */
.goblin-shop { padding-top: clamp(12px, 0.5rem + 1vw, 20px); }

/* The trail, as a row of chips.
 *
 * It reads "Ravensburger › Ravensburger Сложувалки" and nothing else: the two
 * ends are gone, because neither says anything. "Home" is the wordmark two rows
 * above it, and the last crumb is the `<h1>` directly below it in bigger type —
 * a trail whose first and last items are already on the screen is spending a
 * line to repeat them. What is left is the only part that is a way *out* of
 * where you are, which is the whole job of a breadcrumb.
 *
 * They are hidden here rather than filtered out of the array in PHP so that the
 * page's BreadcrumbList JSON-LD keeps the full path — see the note in
 * inc/setup.php. `display: none` takes them out of the accessibility tree too,
 * so a screen reader gets the same trail the screen does; only the schema still
 * knows about Home.
 *
 * The chips answer the readability problem the plate was answering before, and
 * answer it better: an opaque box does not care what is drawn on the ground
 * behind it, and unlike one long plate it says which words are the links.
 *
 * They are the pagination tile at breadcrumb size — white, one hairline, the
 * shared radius, the card shadow, gold on hover — and deliberately not a heavier
 * thing of their own. A first pass drew them with 2px ink borders, square
 * corners and hard 2px offset shadows, which read as five loud objects above a
 * category name: the trail is the quietest thing in the header and was ending up
 * the noisiest. Same idea, one weight down. Reusing the pager's recipe is also
 * what keeps the two small navigation controls on a listing looking related.
 *
 * The row is flex rather than inline-block so a trail that wraps gets a real row
 * gap — inline-block chips on two lines have none, and the shadows would touch.
 *
 * Only the ROW gap is flexbox's, though. A `column-gap` put 7px in front of the
 * first chip, because the items it was spacing from are the hidden "Home" and its
 * chevron — measured, not guessed: the chip sat at x=87 in a container whose
 * content box starts at 80, and setting the gap to 0 moved it to 80. That is the
 * gap between two boxes that are not drawn, and it left the trail seven pixels
 * adrift of the title beneath it. So the horizontal spacing lives on the
 * separators' own margins instead, which disappear with them.
 */
.woocommerce nav.woocommerce-breadcrumb,
.woocommerce-page nav.woocommerce-breadcrumb,
nav.woocommerce-breadcrumb {
	display: flex; flex-wrap: wrap; align-items: center;
	row-gap: 7px; column-gap: 0;
	margin: 0 0 13px; padding: 0;
	background: none; border: 0;
	font-family: var(--goblin-ui); font-size: 0.72rem; line-height: 1.35;
	color: var(--goblin-ink);
}

/* The chip — and the site's only one of this kind, which is why two selectors
 * share the rule rather than two rules describing the same plate.
 *
 * `.goblin-tag` is the same chip in the product page's meta rows (SKU, categories,
 * tags — see woocommerce/single-product/meta.php). The trail over a product's
 * title and the categories under its buy box are pointing at the same terms, so
 * they are the same object; writing that twice is how they stop being.
 *
 * The two are separate class names all the same, because `.goblin-crumb` carries
 * the trail's trimming rules below (`:first-child`/`:last-child` are hidden), and
 * a meta row has no ends to drop. */
.goblin-crumb,
.goblin-tag {
	display: inline-block;
	padding: 3px 9px 4px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-weight: 600; letter-spacing: 0.01em;
	color: var(--goblin-ink); text-decoration: none;
}
.woocommerce nav.woocommerce-breadcrumb .goblin-crumb a,
.woocommerce-page nav.woocommerce-breadcrumb .goblin-crumb a,
nav.woocommerce-breadcrumb .goblin-crumb a {
	display: block; color: inherit; text-decoration: none;
}
.goblin-crumb:hover,
a.goblin-tag:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* The chevron between them. Not a chip — it is the join, not a destination. */
.goblin-crumb__sep {
	margin-inline: 7px;
	font-size: 0.8rem; font-weight: 600; line-height: 1;
	color: var(--goblin-gray);
}

/* The two ends, and the two chevrons they leave behind. `:nth-child(2)` is
 * always the chevron after "Home"; the one before the last crumb is found by
 * looking forward from it. */
.goblin-crumb:first-child,
.goblin-crumb:last-child,
.goblin-crumb__sep:nth-child(2),
.goblin-crumb__sep:has(+ .goblin-crumb:last-child) { display: none; }

/* A trail of two crumbs is Home plus the page you are on, so trimming it leaves
 * nothing — the shop page, and every top-level category. Five element children
 * is the first trail with a middle: crumb, chevron, crumb, chevron, crumb. Below
 * that the row goes away entirely rather than sitting there as an empty margin. */
.woocommerce nav.woocommerce-breadcrumb:not(:has(> :nth-child(5))),
.woocommerce-page nav.woocommerce-breadcrumb:not(:has(> :nth-child(5))),
nav.woocommerce-breadcrumb:not(:has(> :nth-child(5))) { display: none; }

/* The title. It had no size of its own — 32px was the browser's default `h1`,
 * which is a headline for a document, not a label for a listing. The clamp lands
 * at about 25px on a phone and 32px on a desktop, so the desktop keeps what it
 * had and only the phone gives anything back. */
.woocommerce-products-header { margin: 0; }
.woocommerce-products-header__title,
.woocommerce-products-header .page-title {
	margin: 0 0 12px;
	font-size: clamp(1.55rem, 1.2rem + 1.4vw, 2rem);
}

/* The term description, which had no rules of its own and so took the body's:
 * 1.6 line-height and weight 400, inside a `<p>` still carrying the UA's 1em
 * margins.
 *
 * Three things came out of that. The rows sat too far apart for what is at most
 * four lines of standfirst under a title — 1.6 is a setting for a column of body
 * copy, and this is a caption. The gap to the title was 16px rather than the 12
 * the title asks for, because the `<p>`'s top margin collapsed *through* the
 * wrapper and won. The type also reads lighter than it is — the colour is
 * already --goblin-ink, the same near-black the title uses, so there is nothing
 * darker to reach for; what greys it is weight 400 at 16px over a ground that is
 * line art at 0.35 opacity. It stays at 400 all the same: 500 does close the
 * strokes up, but it reads as a second bold under the title, which is the worse
 * of the two problems.
 *
 * The title's margin only tightens where a description follows it, so a bare
 * title keeps its 12px to the toolbar. The bottom margin moves onto the block
 * itself: zeroing the child's margin alone left the text sitting flush on the
 * toolbar plate. */
.woocommerce-products-header:has(.term-description) .page-title { margin-bottom: 6px; }
.term-description {
	margin-bottom: 16px;
	line-height: 1.3;
}
.term-description > :first-child { margin-top: 0; }
.term-description > :last-child { margin-bottom: 0; }

/* Count and sort on one row, in a box of their own. Woo floats the first and
 * stacks them below 768px; both are undone here at the specificity Woo sets them
 * with.
 *
 * The box is the fix for the other half of the problem: `--goblin-gray` is
 * 4.75:1 on white, which passes on paper and does not survive this page, because
 * the ground is not white — it is line art at 0.35 opacity, and grey type on it
 * sits in the drawing rather than on top of it. So the row gets an opaque stone
 * plate with a hairline, the same plate the category tile's body uses, and the
 * type on it goes to --goblin-ink-soft: 8.07:1, on a surface that is actually the
 * colour the ratio was computed against. The breadcrumb above takes the same
 * darker ink but no plate — a trail that wraps to two lines is a ragged shape to
 * put a box around, and at 9.14:1 on the ground it does not need one.
 *
 * It costs about 14px of height against the 55px the block gave back.
 *
 * `nowrap` is the load-bearing word. A wrapping flex row moves an item to a
 * second line *before* it shrinks anything, so with `wrap` the two simply went
 * back to being the two stacked rows this box exists to prevent: 162px of count
 * and a 195px select do not both fit 343px of phone. Told not to wrap, the row
 * shrinks instead — and the two rules below decide which of them gives, because
 * left to itself flexbox squeezes both and wraps the count's text.
 *
 * The count does not give: it is a sentence, and a sentence at 95% of its width
 * is a sentence on two lines. The sort does, because a `<select>` is only ever
 * as wide as it needs to be for the option showing in it — it sized itself to
 * 195px for "Sort by price: low to high", which is a string the reader sees only
 * while the menu is open, and the menu is not what is being measured. */
/* `wrap` and not `nowrap`, since the filter bar moved in: the chip row is a
 * flex item with `flex-basis: 100%`, which is what puts it on a line of its own
 * under the controls without a second box to hold it. Nothing else in the row
 * wraps in practice — the select shrinks and the count is one short string. */
.goblin-shop-toolbar {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
	gap: 12px;
	margin: 0 0 16px; padding: 6px;
	background: var(--goblin-stone);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
/* The same box on the page a filter emptied, where there is no count and no sort
 * to put in it — only the chips and the bar, so that "no products were found"
 * still comes with the controls that caused it and the way back out. */
.goblin-shop-toolbar--empty { margin-bottom: 24px; }
/* Sort at the left end, count at the right — and by `order`, not by moving
 * anything. The count is a `role="status"` live region that WooCommerce prints
 * before the form, and a screen reader should still meet the result of the change
 * before the control that makes it. So the boxes swap and the document does not,
 * the same trade the product card's sale price makes.
 *
 * `space-between` is what puts them at opposite ends, and it costs nothing on a
 * narrow screen: with no free space left to distribute it behaves exactly as
 * flex-start does, and the select goes on shrinking as it did before. */
.woocommerce .goblin-shop-toolbar .woocommerce-ordering,
.woocommerce-page .goblin-shop-toolbar .woocommerce-ordering {
	float: none; margin: 0; order: 1;
	flex: 0 1 auto; min-width: 0;
}
/* `margin-left: auto` does what `space-between` is already doing while the sort
 * is beside it, and the one thing `space-between` cannot: hold the right end of
 * a line the count has wrapped onto alone, which is what the middle widths give
 * it now that the filters take the room they need. */
.woocommerce .goblin-shop-toolbar .woocommerce-result-count,
.woocommerce-page .goblin-shop-toolbar .woocommerce-result-count {
	float: none; margin: 0 0 0 auto; order: 2;
	flex: 0 0 auto; white-space: nowrap;
	font-family: var(--goblin-ui); font-size: 0.8rem; color: var(--goblin-ink-soft);
}
/* The select, in the theme's terms rather than the browser's: the pagination
 * tile's plate and hairline, with the chevron drawn as a background image
 * because `appearance: none` takes the native one away with the rest. */
/* One <select> on the storefront, and the variation picker in a product's buy box
 * is the other instance of it — same plate, same drawn chevron. It restates only
 * its own size below (a picker a thumb has to hit, not a sort control tucked into
 * a toolbar). */
.goblin-shop-toolbar .woocommerce-ordering select,
.goblin-buy table.variations select {
	appearance: none; -webkit-appearance: none;
	/* `width: 100%` and not `auto`: it makes the select take the width the flex row
	 * hands its wrapper rather than the width of its longest option, which is what
	 * lets the row shrink at all. The ellipsis is for the one case that overflows
	 * anyway — the longest option actually selected on the narrowest phone. */
	width: 100%; text-overflow: ellipsis;
	padding: 7px 30px 7px 11px;
	background-color: #fff;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236b747d' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
	background-repeat: no-repeat; background-position: right 9px center; background-size: 14px 14px;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	font-family: var(--goblin-ui); font-size: 0.8rem; line-height: 1.3;
	color: var(--goblin-ink); cursor: pointer;
}
.goblin-shop-toolbar .woocommerce-ordering select:hover,
.goblin-buy table.variations select:hover { border-color: var(--goblin-edge-dark); }
/* Below 360px one row stops being worth it. The count is rigid, so every pixel
 * the row is short comes out of the select, and by 320 it was showing "Sort b…"
 * — a control whose current value you cannot read is worse than a second line.
 * So at that width only, the two stack and the select takes the full width and
 * its whole label back. 360 rather than a rounder number because it is the
 * narrowest phone still sold; everything from an iPhone SE 2 up keeps one row. */
@media (max-width: 359px) {
	.goblin-shop-toolbar { flex-wrap: wrap; gap: 8px; }
	.woocommerce .goblin-shop-toolbar .woocommerce-ordering,
	.woocommerce-page .goblin-shop-toolbar .woocommerce-ordering {
		flex: 1 1 100%;
	}
}

/* ---------- Listing filters ----------
 *
 * The filter bar shares the toolbar with the sort control and the result count
 * (inc/archive-filters.php prints it between them). Layout is by `order`, the
 * same as the two that were there first: filters at the left, sort beside them,
 * count at the far right, and the chip row on its own line underneath.
 *
 * There is no sidebar here and there is not going to be one — CLAUDE.md records
 * why the category sidenav was taken out, and "ate a third of the listing width"
 * applies to a column of filter widgets exactly as it did to a column of links.
 * Facets a reader opens one at a time cost nothing until they are opened.
 *
 * Every button is a <summary> and every panel is the <details> it belongs to, so
 * the open/close state, the keyboard handling and the click target are the
 * browser's. goblin.js adds one thing on top: outside-click dismissal.
 *
 * All five facets are on the bar at every width. There is no second disclosure
 * over the top of them any more — the bar used to fold into one "Filters"
 * button below 900px, which then sat alone on a toolbar line with room for the
 * lot, because a flex item at `100%` takes the line whether it needs it or not.
 * The labels are short, so they wrap into one or two rows on a phone, and each
 * facet opens and closes without taking the other four away with it. */
/* The wrapping row. `relative` is the narrow layout's anchor — see the end of
 * this section, where the panels stop hanging off their own button and drop
 * under the whole row instead. */
.goblin-filters {
	order: 0; flex: 1 1 auto; min-width: 0; position: relative;
	display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}

/* One facet. `relative` is what the panel below is positioned against, so each
 * panel hangs off its own button rather than off the toolbar — down to 640px,
 * where the bar takes that job over. Flex column so `align-items` decides how
 * wide the <summary> inside is: it hugs its label, without that width being
 * written down. */
.goblin-filter {
	position: relative;
	display: flex; flex-direction: column; align-items: flex-start;
}
.goblin-filter__button {
	display: inline-flex; align-items: center; gap: 0.4rem;
	padding: 7px 11px;
	background: #fff; border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	font-family: var(--goblin-ui); font-size: 0.8rem; line-height: 1.3; color: var(--goblin-ink);
	text-decoration: none; cursor: pointer; list-style: none; white-space: nowrap;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}
.goblin-filter__button::-webkit-details-marker { display: none; }
.goblin-filter__button:hover { border-color: var(--goblin-edge-dark); }
/* The chevron the sort select draws as a background image, drawn here as a
 * rotated corner instead — the language switcher's, because this is the same
 * kind of control and the select's version cannot be flipped when it opens. */
.goblin-filter > .goblin-filter__button::after {
	content: ""; width: 0.36rem; height: 0.36rem; margin: -0.18rem 0 0 0.1rem;
	border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg); opacity: 0.55;
	transition: transform 0.15s ease;
}
.goblin-filter[open] > .goblin-filter__button { border-color: var(--goblin-edge-dark); }
.goblin-filter[open] > .goblin-filter__button::after { transform: rotate(-135deg); margin-top: 0.12rem; }

/* How many of this facet are on. Square-cornered and quiet: a count, not a
 * badge — the page has one radius and no pills anywhere else either. */
.goblin-filter__badge {
	min-width: 1.15rem; padding: 0 0.25rem; border-radius: 2px;
	background: var(--goblin-gold); color: #241a05;
	font-size: 0.68rem; font-weight: 700; line-height: 1.5; text-align: center;
}

/* The panel. `min()` rather than a flat max-height so it never grows taller than
 * the phone it is on; `overscroll-behavior` so scrolling to the bottom of 150
 * tags does not then start scrolling the listing behind it. */
.goblin-filter__panel {
	position: absolute; z-index: 40; top: calc(100% + 0.5rem); left: 0;
	min-width: 250px; max-height: min(340px, 60vh); overflow-y: auto;
	overscroll-behavior: contain;
	padding: 0.35rem;
	background: #fff; border: 1px solid var(--goblin-edge);
	border-radius: var(--goblin-radius); box-shadow: var(--goblin-shadow);
}
.goblin-filter__panel--wide { min-width: 300px; }

.goblin-filter__list { margin: 0; padding: 0; list-style: none; }
.goblin-filter__option {
	display: flex; align-items: center; gap: 0.5rem;
	padding: 0.32rem 0.45rem; border-radius: 2px;
	font-family: var(--goblin-ui); font-size: 0.8rem; line-height: 1.35;
	color: var(--goblin-ink); text-decoration: none;
}
.goblin-filter__option:hover { background: var(--goblin-stone); }
.goblin-filter__name { flex: 1 1 auto; min-width: 0; }
.goblin-filter__count { flex: 0 0 auto; font-size: 0.7rem; color: var(--goblin-gray); font-variant-numeric: tabular-nums; }

/* The box is drawn rather than being a real checkbox, because the control is a
 * link: the state lives in the URL, and `aria-pressed` is what says so out loud.
 * Gold when set, the same accent the account nav marks the page you are on
 * with. */
.goblin-filter__check {
	position: relative; flex: 0 0 auto; width: 14px; height: 14px;
	background: #fff; border: 1px solid var(--goblin-edge-dark); border-radius: 2px;
}
[aria-current="true"] > .goblin-filter__check {
	background: var(--goblin-gold); border-color: var(--goblin-gold);
}
[aria-current="true"] > .goblin-filter__check::after {
	content: ""; position: absolute; left: 4px; top: 0; width: 4px; height: 8px;
	border-right: 2px solid #241a05; border-bottom: 2px solid #241a05;
	transform: rotate(45deg);
}

/* In stock and On sale are one option each, so they are the option itself rather
 * than a button that opens a panel holding one. Same plate as the others, and a
 * gold edge when set so a bar with something on reads as such at a glance. */
.goblin-filter__button--toggle[aria-current="true"] {
	background: var(--goblin-stone); border-color: var(--goblin-gold);
}

/* The tag type-ahead. `hidden` in the markup and revealed by goblin.js, because
 * with scripting off it would be a box that does nothing. */
.goblin-filter__search { position: sticky; top: 0; z-index: 1; padding-bottom: 0.35rem; background: #fff; }
.goblin-filter__search-input {
	width: 100%; padding: 6px 9px;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	font-family: var(--goblin-ui); font-size: 0.8rem; color: var(--goblin-ink);
}
.goblin-filter__search-input:focus { outline: none; border-color: var(--goblin-edge-dark); }
.goblin-filter__empty { margin: 0.5rem 0.45rem; font-family: var(--goblin-ui); font-size: 0.78rem; color: var(--goblin-gray); }

/* Price: two numbers and a button on one line, as a grid and not as a wrapping
 * flex row. Both lay the three out identically; only one of them measures right
 * inside a <details>. A wrapping flex container asked for its intrinsic height —
 * which is what the open panel's parent asks for — answers with the height of
 * the layout it would have if it wrapped, so the facet reserved a phantom 38px
 * under the panel on every phone. Three columns cannot wrap, so there is no
 * second answer to give. */
.goblin-filter__price {
	display: grid; grid-template-columns: 1fr 1fr auto; align-items: end;
	gap: 0.5rem; padding: 0.15rem;
}
.goblin-filter__price-field { display: grid; gap: 0.25rem; min-width: 0; }
.goblin-filter__price-field > span {
	font-family: var(--goblin-ui); font-size: 0.68rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; color: var(--goblin-gray);
}
.goblin-filter__price-field input {
	width: 100%; padding: 6px 8px;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	font-family: var(--goblin-ui); font-size: 0.8rem; color: var(--goblin-ink);
}
.goblin-filter__apply {
	flex: 0 0 auto; padding: 7px 12px;
	background: var(--goblin-ink); color: #fff;
	border: 1px solid var(--goblin-ink); border-radius: var(--goblin-radius);
	font-family: var(--goblin-ui); font-size: 0.72rem; font-weight: 700;
	letter-spacing: 0.1em; text-transform: uppercase; cursor: pointer;
}
.goblin-filter__apply:hover { background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05; }

/* What is on, and how to take it off. Last in the row and first in the document
 * — see the toolbar's ordering note above for why those are not the same. */
.goblin-filters__active {
	order: 3; flex: 1 1 100%;
	display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem;
	padding-top: 2px;
}
.goblin-filters__active-label {
	font-family: var(--goblin-ui); font-size: 0.68rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; color: var(--goblin-gray);
}
.goblin-chip--remove {
	display: inline-flex; align-items: center; gap: 0.35rem;
	background: #fff; font-size: 0.78rem;
}
.goblin-chip__x { font-size: 0.95rem; line-height: 1; color: var(--goblin-gray); }
.goblin-chip--remove:hover .goblin-chip__x { color: #241a05; }
.goblin-filters__reset {
	margin-left: 0.2rem;
	font-family: var(--goblin-ui); font-size: 0.68rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase;
	color: var(--goblin-gray); text-decoration: none;
}
.goblin-filters__reset:hover { color: var(--goblin-red); }

/* The buttons stay as they are on a narrow screen; the panels are what has to
 * give. A 250px panel hanging off the left edge of its own button is off the
 * side of the screen the moment that button is the second or third thing on a
 * wrapped row — so below 640px the panel is anchored to the bar rather than to
 * the button and spans it, which is why the facet gives up being the `relative`
 * one here and `.goblin-filters` takes over. The cost is that a panel opens
 * under the whole row instead of directly under the button that opened it; the
 * button keeps its darkened edge to say which one it belongs to.
 *
 * 640 and not the 900 the header's nav folds at: the five facets measure about
 * 495px together, so they go on fitting a row with the sort beside them well
 * past the width at which the nav runs out of room. */
@media (max-width: 640px) {
	.goblin-filters { flex: 1 1 100%; }
	.goblin-filter { position: static; }
	.goblin-filter__panel { left: 0; right: 0; min-width: 0; max-height: 50vh; }
	/* A list panel wants every pixel of that width; the price form does not —
	 * three controls given 580px are two number fields a quarter of a metre
	 * wide. It keeps the width it has on a desktop, where the panel's own
	 * `min-width` was setting it. */
	.goblin-filter__price { max-width: 320px; }
	/* Nothing in the toolbar shares a line with anything else at this width, so
	 * the 12px is doing no horizontal work and every bit of it is height: four
	 * stacked rows on a phone. 8px is the gap the facet buttons are already set
	 * in, which makes the whole box one block of controls at one rhythm rather
	 * than two spacings arguing. */
	.goblin-shop-toolbar { gap: 8px; }
	/* Stacked, the four rows want a different order from the one they take side
	 * by side. The chips go up under the buttons that made them — on a desktop
	 * they are a line under the whole bar, but here they would be separated from
	 * their own facets by the sort control — and the count drops to the bottom,
	 * directly above the grid it is counting. Order only; the document is
	 * untouched, so the `role="status"` count is still read before the controls
	 * that change it. */
	.goblin-filters__active { order: 1; }
	.woocommerce .goblin-shop-toolbar .woocommerce-ordering,
	.woocommerce-page .goblin-shop-toolbar .woocommerce-ordering { order: 2; }
	.woocommerce .goblin-shop-toolbar .woocommerce-result-count,
	.woocommerce-page .goblin-shop-toolbar .woocommerce-result-count { order: 3; }
}

/* The chip row's label goes, and only the label. Three chips and a Reset are
 * about 360px of the 330 a phone has; "Filtered by:" is another 123 and it is
 * the one piece of that row a reader does not need told — every chip carries a
 * × and says what it takes off. Clipped rather than `display: none`, so it is
 * still the context a screen reader meets before the chips, the same trade the
 * header's cart label makes at this width. 560 is where the label stops fitting
 * on the row with them. */
@media (max-width: 560px) {
	.goblin-filters__active-label {
		position: absolute; width: 1px; height: 1px;
		overflow: hidden; clip: rect(1px, 1px, 1px, 1px); white-space: nowrap;
	}
}

/* ---------- Archive extras ---------- */
.goblin-archive-banner { margin: 0 auto 1.5rem; border-radius: var(--goblin-radius); overflow: hidden; }
.goblin-archive-banner img { width: 100%; height: auto; display: block; }
.goblin-subcats { margin-block: 1rem 1.75rem; }
.goblin-publishers { margin-block: 0.75rem 1.5rem; display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem; }
.goblin-publishers__label {
	font-family: var(--goblin-ui); font-size: 0.72rem; font-weight: 700;
	letter-spacing: 0.16em; text-transform: uppercase; color: var(--goblin-gray);
}
.goblin-chip {
	display: inline-block; padding: 0.3rem 0.7rem; border-radius: var(--goblin-radius);
	background: var(--goblin-stone); border: 1px solid var(--goblin-edge);
	color: var(--goblin-ink);
	text-decoration: none; font-size: 0.85rem;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}
.goblin-chip:hover { background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05; }

/* ---------- The single product page ----------
 * Written mobile first — everything below is the phone, and the two `min-width`
 * blocks are the only places a wider screen is mentioned. The rest of this file
 * is the other way round (a desktop rule with a `max-width: 900px` block near the
 * end taking things back), which is worth knowing before adding to it: a rule
 * added here will not be undone down there.
 *
 * What ships in WooCommerce's own templates is a floated 48/48 pair, a lilac
 * add-to-cart button, a tab bar with one tab in it and a paragraph of red
 * underlined links. Almost nothing below is a new object: the button is the
 * card's, the chips are the breadcrumb's, the headings are the homepage's, the
 * plates are the archive toolbar's, and the rows of products at the bottom are
 * rails. See inc/single-product.php for the hooks that arrange them.
 */

/* Gallery and summary in one box (opened in inc/single-product.php), so the page
 * around them stays a plain stack. On a phone that box is one column and the
 * order is the document's: picture, name, price, what it is, buy, meta. */
.goblin-product__top {
	position: relative;
	display: grid;
	gap: clamp(18px, 1rem + 1.4vw, 30px);
	margin-bottom: clamp(8px, 0.5rem + 1vw, 20px);
}

/* Woo's layout sheet floats these two and gives each 48% — a width a grid item
 * still takes, unlike the float. Its selectors are two classes and two elements
 * (`.woocommerce-page div.product div.images`), so these have to be at least
 * that; the `> ` is not decoration, it is the extra element the arithmetic needs. */
.woocommerce div.product .goblin-product__top > .woocommerce-product-gallery,
.woocommerce div.product .goblin-product__top > .summary {
	float: none; width: auto; margin: 0;
}

@media (min-width: 860px) {
	.goblin-product__top {
		/* 46% rather than a half: product photographs here are 500px square, and a
		 * column much past 540 is upscaling them to fill space the summary can use
		 * better. The gallery's own max-width holds that on the widest screens. */
		grid-template-columns: minmax(0, 46%) minmax(0, 1fr);
		gap: clamp(28px, 1rem + 2.4vw, 48px);
		align-items: start;
	}
}

/* ---------- The gallery ----------
 * A white plate with a hairline and the card's shadow — the same frame the
 * product card puts around the same photograph on the listing the reader came
 * from. Without it the image sits straight on the ground pattern, which on a
 * product shot with a pale background has no edge at all. */
.woocommerce div.product .goblin-product__top > .woocommerce-product-gallery {
	position: relative;
	padding: 10px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	max-width: 540px;
}
.woocommerce div.product div.images .woocommerce-product-gallery__image img {
	/* A square slot whatever the file is, so a portrait photograph in a gallery of
	 * squares does not resize the whole top of the page when it is selected. */
	aspect-ratio: 1 / 1; object-fit: contain;
	width: 100%; height: auto;
}

/* The full-screen trigger, as a tile rather than Woo's black-on-white circle with
 * a 2px CSS magnifier drawn inside it. The glyph is a mask so it takes
 * `currentColor` and turns with the tile on hover; WordPress's emoji replacement
 * turns the button's own character into an <img>, which goes. */
.woocommerce div.product div.images .woocommerce-product-gallery__trigger {
	top: 16px; right: 16px;
	/* Woo ships `z-index: 99` on this, and the header is a sticky 50 — so scrolling
	 * a product page slid the tile up over the wordmark and the search field. It
	 * only ever needs to sit above the photograph beneath it. */
	z-index: 3;
	display: flex; align-items: center; justify-content: center;
	width: 38px; height: 38px; padding: 0;
	background: #fff; border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	color: var(--goblin-ink); text-indent: 0; font-size: 0;
}
.woocommerce div.product div.images .woocommerce-product-gallery__trigger::before,
.woocommerce div.product div.images .woocommerce-product-gallery__trigger img { display: none; }
.woocommerce div.product div.images .woocommerce-product-gallery__trigger::after {
	content: ""; position: static;
	width: 18px; height: 18px; background: currentColor; transform: none; border-radius: 0;
	-webkit-mask: var(--goblin-zoom-glyph) center / contain no-repeat;
	mask: var(--goblin-zoom-glyph) center / contain no-repeat;
}
.woocommerce div.product div.images .woocommerce-product-gallery__trigger:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* Thumbnails: a grid of small plates rather than Woo's four half-transparent
 * floats. `auto-fill` at 62px keeps them thumb-sized on a phone and stops a
 * gallery of two from drawing them a quarter of the frame wide. */
.woocommerce div.product div.images .flex-control-thumbs {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(62px, 1fr));
	gap: 8px; margin: 10px 0 0; padding: 0; overflow: visible;
}
.woocommerce div.product div.images .flex-control-thumbs li {
	width: auto; float: none; margin: 0;
}
.woocommerce div.product div.images .flex-control-thumbs li img {
	width: 100%; aspect-ratio: 1 / 1; object-fit: contain; padding: 4px;
	background: #fff; border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	/* Woo dims every thumbnail to 0.5 and lights the active one. A dimmed
	 * photograph reads as unavailable; the border says which one is up instead. */
	opacity: 1;
}
.woocommerce div.product div.images .flex-control-thumbs li img.flex-active,
.woocommerce div.product div.images .flex-control-thumbs li img:hover {
	opacity: 1; border-color: var(--goblin-gold);
}

/* The badges, over the gallery's top-left corner — the card's stack, in the
 * card's corner, and nothing here but where to put it. It is a child of
 * `.goblin-product__top` rather than of the gallery (the stack is printed before
 * the images, on the hook Woo's own flash used), and absolute takes it out of the
 * grid so it claims no track of its own. */
.woocommerce div.product .goblin-product__top > .goblin-badges {
	top: 10px; left: 10px; right: auto; z-index: 3;
}

/* ---------- The summary ---------- */
.woocommerce div.product .goblin-product__top > .summary { margin: 0; }

.woocommerce div.product .summary .product_title {
	margin: 0 0 10px;
	font-size: clamp(1.32rem, 1.05rem + 1.3vw, 1.9rem);
	line-height: 1.2; letter-spacing: -0.02em;
}

/* The price, in the card's terms: the display face, the near-black ink, what you
 * pay first and the struck-through old price after it. It had been WooCommerce's
 * #958e09 — an olive from no palette on this site, and the same colour Woo paints
 * its sale badge, so the one number on the page was announcing itself as a
 * discount on every product whether or not it was one.
 *
 * Bigger than the card's, because here it is the number the page is about rather
 * than the second thing read on a tile. Woo's own rules are two classes and two
 * elements; these are three and two. */
.woocommerce div.product .summary p.price,
.woocommerce div.product .summary span.price {
	display: flex; flex-wrap: wrap; align-items: baseline; gap: 9px;
	margin: 0 0 14px;
	font-family: var(--goblin-display); font-weight: 600;
	font-size: clamp(1.4rem, 1.15rem + 1.1vw, 1.9rem); line-height: 1.2;
	letter-spacing: -0.01em; color: var(--goblin-ink);
}
.woocommerce div.product .summary p.price ins,
.woocommerce div.product .summary span.price ins {
	order: 1; background: none; color: var(--goblin-red);
	font-weight: 600; text-decoration: none;
}
.woocommerce div.product .summary p.price del,
.woocommerce div.product .summary span.price del {
	order: 2; opacity: 1;
	color: var(--goblin-gray); font-weight: 500; font-size: 0.62em;
}
/* A comparison, not an amount to act on — same trade the card makes. */
.woocommerce div.product .summary p.price del .woocommerce-Price-currencySymbol,
.woocommerce div.product .summary span.price del .woocommerce-Price-currencySymbol { display: none; }
.woocommerce div.product .summary .price .amount { white-space: nowrap; }

/* The short description. Two things were wrong with it: it took the body's 1.6
 * line-height, which is a setting for a column of prose and not for a four-line
 * spec list, and it took the browser's 40px list indent — twice, on the one
 * product whose imported markup wraps the real list in another one, which put its
 * bullets 80px right of the price above them. */
.woocommerce-product-details__short-description {
	margin: 0 0 16px;
	font-size: 0.95rem; line-height: 1.45; color: var(--goblin-ink);
}
.woocommerce-product-details__short-description > :first-child { margin-top: 0; }
.woocommerce-product-details__short-description > :last-child { margin-bottom: 0; }
.woocommerce-product-details__short-description ul,
.woocommerce-product-details__short-description ol {
	margin: 0; padding-left: 1.15em;
}
.woocommerce-product-details__short-description li { margin: 0 0 3px; }
/* Imported markup sometimes wraps the real list in a one-item list and a pair of
 * <div>s (a CS-Cart export artefact; one product in 3,180 has it). A list item
 * holding a block is a wrapper and not a bullet, so it gets neither a marker nor
 * an indent and the list inside it starts where the outer one would have. Written
 * as a shape rather than as that product's class names, because the next
 * re-migration brings the same shape back under whatever names it likes. */
.woocommerce-product-details__short-description li:has(> div) { list-style: none; }
.woocommerce-product-details__short-description ul:has(> li:only-child > div) { padding-left: 0; }
/* And the list inside such a wrapper is the top-level list, so it takes the
 * top-level marker: the browser was drawing it a hollow `circle`, which is what
 * it draws for a genuine second level. */
.woocommerce-product-details__short-description li:has(> div) ul { list-style-type: disc; }

/* ---------- Add to cart ----------
 * The card's button and a link under it. No plate, no stock line, no readout of
 * what the cart holds — the summary is one column (name, price, what it is, buy)
 * and a box drawn round the last of those cuts it off from the price it belongs
 * with. What the reader gets back after pressing it is the tick the card gives
 * and the header's tally, which is where the cart is on every other page here. */
/* One column for the whole control: the button, the message under it and the cart
 * link all stop at the same place. Without it each found its own width — a 340px
 * button over a 650px message over a 110px link — and three left-aligned things
 * of three unrelated widths read as debris rather than as a block. 380 is about
 * as wide as a 48px-tall button can be before it reads as a banner rather than as
 * something to press; a phone is narrower than it and simply ignores it. */
.goblin-buy { max-width: 380px; margin: 0 0 20px; }

/* Out of stock only. WooCommerce's in-stock line is filtered away in
 * inc/single-product.php; this is the case where there is no button, so the row
 * has to say why. A dot and a word — Woo's own green (#77a464) is off this
 * palette and was carrying the whole message on its own. */
.woocommerce div.product .goblin-buy p.stock {
	display: flex; align-items: center; gap: 8px;
	margin: 0;
	font-size: 0.85rem; font-weight: 600; color: var(--goblin-red-ink);
}
.woocommerce div.product .goblin-buy p.stock::before {
	content: ""; flex: 0 0 auto;
	width: 8px; height: 8px; border-radius: 50%;
	background: var(--goblin-red);
}

/* Quantity beside the button, and the button taking whatever is left. Woo floats
 * them and clears the row with two `content: " "` pseudo-elements — which in a
 * flex row are two more items, so both have to go.
 *
 * Only a form whose quantity and button are its own children becomes the row. A
 * variable product's are inside `.woocommerce-variation-add-to-cart` and a
 * grouped product's are cells of a table, and making those forms flex containers
 * shrink-to-fits the wrapper the controls are actually in — a 253px picker in a
 * 423px box. Those two get the row put on the right element further down. */
.woocommerce div.product .goblin-buy form.cart { margin: 0; }
.woocommerce div.product .goblin-buy form.cart:not(.variations_form):not(.grouped_form) {
	display: flex; flex-wrap: wrap; align-items: stretch; gap: 10px;
}
.woocommerce div.product .goblin-buy form.cart::before,
.woocommerce div.product .goblin-buy form.cart::after { content: none; }
/* When a product can only be bought one at a time WooCommerce still prints the
 * quantity wrapper, with a `type="hidden"` input inside it. As a flex item that
 * is a 2px box plus the row's 10px gap, which left the button — the only thing on
 * the row — starting twelve pixels right of the title and the price above it.
 * A wrapper with nothing showing in it is not a column. */
.woocommerce div.product .goblin-buy .quantity:has(input.qty[type="hidden"]) { display: none; }
/* And hidden outright wherever initSingleCart() has taken the press over: there
 * the field is not a control any more, only what a reader with no JavaScript
 * posts and where Woo writes the chosen variation's own min and max.
 *
 * The one `!important` in this file, and it is not a specificity argument — it is
 * an inline-style argument, which specificity cannot win. Woo's variation script
 * calls jQuery `.show()` on this wrapper every time the picker resolves, and
 * jQuery shows an element by writing `display: block` onto its `style` attribute.
 * Author `!important` is the only thing that outranks that, short of fighting the
 * script for the attribute on every change. */
.woocommerce div.product .goblin-buy .quantity[hidden] { display: none !important; }
.woocommerce div.product .goblin-buy form.cart div.quantity {
	float: none; margin: 0;
	display: flex; align-items: stretch; flex: 0 0 auto;
	background: #fff; overflow: hidden;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
/* The stepper buttons are added by initSingleQty() in assets/js/goblin.js and
 * are the card's — same class, same 34px. Without JS the row is the plain number
 * input Woo prints, which still works. */
.woocommerce div.product .goblin-buy .quantity input.qty {
	width: 3rem; min-width: 0; height: auto; padding: 0;
	border: 0; background: transparent;
	font-family: var(--goblin-display); font-size: 0.95rem; font-weight: 600;
	color: var(--goblin-ink); text-align: center;
	appearance: textfield; -moz-appearance: textfield;
}
.woocommerce div.product .goblin-buy .quantity input.qty::-webkit-outer-spin-button,
.woocommerce div.product .goblin-buy .quantity input.qty::-webkit-inner-spin-button {
	appearance: none; -webkit-appearance: none; margin: 0;
}

/* The card's button, at the size the one control on a product page should be:
 * 48px tall against the card's 34, which is also the touch target a phone wants.
 * It is the card's in every other respect — same gold, same ink, same radius,
 * same hover — because it is the same button, and a reader who has been pressing
 * it across a listing should not have to learn a second one here.
 *
 * The only difference from the card is that it does not run the full width of
 * what holds it — `.goblin-buy` above caps that at 380px, because the summary
 * column is 650 and a button as wide as a paragraph reads as a banner rather than
 * as something to press.
 *
 * Woo dresses this button through `.woocommerce button.button.alt` — three
 * classes and one element — so the selector needs three classes of its own; the
 * three elements are what carry it past. */
.woocommerce div.product .goblin-buy form.cart button.single_add_to_cart_button,
.woocommerce div.product .goblin-buy .woocommerce-variation-add-to-cart button.single_add_to_cart_button {
	flex: 1 1 180px;
	display: flex; align-items: center; justify-content: center; text-align: center;
	min-height: 48px; padding: 12px 22px; margin: 0;
	border: 0; border-radius: var(--goblin-radius);
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.92rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em;
	cursor: pointer;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce div.product .goblin-buy button.single_add_to_cart_button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}
.woocommerce div.product .goblin-buy button.single_add_to_cart_button:disabled,
.woocommerce div.product .goblin-buy button.single_add_to_cart_button.loading {
	opacity: 0.55; pointer-events: none;
}
.woocommerce div.product .goblin-buy button.single_add_to_cart_button.loading::after { content: none; }
/* The card's tick, meaning what it means there: that press moved the cart. Only
 * a sold-individually product still shows it — everywhere else the button has
 * turned into the stepper by then, which says the same thing and says how many. */
.woocommerce div.product .goblin-buy button.single_add_to_cart_button.added::after {
	content: "\2713"; margin-left: 0.5em;
}
/* The button's half of the shared slot. `display: flex` above beats the `hidden`
 * attribute, so as with the card it is said twice — and once per wrapper, because
 * the variable product's selector up there carries a class the other does not and
 * a single rule here would lose to it. */
.woocommerce div.product .goblin-buy form.cart button.single_add_to_cart_button[hidden],
.woocommerce div.product .goblin-buy .woocommerce-variation-add-to-cart button.single_add_to_cart_button[hidden] {
	display: none;
}

/* The stepper's half: the card's stepper at the button's size, in the button's
 * place. It is the card's element and the card's rules — inserted before the
 * button by initSingleCart() so it lands in whichever wrapper this product type
 * put the button in — and all it needs here is the height the two share and a
 * `flex` that matches the button's, so nothing on the row moves as they swap.
 * The control height is the card's custom property because it is the card's
 * control; 48 is what a product page's one control is worth. */
.woocommerce div.product .goblin-buy .goblin-qty {
	--goblin-card-control-h: 48px;
	flex: 1 1 180px;
}
.woocommerce div.product .goblin-buy .goblin-qty__step { width: 44px; font-size: 1.05rem; }
.woocommerce div.product .goblin-buy .goblin-qty__input { font-size: 0.95rem; }

/* The link under it. A link and not a second button: there is one thing to press
 * on this page, and a bordered "View cart" beside the gold one made two. */
.goblin-buy__cart {
	display: inline-block; margin-top: 11px;
	font-size: 0.82rem; font-weight: 600; color: var(--goblin-ink-soft);
	text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px;
}
.goblin-buy__cart:hover { color: var(--goblin-gold-ink); text-decoration-color: currentColor; }

/* Where an add that could not happen is said — filled by initSingleCart() when
 * the cart clamps the quantity, in the same slot and the same shape WooCommerce's
 * own notices take directly beneath (see the notices block near the end of this
 * file). `display: block` beats the `hidden` attribute's UA rule, so the
 * attribute is said twice, as the card's two halves and the rail's arrows do. */
.goblin-buy__msg {
	display: block; margin: 12px 0 0; padding: 8px 11px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-left: 3px solid var(--goblin-red);
	border-radius: var(--goblin-radius);
	font-size: 0.82rem; line-height: 1.4; color: var(--goblin-red-ink);
}
.goblin-buy__msg[hidden] { display: none; }
/* Woo's own notices print directly under this box on a product page (the empty
 * wrapper it prints alongside them is hidden by the notices block further down),
 * and they take its column so the error lines up under the button that caused it
 * rather than running the width of the summary. */
.goblin-buy + .woocommerce-notices-wrapper { max-width: 380px; margin-top: 12px; }

/* ---------- The variation picker ----------
 * A variable product puts a two-column table of attribute pickers above the
 * button and moves the quantity and the button into a wrapper of its own, so the
 * flex row above never reaches them. Both are handled here.
 *
 * The table becomes a stack: WooCommerce sets the label as a right-aligned `<th>`
 * in a column of its own, which on a phone leaves an attribute name wrapping to
 * three lines beside a select that has half the width. Label over control is what
 * every other field on this page does. */
.woocommerce div.product .goblin-buy table.variations {
	display: block; width: 100%; margin: 0 0 14px; border: 0;
}
.woocommerce div.product .goblin-buy table.variations tbody,
.woocommerce div.product .goblin-buy table.variations tr,
.woocommerce div.product .goblin-buy table.variations th,
.woocommerce div.product .goblin-buy table.variations td {
	display: block; width: auto; padding: 0; border: 0; text-align: left;
}
.woocommerce div.product .goblin-buy table.variations th.label {
	margin-bottom: 5px;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; color: var(--goblin-ink-soft);
}
.woocommerce div.product .goblin-buy table.variations th.label label { margin: 0; font-weight: inherit; }
.woocommerce div.product .goblin-buy table.variations tr + tr { margin-top: 10px; }
.goblin-buy table.variations select {
	width: 100%; min-height: 44px; padding: 8px 34px 8px 12px; font-size: 0.9rem;
}
/* "Clear". WooCommerce keeps it in the flow and only turns its visibility off, so
 * the row it will occupy is reserved from the start and nothing jumps when a
 * variation is picked. Kept small so the reserved band is small. */
.goblin-buy .reset_variations {
	display: inline-block; margin-top: 6px;
	font-size: 0.76rem; line-height: 1.4; color: var(--goblin-ink-soft);
}
/* The picked variation's own price and stock line. */
.woocommerce div.product .goblin-buy .woocommerce-variation { margin: 0 0 12px; }
.woocommerce div.product .goblin-buy .woocommerce-variation:empty { margin: 0; }
.woocommerce div.product .goblin-buy .woocommerce-variation-price .price {
	margin: 0 0 6px; font-size: 1.15rem;
}
.woocommerce div.product .goblin-buy .woocommerce-variation-description p:last-child { margin-bottom: 0; }
/* Quantity and button, again — for a variable product they live in here rather
 * than as children of the form. */
.woocommerce div.product .goblin-buy .woocommerce-variation-add-to-cart {
	display: flex; flex-wrap: wrap; align-items: stretch; gap: 10px;
}
/* Both controls are 48px whichever wrapper they are in, so the row is level. */
.woocommerce div.product .goblin-buy .quantity { min-height: 48px; }

/* ---------- The meta rows ----------
 * One row per kind, each a small uppercase label and then its values as chips —
 * the breadcrumb's chips, which are pointing at these same terms two rows above
 * the title. See woocommerce/single-product/meta.php.
 *
 * The label is the only thing here that sits on the ground unaided, so it takes
 * --goblin-ink-soft (9.14:1) rather than --goblin-gray: everything else in the
 * row is an opaque plate and does not care what is drawn behind it. */
.goblin-meta {
	display: grid; gap: 13px;
	margin: 0; padding: 0; border: 0;
	font-size: 0.78rem;
}
.goblin-meta__row {
	display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
}
/* The label sits above its chips, not in front of them. On one line it was
 * competing with them for the row: a wrapping set of categories put the second
 * half under the label and left the three rows with no common left edge, and at
 * 0.66rem uppercase beside a 0.78rem chip it read as the first chip's prefix.
 * `flex-basis: 100%` breaks the row rather than a second element wrapping it, so
 * the chips still flow as one group underneath. */
.goblin-meta__label {
	flex: 0 0 100%; margin-bottom: 1px;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase;
	color: var(--goblin-ink-soft);
}
/* The SKU is a value, not a destination: the same plate, with nothing to click
 * and nothing to hover. */
.goblin-tag--flat {
	background: var(--goblin-stone); box-shadow: none;
	font-family: var(--goblin-display); letter-spacing: 0.02em;
}

/* ---------- The share row ----------
 * One more meta row, and almost entirely the meta row's CSS — a label over a set
 * of `.goblin-tag` chips (inc/single-product.php). Only the two things a chip
 * that is a <button> does not inherit are set here.
 *
 * The margin is the gap between meta rows, not a new kind of space: share sits
 * under SKU/categories/tags and reads as the last of them. */
.goblin-share { margin-top: 13px; }
/* A <button> brings its own font family and size, which `.goblin-tag` does not
 * set and so does not take back. The border is deliberately not reset: the chip's
 * own `1px solid var(--goblin-edge)` already beats the UA's, and zeroing it here
 * would leave the one chip in the row with no edge.
 *
 * The hover is repeated because the chip's is on `a.goblin-tag:hover` — scoped to
 * the anchor so a non-interactive `.goblin-tag--flat` (the SKU) does not light up
 * under the pointer. This is interactive, so it opts back in. */
.goblin-share__copy {
	font: inherit; font-size: inherit; line-height: inherit; cursor: pointer;
}
.goblin-share__copy:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}
/* Copied: the chip goes gold for the two seconds the label says so, which is the
 * same gold `a.goblin-tag:hover` already uses — the confirmation is the hover
 * state held still, not a new colour to learn. */
.goblin-share__copy.is-done {
	background: var(--goblin-gold); color: #241a05;
}

/* ---------- The detail block ----------
 * The tabs, printed one after another as sections (inc/single-product.php). The
 * heading is the homepage's section heading, so a product page reads in the same
 * rhythm the front page does. */
.goblin-product__detail { margin-top: clamp(30px, 1.5rem + 2.4vw, 54px); }
.goblin-product__section + .goblin-product__section { margin-top: clamp(26px, 1.5rem + 2vw, 46px); }
/* A measure. The container is 1280px and this is running text: at full width a
 * description was about 175 characters a line, which is roughly twice what an eye
 * tracks back from without losing the row. */
.goblin-product__prose { max-width: 72ch; line-height: 1.6; }
.goblin-product__prose > :first-child { margin-top: 0; }
.goblin-product__prose > :last-child { margin-bottom: 0; }
.goblin-product__prose p { margin: 0 0 1em; }
.goblin-product__prose ul,
.goblin-product__prose ol { margin: 0 0 1em; padding-left: 1.2em; }
.goblin-product__prose h2,
.goblin-product__prose h3 { font-size: 1.05rem; margin: 1.6em 0 0.5em; }
.goblin-product__prose img { height: auto; border-radius: var(--goblin-radius); }

/* The attribute table, which is the whole of the "Additional information"
 * section: hairlines and a stone name column, so it reads as the same family of
 * boxes as the buy box above it. Woo's own is dotted rules and italics. */
.woocommerce .goblin-product__prose table.shop_attributes {
	width: 100%; max-width: 560px; margin: 0;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	border-collapse: separate; border-spacing: 0; overflow: hidden;
	font-size: 0.9rem;
}
.woocommerce .goblin-product__prose table.shop_attributes th,
.woocommerce .goblin-product__prose table.shop_attributes td {
	padding: 9px 12px; border: 0; border-top: 1px solid var(--goblin-edge);
	font-style: normal; line-height: 1.4;
}
.woocommerce .goblin-product__prose table.shop_attributes tr:first-child th,
.woocommerce .goblin-product__prose table.shop_attributes tr:first-child td { border-top: 0; }
.woocommerce .goblin-product__prose table.shop_attributes th {
	width: 40%; background: var(--goblin-stone);
	font-weight: 600; color: var(--goblin-ink-soft); text-align: left;
}
.woocommerce .goblin-product__prose table.shop_attributes td p { margin: 0; }
/* A taxonomy attribute's value is a link. Red and underlined — the theme's link,
 * written for running prose — is the loudest thing in a table this quiet, and it
 * is the only one in it, so it reads as an error rather than as a way out. */
.woocommerce .goblin-product__prose table.shop_attributes td a {
	color: var(--goblin-ink);
	text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 2px;
}
.woocommerce .goblin-product__prose table.shop_attributes td a:hover {
	color: var(--goblin-gold-ink); text-decoration-color: currentColor;
}

/* ---------- Up-sells and related products ----------
 * Rails, not grids — see inc/single-product.php. The heading is the same one the
 * detail sections take, and Woo's own `.related`/`.upsells` boxes bring float and
 * margin rules that a rail has no use for. */
.goblin-product__more {
	margin-top: clamp(34px, 1.5rem + 3vw, 60px);
	clear: both;
}
.woocommerce .goblin-product__more > h2 { margin-top: 0; }

/* ---------- WooCommerce notices ----------
 * Site-wide, not only the product page: this is the same box on the cart and the
 * checkout, and there should be one of it.
 *
 * What shipped was WooCommerce's own: a full-width lilac-topped slab with 1em of
 * padding, 2em of margin under it and a 3.5em left inset holding a glyph from the
 * WooCommerce icon font. On a product page "You cannot add that amount of X to
 * the cart because there is not enough stock" arrived as a hundred-pixel banner
 * above the gallery — a shout for a sentence, and a screen and a half from the
 * button that caused it, which is now where it prints (inc/single-product.php).
 *
 * It is a plate with one coloured edge instead: the theme's card, at the size of
 * the sentence in it, with the colour on the left rule doing what the icon and
 * the slab were doing between them. Errors take the red, a message takes the
 * green, anything else stays grey.
 *
 * Not a flex row, deliberately: `.woocommerce-error` is a `<ul>` and its items
 * would become flex items sitting side by side. */
.woocommerce-error,
.woocommerce-info,
.woocommerce-message {
	margin: 0 0 14px; padding: 9px 12px;
	background: #fff;
	border: 1px solid var(--goblin-edge);
	border-left: 3px solid var(--goblin-gray);
	border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-size: 0.84rem; line-height: 1.45; color: var(--goblin-ink-soft);
	list-style: none;
}
.woocommerce-error::before,
.woocommerce-info::before,
.woocommerce-message::before { content: none; }
/* WooCommerce gives a notice `tabindex="-1"` and focuses it so a screen reader
 * announces it. The theme's gold focus ring then draws round the whole box on
 * arrival, which reads as a highlight rather than as focus — and a box nothing
 * can Tab to has no focus a sighted reader needs told about. */
.woocommerce-error:focus,
.woocommerce-info:focus,
.woocommerce-message:focus,
.woocommerce-error:focus-visible,
.woocommerce-info:focus-visible,
.woocommerce-message:focus-visible { outline: none; }
.woocommerce-error { border-left-color: var(--goblin-red); color: var(--goblin-red-ink); }
.woocommerce-message { border-left-color: var(--goblin-green); }
.woocommerce-error li,
.woocommerce-info li,
.woocommerce-message li { margin: 0; padding: 0; list-style: none; }
.woocommerce-error li + li,
.woocommerce-info li + li,
.woocommerce-message li + li { margin-top: 5px; }
/* The button WooCommerce puts in a notice — "View cart", "Undo?" — is a link's
 * worth of text and was floated right out of the box on a narrow screen. */
.woocommerce .woocommerce-error .button,
.woocommerce .woocommerce-info .button,
.woocommerce .woocommerce-message .button {
	float: none; display: inline-block;
	margin: 0 0 0 6px; padding: 0;
	background: none; border: 0; border-radius: 0;
	font-size: inherit; font-weight: 600; color: inherit;
	text-decoration: underline; text-underline-offset: 3px;
}
/* Woo prints the wrapper on every page whether or not it holds a notice, and an
 * empty one still carries the margin below it. */
.woocommerce-notices-wrapper:not(:has(*)) { display: none; }

/* ---------- The cart page ----------
 * See inc/cart-page.php. Written **mobile first**, like the single product page
 * above and unlike the rest of this file: everything outside the two
 * `min-width` blocks at the end of the section is the phone, so a rule added
 * here is not quietly undone by the `max-width: 900px` block near the bottom of
 * the file.
 *
 * Two objects: the plate holding the lines, and the summary plate beside it.
 * Both are the product card's plate — white, one hairline, the shared radius,
 * the card shadow — because that is what a box holding goods is on this site.
 * Everything inside them is borrowed too: the stepper is the card's, the
 * checkout button is the card's add-to-cart at the product page's 48px, the
 * small uppercase labels are the product meta rows', the coupon control is the
 * archive toolbar's field and the pagination tile's button, and the cross-sell
 * row is a rail.
 *
 * WooCommerce prints all of it as two `<table>`s, and both are unpicked into
 * grids here rather than left as tables. A cart line is not a record in a table
 * — it is a picture, a name, a price, a control and a total, and below 720px it
 * has to become a card, which a table cannot do without the second layout
 * WooCommerce ships for exactly that (`woocommerce-smallscreen.css`, dropped on
 * this page in inc/cart-page.php). One grid that changes its template at 720px
 * is one layout to read instead of two that disagree.
 */

/* page.php caps a page's content at the 820px reading measure. That is the right
 * width for the legal pages and the wrong one for a cart, which is a listing
 * beside a summary and wants the container's own 1280. */
.woocommerce-cart .goblin-page__content { max-width: none; }
/* A notice is still a sentence, though, and a sentence does not want 1280 either. */
.woocommerce-cart .woocommerce-notices-wrapper { max-width: 760px; }

.goblin-cart {
	display: grid; align-items: start;
	gap: 22px;
	margin-top: 4px;
}

/* ---------- The lines ---------- */
.woocommerce .goblin-cart table.shop_table.cart {
	display: block; width: 100%; margin: 0;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	border-collapse: separate; border-spacing: 0;
	box-shadow: var(--goblin-shadow); overflow: hidden;
	font-family: var(--goblin-ui); font-size: 0.88rem;
}
/* The header row is the phone's to lose: the columns it would name are stacked
 * rather than side by side, so the one value that needs saying carries its own
 * label instead (the `::before` rule below). It comes back at 720. */
.woocommerce .goblin-cart table.cart thead { display: none; }
.woocommerce .goblin-cart table.cart tbody { display: block; }
.woocommerce .goblin-cart table.cart tbody tr { display: block; }
.woocommerce .goblin-cart table.cart tbody tr + tr { border-top: 1px solid var(--goblin-edge); }
.woocommerce .goblin-cart table.cart tbody td { padding: 0; border: 0; vertical-align: middle; }

/* One line, as a card: the picture beside the name and the unit price, then the
 * stepper and the line total across the bottom.
 *
 * The name spans both of the columns to its right rather than stopping at the
 * one, and the remove is taken out of the grid and pinned to the corner (the
 * row's right padding is the room it needs). Both of those are the same
 * arithmetic: a phone row is about 300px wide once the picture is out of it, and
 * a third column sized by "12.000 ден" takes a quarter of that away from the one
 * thing on the row that has to wrap — the product name, which was coming out at
 * seven lines of two words. Nothing else on the row wants a column of its own,
 * so nothing else gets one. */
.woocommerce .goblin-cart table.cart tbody tr.cart_item {
	position: relative;
	display: grid;
	grid-template-columns: 64px minmax(0, 1fr) auto;
	grid-template-areas:
		"thumb name  name"
		"thumb price price"
		"qty   qty   subtotal";
	column-gap: 12px; row-gap: 9px;
	align-items: center;
	padding: 14px 42px 14px 14px;
}
.woocommerce .goblin-cart table.cart tbody tr.cart_item td.product-remove {
	position: absolute; top: 11px; right: 9px;
}
/* Assigned once for both rows: WooCommerce gives the `<th>`s in the header the
 * same six class names it gives the `<td>`s, so the two rows can share a
 * template and the columns line up without a second set of rules. */
.goblin-cart .product-thumbnail { grid-area: thumb; }
.goblin-cart .product-name { grid-area: name; }
.goblin-cart .product-price { grid-area: price; }
.goblin-cart .product-quantity { grid-area: qty; }
.goblin-cart .product-subtotal { grid-area: subtotal; }
.goblin-cart .product-remove { grid-area: remove; }

.woocommerce .goblin-cart td.product-thumbnail a { display: block; }
/* WooCommerce draws this at 32px, which is a favicon of a boardgame box. The
 * card's media plate at the size a line can carry: contained rather than cropped,
 * because a box shot cropped to a square loses the title on the lid. */
.woocommerce .goblin-cart table.cart td.product-thumbnail img {
	display: block; width: 68px; height: 68px;
	padding: 4px; object-fit: contain;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: none;
}

.woocommerce .goblin-cart td.product-name {
	font-size: 0.88rem; line-height: 1.35;
}
/* Ink, not the site's link red, and no underline: a row of six red underlined
 * product names is the loudest thing on the page, and the picture beside it has
 * already said this is a product you can go and look at. Gold ink on hover, the
 * same cue the product page's cart link takes. */
.woocommerce .goblin-cart td.product-name a {
	color: var(--goblin-ink); font-weight: 600; text-decoration: none;
}
.woocommerce .goblin-cart td.product-name a:hover { color: var(--goblin-gold-ink); }
/* A variable product's chosen attributes, and anything else a plugin adds under
 * the name. */
.woocommerce .goblin-cart td.product-name dl.variation {
	margin: 4px 0 0; font-size: 0.76rem; line-height: 1.4; color: var(--goblin-ink-soft);
}
.woocommerce .goblin-cart td.product-name dl.variation dt,
.woocommerce .goblin-cart td.product-name dl.variation dd { margin: 0; padding: 0; display: inline; }
.woocommerce .goblin-cart td.product-name dl.variation dd + dt::before { content: " · "; }
.woocommerce .goblin-cart td.product-name dl.variation p { margin: 0; display: inline; }
.woocommerce .goblin-cart td.product-name .backorder_notification {
	margin: 4px 0 0; font-size: 0.76rem; color: var(--goblin-red-ink);
}

/* The two amounts, in the display face the prices take everywhere else. The unit
 * price is the quieter of them — it is what one costs, and the line total is what
 * this line is actually adding to the number in the summary. */
.woocommerce .goblin-cart td.product-price,
.woocommerce .goblin-cart td.product-subtotal {
	font-family: var(--goblin-display); white-space: nowrap;
}
.woocommerce .goblin-cart td.product-price {
	font-size: 0.82rem; font-weight: 500; color: var(--goblin-ink-soft);
}
.woocommerce .goblin-cart td.product-subtotal {
	font-size: 0.95rem; font-weight: 600; color: var(--goblin-ink); text-align: right;
}
/* On a phone the header row is gone, so the unit price says what it is — the
 * string is WooCommerce's own `data-title`, which is already translated: the
 * column heading, moved to where the column went. Only the unit price needs it.
 * The line total is the last thing on the row and the only bold number on it,
 * and a second label beside the stepper would be the third piece of small print
 * in four lines. */
.woocommerce .goblin-cart td.product-price::before {
	content: attr(data-title);
	margin-right: 7px;
	font-family: var(--goblin-ui); font-size: 0.62rem; font-weight: 700;
	letter-spacing: 0.12em; text-transform: uppercase; color: var(--goblin-ink-soft);
}

/* The stepper. `div.quantity` is WooCommerce's own wrapper round its own number
 * field; the two glyphs inside it are added by initSingleQty() (assets/js/goblin.js)
 * and are `.goblin-qty__step`, so this only has to be the box they share — which
 * is `.goblin-qty`, restated on a class of Woo's. Not `@extend`-ed or aliased in
 * PHP: the markup is Woo's and this is the one place that has to say so. */
.woocommerce .goblin-cart td.product-quantity div.quantity {
	display: flex; align-items: stretch; justify-content: space-between;
	float: none; margin: 0; width: 112px; min-height: 34px;
	background: #fff; overflow: hidden;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
.woocommerce .goblin-cart td.product-quantity div.quantity input.qty {
	flex: 1 1 auto; width: auto; min-width: 0; height: auto;
	padding: 0; border: 0; background: transparent;
	font-family: var(--goblin-display); font-size: 0.88rem; font-weight: 600;
	color: var(--goblin-ink); text-align: center;
	appearance: textfield; -moz-appearance: textfield;
}
.woocommerce .goblin-cart td.product-quantity div.quantity input.qty::-webkit-outer-spin-button,
.woocommerce .goblin-cart td.product-quantity div.quantity input.qty::-webkit-inner-spin-button {
	appearance: none; -webkit-appearance: none; margin: 0;
}
/* A product sold one at a time gets a hidden input and the bare number "1", which
 * is not a control and should not be drawn as one. */
.woocommerce .goblin-cart td.product-quantity div.quantity:has(input.qty[type="hidden"]) {
	border: 0; background: none; width: auto; min-height: 0;
	font-family: var(--goblin-display); font-weight: 600; color: var(--goblin-ink-soft);
}

/* The remove.
 *
 * The two `!important`s here are not a specificity argument — WooCommerce writes
 * `color: var(--wc-red) !important` on `a.remove` and `color: #fff !important` on
 * its hover, and author `!important` is the only thing that outranks author
 * `!important`. (The same trade the card's button makes further up, and the same
 * one the product page's quantity wrapper makes.)
 *
 * Grey at rest and red only under the pointer, because there is one of these per
 * line and six red circles down the side of a cart is the page shouting about the
 * thing the reader is least likely to want. The destructive colour arrives at the
 * moment the press would be destructive. */
.woocommerce .goblin-cart td.product-remove a.remove {
	display: flex; align-items: center; justify-content: center;
	width: 26px; height: 26px; margin-left: auto;
	background: none; border-radius: var(--goblin-radius);
	font-size: 1.05rem; font-weight: 400; line-height: 1;
	color: var(--goblin-gray) !important; text-decoration: none;
}
.woocommerce .goblin-cart td.product-remove a.remove:hover {
	background: var(--goblin-stone);
	color: var(--goblin-red-ink) !important;
}

/* ---------- The actions row: coupon, and the button nobody presses ---------- */
.woocommerce .goblin-cart table.cart td.actions {
	display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
	padding: 12px 14px;
	background: var(--goblin-stone);
	text-align: left;
}
.woocommerce .goblin-cart table.cart td.actions .coupon {
	display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
	flex: 1 1 240px; min-width: 0; max-width: 380px;
	float: none; padding: 0;
}
.woocommerce .goblin-cart table.cart td.actions .coupon::before,
.woocommerce .goblin-cart table.cart td.actions .coupon::after { content: none; }
/* The archive toolbar's field: a white plate with a hairline, at the size of the
 * word going in it. WooCommerce's own is 100px wide and floated. */
.woocommerce .goblin-cart table.cart td.actions .coupon input.input-text {
	flex: 1 1 auto; width: auto; min-width: 0; float: none; margin: 0;
	padding: 8px 11px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	outline: 0;
	font-family: var(--goblin-ui); font-size: 0.85rem; line-height: 1.3;
	color: var(--goblin-ink);
}
.woocommerce .goblin-cart table.cart td.actions .coupon input.input-text:hover { border-color: var(--goblin-edge-dark); }
/* The pagination tile as a button: white, one hairline, the card shadow, gold on
 * hover. Every secondary control on this site is that plate, and the coupon is
 * the only secondary control on this page. */
.woocommerce .goblin-cart table.cart td.actions button.button {
	flex: 0 0 auto; width: auto; float: none;
	padding: 8px 15px; min-height: 0; margin: 0;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 600;
	line-height: 1.3; letter-spacing: 0.01em; text-transform: none;
	white-space: nowrap; cursor: pointer;
}
.woocommerce .goblin-cart table.cart td.actions button.button:hover:not(:disabled) {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}
.woocommerce .goblin-cart table.cart td.actions button.button:disabled {
	opacity: 0.45; cursor: default;
}
/* WooCommerce prints the refusal inside the `.coupon` box, as a sibling of the
 * field and the button. It gets its own line rather than a share of theirs —
 * `flex-basis: 100%` on a wrapping row, which is how the product page's meta
 * rows put a label over its chips — because a sentence given the ~120px left
 * over beside a 380px control is a sentence on three lines, and it took the
 * width to reach them from the field, which shrank to 90px to make room. */
.woocommerce .goblin-cart td.actions .coupon .coupon-error-notice {
	flex: 0 0 100%; width: auto; float: none; margin: 2px 0 0;
	font-size: 0.76rem; line-height: 1.4; color: var(--goblin-red-ink);
}
/* Woo marks the field `has-error` and points `aria-describedby` at the sentence
 * above; the border is the same thing for a reader who is looking at it. */
.woocommerce .goblin-cart table.cart td.actions .coupon input.input-text.has-error {
	border-color: var(--goblin-red);
}
/* "Update cart" goes away as soon as JavaScript is running, because the stepper
 * posts the change itself by pressing this button for the reader (initCartQty()
 * in assets/js/goblin.js). Without JavaScript it is the only way the field means
 * anything, so it stays — which is why the class is set by the script and not
 * printed by PHP. It is set on this box rather than on the form because the form
 * is replaced on every update and a class put there would flash back each time. */
.goblin-cart--live table.cart td.actions button[name="update_cart"] { display: none; }

/* ---------- The summary ---------- */
.woocommerce .goblin-cart .cart-collaterals { width: 100%; }
.woocommerce .goblin-cart .cart-collaterals::before,
.woocommerce .goblin-cart .cart-collaterals::after { content: none; }
.woocommerce .goblin-cart .cart-collaterals .cart_totals {
	float: none; width: auto;
	padding: 16px 16px 18px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
}
/* A label for a block of numbers, not a headline over it — the meta rows' label,
 * which is what this theme's small print looks like. WooCommerce prints it as an
 * `<h2>`, and it deserves the tag and not the size. */
.woocommerce .goblin-cart .cart_totals > h2 {
	margin: 0 0 12px;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; color: var(--goblin-ink-soft);
}
.woocommerce .goblin-cart .cart_totals table.shop_table {
	display: block; width: 100%; margin: 0;
	background: none; border: 0; border-radius: 0; box-shadow: none;
}
.woocommerce .goblin-cart .cart_totals table.shop_table tbody { display: block; }
.woocommerce .goblin-cart .cart_totals table.shop_table tr {
	display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
	gap: 6px 14px;
	padding: 9px 0;
	border-top: 1px solid var(--goblin-edge);
}
.woocommerce .goblin-cart .cart_totals table.shop_table tr:first-child { padding-top: 0; border-top: 0; }
.woocommerce .goblin-cart .cart_totals table.shop_table th {
	flex: 0 0 auto; padding: 0; border: 0;
	font-family: var(--goblin-ui); font-size: 0.78rem; font-weight: 600; line-height: 1.4;
	color: var(--goblin-ink-soft); text-align: left;
}
.woocommerce .goblin-cart .cart_totals table.shop_table td {
	flex: 1 1 auto; padding: 0; border: 0; text-align: right;
	font-family: var(--goblin-display); font-size: 0.92rem; font-weight: 600;
	color: var(--goblin-ink);
}
/* The one number the page is about. Bigger than the rows above it and in ink,
 * with the label promoted out of the small print to match. */
.woocommerce .goblin-cart .cart_totals tr.order-total th {
	font-size: 0.86rem; color: var(--goblin-ink);
}
.woocommerce .goblin-cart .cart_totals tr.order-total td { font-size: 1.22rem; }
.woocommerce .goblin-cart .cart_totals tr.cart-discount th { color: var(--goblin-green); }
.woocommerce .goblin-cart .cart_totals tr.cart-discount td { color: var(--goblin-green); }
.woocommerce .goblin-cart .cart_totals .woocommerce-remove-coupon {
	margin-left: 6px; font-family: var(--goblin-ui); font-size: 0.72rem; font-weight: 600;
	color: var(--goblin-ink-soft);
}

/* Shipping is the one row that is a choice rather than a number, so it takes the
 * meta rows' arrangement instead of the row's: the label breaks the line with
 * `flex-basis: 100%` and the options sit under it at full width. Squeezed into
 * the right-hand half of a two-column row, three radio labels wrapped to eight
 * lines against a one-line "Shipment" on the left. */
.woocommerce .goblin-cart .cart_totals tr.woocommerce-shipping-totals th,
.woocommerce .goblin-cart .cart_totals tr.shipping th { flex: 0 0 100%; margin-bottom: 7px; }
.woocommerce .goblin-cart .cart_totals tr.woocommerce-shipping-totals td,
.woocommerce .goblin-cart .cart_totals tr.shipping td {
	flex: 0 0 100%; text-align: left;
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 400;
	color: var(--goblin-ink);
}
/* The list is shared with the checkout's order review, which asks the same
 * question in the same plate. One control, written once. */
.woocommerce .goblin-cart ul#shipping_method,
.woocommerce-checkout .goblin-checkout__aside ul#shipping_method {
	display: grid; gap: 8px; margin: 0; padding: 0; list-style: none;
}
.woocommerce .goblin-cart ul#shipping_method li,
.woocommerce-checkout .goblin-checkout__aside ul#shipping_method li {
	display: flex; align-items: flex-start; gap: 9px;
	margin: 0; padding: 0; list-style: none;
}
.woocommerce .goblin-cart ul#shipping_method li input.shipping_method,
.woocommerce-checkout .goblin-checkout__aside ul#shipping_method li input.shipping_method {
	flex: 0 0 auto; width: 15px; height: 15px; margin: 2px 0 0;
	accent-color: var(--goblin-gold);
}
.woocommerce .goblin-cart ul#shipping_method li label,
.woocommerce-checkout .goblin-checkout__aside ul#shipping_method li label {
	display: block; margin: 0; font-size: 0.82rem; line-height: 1.4; color: var(--goblin-ink);
}
.woocommerce .goblin-cart ul#shipping_method .amount,
.woocommerce-checkout .goblin-checkout__aside ul#shipping_method .amount {
	font-family: var(--goblin-display); font-weight: 600; white-space: nowrap;
}
.woocommerce .goblin-cart .woocommerce-shipping-destination {
	margin: 9px 0 0; font-size: 0.76rem; line-height: 1.45; color: var(--goblin-ink-soft);
}
.woocommerce .goblin-cart .shipping-calculator-button {
	font-size: 0.78rem; font-weight: 600; color: var(--goblin-ink-soft);
	text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px;
}
.woocommerce .goblin-cart .shipping-calculator-button:hover { color: var(--goblin-gold-ink); }

/* The one thing to press on this page, so it is the card's add-to-cart at the
 * product page's size and the full width of the plate it closes. What it replaced
 * was Woo's `button.alt` lilac (`--wc-primary`, #720eec), which is the only
 * colour on the storefront that is in no palette here. */
.woocommerce .goblin-cart .wc-proceed-to-checkout { margin: 0; padding: 15px 0 0; }
.woocommerce .goblin-cart .wc-proceed-to-checkout a.checkout-button {
	display: flex; align-items: center; justify-content: center; text-align: center;
	width: 100%; min-height: 48px; margin: 0; padding: 12px 22px;
	border: 0; border-radius: var(--goblin-radius);
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.95rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-decoration: none;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce .goblin-cart .wc-proceed-to-checkout a.checkout-button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}

/* ---------- An empty cart ---------- */
/* Nothing to lay out, so nothing is: the sentence takes the site's notice plate
 * (the `.woocommerce-info` rule further up) and the way out takes the gold
 * button, because with an empty cart "Return to shop" is the only action on the
 * page and the one thing that should look like one. */
.woocommerce .wc-empty-cart-message { max-width: 760px; }
.woocommerce .return-to-shop { margin: 14px 0 0; }
.woocommerce .return-to-shop a.button {
	display: inline-flex; align-items: center; justify-content: center;
	min-height: 48px; padding: 12px 26px;
	border: 0; border-radius: var(--goblin-radius);
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.92rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-decoration: none;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce .return-to-shop a.button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}

/* ---------- Wide enough for the columns to be columns ---------- */
/* 720 is where a line stops being a card and becomes a row again: six things
 * across, with the header row back above them saying what each column is. Below
 * it there is not enough width for a name and three numbers side by side without
 * the name wrapping to four lines. */
@media (min-width: 720px) {
	.woocommerce .goblin-cart table.cart thead { display: block; }
	.woocommerce .goblin-cart table.cart thead tr,
	.woocommerce .goblin-cart table.cart tbody tr.cart_item {
		display: grid;
		grid-template-columns: 72px minmax(0, 1fr) 104px 118px 104px 28px;
		grid-template-areas: "thumb name price qty subtotal remove";
		column-gap: 14px; row-gap: 0;
		align-items: center;
	}
	.woocommerce .goblin-cart table.cart thead tr {
		padding: 9px 16px;
		background: var(--goblin-stone);
		border-bottom: 1px solid var(--goblin-edge);
	}
	/* The meta rows' label, which is what a column heading is on this site. */
	.woocommerce .goblin-cart table.cart thead th {
		padding: 0; border: 0;
		font-family: var(--goblin-ui); font-size: 0.62rem; font-weight: 700;
		letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.3;
		color: var(--goblin-ink-soft); text-align: left;
	}
	.woocommerce .goblin-cart table.cart thead th.product-price,
	.woocommerce .goblin-cart table.cart thead th.product-subtotal { text-align: right; }
	/* Centred, over a stepper that fills its column and is symmetrical about the
	 * number in it. Left-aligned it sat 14px from the right-aligned price heading
	 * beside it, and the two read as one run of small caps rather than as two
	 * column names. */
	.woocommerce .goblin-cart table.cart thead th.product-quantity { text-align: center; }
	.woocommerce .goblin-cart table.cart tbody tr.cart_item { padding: 14px 16px; }
	/* The remove goes back into the grid: there is a column for it again. */
	.woocommerce .goblin-cart table.cart tbody tr.cart_item td.product-remove { position: static; }
	/* And the label moves back into the header row it came from. */
	.woocommerce .goblin-cart td.product-price::before { content: none; }
	.woocommerce .goblin-cart td.product-price { text-align: right; font-size: 0.85rem; }
	.woocommerce .goblin-cart table.cart td.product-thumbnail img { width: 72px; height: 72px; }
	.woocommerce .goblin-cart td.product-quantity div.quantity { width: 100%; }
	.woocommerce .goblin-cart td.product-remove a.remove { margin: 0; }
	/* The summary is a plate under the lines until 1060, aligned to their right
	 * edge — which is where a total belongs whichever way the page is stacked. On
	 * a phone it simply runs the full width, because there is no edge to align to
	 * that is not the screen's. */
	.woocommerce .goblin-cart .cart-collaterals { max-width: 420px; margin-left: auto; }
}

/* 1060 is where the summary can sit beside the lines instead of under them: the
 * 1280 container, less a 330px summary and the gap, still leaves a line room for
 * a name of a useful length next to its three numbers. */
@media (min-width: 1060px) {
	.goblin-cart {
		grid-template-columns: minmax(0, 1fr) 330px;
		gap: 26px;
	}
	.woocommerce .goblin-cart .cart-collaterals {
		max-width: none; margin-left: 0;
		/* Clear of the sticky header — 129px of brand row and category band at this
		 * width, plus a little air. A summary that scrolls away while the reader is
		 * still checking the lines it is the total of is a summary they have to
		 * scroll back to. */
		position: sticky; top: 140px;
	}
}

/* ---------- The checkout page ----------
 * See inc/checkout.php. Written **mobile first**, like the cart page above and
 * the single product page before it: everything outside the `min-width` blocks
 * at the end of the section is the phone.
 *
 * The page is the cart's arrangement one step on — fields left, the order and
 * its total in a plate on the right — so it is built out of the cart's parts.
 * The plates are the product card's, the fields are the archive toolbar's, the
 * section labels are the product meta rows', the review's rows are the cart
 * summary's rows, "Place order" is the cart's checkout button and the secondary
 * buttons are the pagination tile. Nothing here is a new object.
 */

/* page.php caps content at the 820px reading measure, which is right for a legal
 * page and wrong for a form beside a summary — the same trade the cart makes.
 *
 * `is_checkout()` is three screens, not one: order-pay and order-received carry
 * this body class too, and neither has a form beside a summary on it. Both keep
 * a measure, and say so themselves in The order pages below. The exclusion is
 * written here rather than as an override there because the two selectors would
 * otherwise be two classes each, and the winner would be whichever was written
 * second. */
.woocommerce-checkout:not(.woocommerce-order-received):not(.woocommerce-order-pay) .goblin-page__content { max-width: none; }
/* A notice is still a sentence. So is the "returning customer?" strip and the
 * coupon one: both are `.woocommerce-info` plates, and a plate 1280px wide with
 * six words in it reads as a banner. */
.woocommerce-checkout .woocommerce-notices-wrapper,
.woocommerce-checkout .woocommerce-form-login-toggle,
.woocommerce-checkout .woocommerce-form-coupon-toggle { max-width: 760px; }

/* ---------- The two columns ---------- */
/* `form.checkout` holds exactly two things once inc/checkout.php has wrapped the
 * review and its heading together: the fields and the summary. So the form is
 * the grid, and there is no extra box for one. */
.woocommerce-checkout form.checkout {
	display: grid; align-items: start;
	gap: 22px;
	margin: 4px 0 0;
}
/* WooCommerce's order-attribution custom element is a bag of hidden inputs. It
 * is not `display: none` by default, so as a child of a grid it takes a row of
 * its own and leaves a 22px gap where nothing is. There are four of them. */
.woocommerce-checkout wc-order-attribution-inputs { display: none; }

/* `#customer_details` is a `col2-set` WooCommerce floats at 47/47. In a column
 * that is now half the page that is two ~300px columns of address fields, so the
 * two halves stack and the plates below give them their separation instead. */
.woocommerce-checkout #customer_details { display: block; }
.woocommerce-checkout #customer_details > .col-1,
.woocommerce-checkout #customer_details > .col-2 {
	float: none; width: auto; margin: 0;
}
.woocommerce-checkout #customer_details > .col-2 { margin-top: 18px; }
/* Woo clears the set with two `content: " "` pseudo-elements. Harmless as
 * floats, but they are boxes, and a stray box is a stray box. */
.woocommerce-checkout .col2-set::before,
.woocommerce-checkout .col2-set::after { content: none; }

/* ---------- The plates ----------
 * The product card's plate — white, one hairline, the shared radius, the card
 * shadow — because that is what a box holding something on this site is. One per
 * column half rather than one per field group: billing and "create an account?"
 * are one decision, and so are the delivery address and the note that goes with
 * it. Four plates for four groups would have been four boxes for one form. */
.woocommerce-checkout #customer_details > .col-1,
.woocommerce-checkout #customer_details > .col-2,
.woocommerce-checkout .goblin-checkout__aside {
	padding: 16px 16px 18px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
}

/* ---------- Section labels ----------
 * "Billing details" and "Your order" are labels for a block, not headlines over
 * a page — the product meta rows' label, which is what this theme's small print
 * looks like, and what the cart summary's own `<h2>` was given for the same
 * reason. They keep their `<h3>` because the document outline is right; only the
 * size was ever wrong. */
.woocommerce-checkout .woocommerce-billing-fields > h3,
.woocommerce-checkout .woocommerce-additional-fields > h3,
.woocommerce-checkout .goblin-checkout__aside > h3 {
	margin: 0 0 12px;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.3;
	color: var(--goblin-ink-soft);
}
/* The shipping heading is not a label at all — it is a checkbox with a sentence
 * on it ("Ship to a different address?"). Giving it the small-caps treatment set
 * a question in 0.66rem letterspaced uppercase next to a control, which reads as
 * a column heading that happens to be clickable. It keeps the body face. */
.woocommerce-checkout .woocommerce-shipping-fields > h3 {
	margin: 0; font-family: var(--goblin-ui); font-size: 0.88rem; font-weight: 600;
	line-height: 1.4; letter-spacing: 0; text-transform: none; color: var(--goblin-ink);
}
.woocommerce-checkout .woocommerce-shipping-fields .shipping_address { padding-top: 16px; }
.woocommerce-checkout .woocommerce-additional-fields { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--goblin-edge); }
.woocommerce-checkout .woocommerce-account-fields { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--goblin-edge); }

/* ---------- The fields ----------
 * A field wrapper is a grid, not a pair of floats: `form-row-first` and
 * `form-row-last` are Woo's two halves and `form-row-wide` is the full width,
 * which is three column spans and no clearing. Below 520px everything is one
 * column — two 130px halves is not a first name and a last name, it is two
 * abbreviations.
 *
 * **These rules are shared with the account pages** — the address book's form
 * and "Account details" are the same `.form-row` markup asking for the same
 * things, so every group below carries `.woocommerce-MyAccount-content`
 * alongside `.woocommerce-checkout` rather than being copied into that section.
 * Same arrangement as `#shipping_method`, which the cart and the checkout share:
 * a field is one control on this site and is written once. The wrappers those
 * rows sit in differ per page and are set where they belong — the two
 * `__field-wrapper` grids here, the account's two in its own section. */
.woocommerce-checkout .woocommerce-billing-fields__field-wrapper,
.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper,
.woocommerce-checkout .woocommerce-additional-fields__field-wrapper {
	display: grid; gap: 12px;
}
.woocommerce-checkout .form-row,
.woocommerce-MyAccount-content .form-row {
	float: none; width: auto; margin: 0; padding: 0;
}
.woocommerce-checkout .form-row label,
.woocommerce-MyAccount-content .form-row label {
	display: block; margin: 0 0 5px;
	font-family: var(--goblin-ui); font-size: 0.74rem; font-weight: 600; line-height: 1.35;
	color: var(--goblin-ink-soft);
}
/* Required is a colour and a glyph, optional is a word set quieter than the name
 * it qualifies. Woo prints both; neither had a rule. */
.woocommerce-checkout .form-row label .required,
.woocommerce-MyAccount-content .form-row label .required { color: var(--goblin-red); text-decoration: none; border: 0; }
.woocommerce-checkout .form-row label .optional,
.woocommerce-MyAccount-content .form-row label .optional { font-weight: 400; color: var(--goblin-gray); }
.woocommerce-checkout .woocommerce-input-wrapper,
.woocommerce-MyAccount-content .woocommerce-input-wrapper { display: block; width: 100%; }
/* Selling to one country only, WooCommerce prints the country as a `<strong>`
 * and a hidden input rather than a select. It is a value the reader is being
 * shown, not a heading, so it is set as the field's own text and not as the
 * bold body copy it defaulted to. */
.woocommerce-checkout .woocommerce-input-wrapper > strong,
.woocommerce-MyAccount-content .woocommerce-input-wrapper > strong {
	display: block; padding: 9px 0 0;
	font-family: var(--goblin-ui); font-size: 0.88rem; font-weight: 500; line-height: 1.4;
	color: var(--goblin-ink);
}

/* The archive toolbar's field, at the size of a line of an address. Woo's own is
 * the browser's box with a 1px `#ddd` edge and whatever focus ring the platform
 * draws — on the one screen where a reader is typing ten things in a row and
 * needs to see which one they are in. */
.woocommerce-checkout .form-row input.input-text,
.woocommerce-checkout .form-row textarea,
.woocommerce-checkout .form-row select,
.woocommerce-checkout form.login input.input-text,
.woocommerce-checkout form.checkout_coupon input.input-text,
.woocommerce-MyAccount-content .form-row input.input-text,
.woocommerce-MyAccount-content .form-row select {
	display: block; width: 100%; margin: 0; float: none;
	padding: 9px 11px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	outline: 0; box-shadow: none;
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.4;
	color: var(--goblin-ink);
}
.woocommerce-checkout .form-row textarea { min-height: 76px; resize: vertical; }
.woocommerce-checkout .form-row input.input-text:hover,
.woocommerce-checkout .form-row textarea:hover,
.woocommerce-checkout .form-row select:hover,
.woocommerce-MyAccount-content .form-row input.input-text:hover,
.woocommerce-MyAccount-content .form-row select:hover { border-color: var(--goblin-edge-dark); }
/* The gold ring, which is the site's focus, rather than the platform's blue.
 * `box-shadow` and not `outline` so the ring follows the 3px radius. */
.woocommerce-checkout .form-row input.input-text:focus,
.woocommerce-checkout .form-row textarea:focus,
.woocommerce-checkout .form-row select:focus,
.woocommerce-checkout form.login input.input-text:focus,
.woocommerce-checkout form.checkout_coupon input.input-text:focus,
.woocommerce-MyAccount-content .form-row input.input-text:focus,
.woocommerce-MyAccount-content .form-row select:focus {
	border-color: var(--goblin-gold);
	box-shadow: 0 0 0 3px rgba(224, 168, 30, 0.22);
}
.woocommerce-checkout .form-row ::placeholder,
.woocommerce-MyAccount-content .form-row ::placeholder { color: var(--goblin-gray); }
/* Woo marks a failed field `woocommerce-invalid` on the row, not on the input. */
.woocommerce-checkout .form-row.woocommerce-invalid input.input-text,
.woocommerce-checkout .form-row.woocommerce-invalid select,
.woocommerce-checkout .form-row.woocommerce-invalid textarea,
.woocommerce-MyAccount-content .form-row.woocommerce-invalid input.input-text,
.woocommerce-MyAccount-content .form-row.woocommerce-invalid select { border-color: var(--goblin-red); }
.woocommerce-checkout .form-row.woocommerce-validated input.input-text,
.woocommerce-MyAccount-content .form-row.woocommerce-validated input.input-text { border-color: var(--goblin-edge); }

/* Country and state become select2 widgets when they are selects at all
 * (selectWoo, which WooCommerce enqueues on this page either way). **Today they
 * are not**: the shop sells to one country, so WooCommerce prints the country as
 * the `<strong>` styled above and a hidden input, and the state as a plain text
 * field. These rules therefore change nothing on the storefront as it stands.
 *
 * They are here rather than left out because the day a second country is added
 * in WooCommerce → Settings the two controls appear as select2 widgets with the
 * plugin's own 28px grey box on a form where nothing else looks like that, and
 * nobody will connect the regression to a shipping setting. Deleting them is
 * fine if that is never going to happen.
 *
 * Shared with the account pages for the same reason the fields above are: the
 * address book edits the same two fields on the same markup, and WooCommerce
 * enqueues `wc-country-select` on `is_account_page()` as well as on the
 * checkout. */
.woocommerce-checkout .select2-container .select2-selection--single,
.woocommerce-MyAccount-content .select2-container .select2-selection--single {
	height: auto; padding: 9px 11px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
.woocommerce-checkout .select2-container .select2-selection--single:hover,
.woocommerce-MyAccount-content .select2-container .select2-selection--single:hover { border-color: var(--goblin-edge-dark); }
.woocommerce-checkout .select2-container--open .select2-selection--single,
.woocommerce-MyAccount-content .select2-container--open .select2-selection--single {
	border-color: var(--goblin-gold);
	box-shadow: 0 0 0 3px rgba(224, 168, 30, 0.22);
}
.woocommerce-checkout .select2-container .select2-selection--single .select2-selection__rendered,
.woocommerce-MyAccount-content .select2-container .select2-selection--single .select2-selection__rendered {
	padding: 0; line-height: 1.4;
	font-family: var(--goblin-ui); font-size: 0.88rem; color: var(--goblin-ink);
}
.woocommerce-checkout .select2-container .select2-selection--single .select2-selection__arrow,
.woocommerce-MyAccount-content .select2-container .select2-selection--single .select2-selection__arrow {
	top: 50%; right: 8px; transform: translateY(-50%); height: auto;
}

/* ---------- Checkboxes ----------
 * "Create an account?", "Ship to a different address?", "Remember me" and the
 * terms are all the same row: the control, then the sentence beside it, with a
 * wrapped sentence lining up under itself rather than under the box.
 *
 * The control is taken out of the flow and placed, and the label keeps its
 * ordinary inline content — it is NOT a flex row. WooCommerce prints the input
 * *inside* the label and, on the terms, a bare `*` in an `<abbr>` after the
 * sentence. As flex items those are three boxes, and the asterisk ended up
 * alone against the right edge of the row, level with the first line of a
 * sentence whose last line was two lines below it. Inline content has no such
 * problem: the `*` simply follows the words, wherever they end.
 *
 * The selector is long because it has to be. WooCommerce writes these as
 * `.woocommerce form .form-row label` (0,2,2) and `.woocommerce form .form-row
 * label.checkbox` (0,3,2), and this theme's own field-label rule a few lines up
 * is `.woocommerce-checkout .form-row label` (0,2,1) — so a rule written on the
 * checkbox class alone loses to all three. It did: of the four checkbox rows on
 * this page exactly one came out as intended and the other three took
 * `display: block` or `inline` and stacked each control above its sentence.
 * Every one of these labels carries both `woocommerce-form__label` and
 * `woocommerce-form__label-for-checkbox`, so naming both takes this to (0,4,2)
 * and settles it outright rather than on source order. The second selector is
 * the "Ship to a different address?" label, which WooCommerce prints inside an
 * `<h3>` and not a `.form-row` — no Woo rule reaches it, so it needs no weight. */
.woocommerce-checkout form .form-row label.woocommerce-form__label.woocommerce-form__label-for-checkbox,
.woocommerce-checkout label.woocommerce-form__label.woocommerce-form__label-for-checkbox {
	display: block; position: relative;
	margin: 0; padding-left: 24px;
	font-family: var(--goblin-ui); font-size: 0.85rem; font-weight: 400; line-height: 1.5;
	color: var(--goblin-ink); cursor: pointer;
}
/* `top` in `em` so the box sits on the first line's cap height whatever the row's
 * type size is, rather than at a pixel offset that only suits one of them. */
.woocommerce-checkout .woocommerce-form__input-checkbox {
	position: absolute; left: 0; top: 0.28em;
	width: 15px; height: 15px; margin: 0;
	accent-color: var(--goblin-gold);
}
.woocommerce-checkout label.woocommerce-form__label-for-checkbox abbr.required {
	border: 0; text-decoration: none; color: var(--goblin-red);
}

/* ---------- The two things above the form ----------
 * "Returning customer?" and "Have a coupon?" are `.woocommerce-info` plates and
 * already look like every other notice on the site. What had no rules is what
 * they reveal: two forms that opened as a run of unstyled fields. */
.woocommerce-checkout form.login,
.woocommerce-checkout form.checkout_coupon {
	max-width: 760px; margin: 0 0 18px; padding: 16px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
}
.woocommerce-checkout form.login > p:first-child { margin-top: 0; font-size: 0.85rem; line-height: 1.5; color: var(--goblin-ink-soft); }
.woocommerce-checkout form.login .form-row,
.woocommerce-checkout form.checkout_coupon .form-row { margin: 0 0 12px; }
.woocommerce-checkout form.checkout_coupon { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
.woocommerce-checkout form.checkout_coupon .form-row { flex: 1 1 200px; min-width: 0; margin: 0; }
.woocommerce-checkout form.checkout_coupon .form-row-last { flex: 0 0 auto; }
.woocommerce-checkout form.login .clear,
.woocommerce-checkout form.checkout_coupon .clear { display: none; }
.woocommerce-checkout .lost_password { margin: 10px 0 0; font-size: 0.8rem; }
.woocommerce-checkout .lost_password a { color: var(--goblin-ink-soft); text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px; }
.woocommerce-checkout .lost_password a:hover { color: var(--goblin-gold-ink); }

/* ---------- The order review ----------
 * The cart summary's table, which is the same object: a stack of rows where a
 * label sits left and a number sits right, and the one number the page is about
 * is bigger than the rest. The only thing this one has that the cart's does not
 * is the lines themselves at the top. */
.woocommerce-checkout .goblin-checkout__aside table.shop_table {
	display: block; width: 100%; margin: 0;
	background: none; border: 0; border-radius: 0; box-shadow: none;
}
.woocommerce-checkout .goblin-checkout__aside table.shop_table thead,
.woocommerce-checkout .goblin-checkout__aside table.shop_table tbody,
.woocommerce-checkout .goblin-checkout__aside table.shop_table tfoot { display: block; }
.woocommerce-checkout .goblin-checkout__aside table.shop_table tr {
	display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
	gap: 6px 14px;
	padding: 9px 0;
	border-top: 1px solid var(--goblin-edge);
}
/* A line never wraps: the name shrinks and wraps *inside its own cell* instead,
 * so the price stays on the first line of the product it belongs to. "Riftbound:
 * League of Legends TCG Vendetta Booster × 2" took two lines and pushed its 800
 * ден onto a third, where it read as a row of its own. Only the totals below
 * wrap, and only so the shipping choice can break to full width. */
.woocommerce-checkout .goblin-checkout__aside table.shop_table tbody tr { flex-wrap: nowrap; }
.woocommerce-checkout .goblin-checkout__aside table.shop_table th,
.woocommerce-checkout .goblin-checkout__aside table.shop_table td {
	padding: 0; border: 0;
}
/* The column headings say "Product" and "Subtotal" over two lines that already
 * read as a name and a price. The meta rows' label, at the size the cart's
 * `thead` takes on a wide screen. */
/* "PRODUCT / SUBTOTAL" is dropped, unlike the cart's header row. There it names
 * six columns you could not otherwise tell apart; here it is two words in the
 * meta label's small caps directly under "YOUR ORDER" in the same small caps,
 * over a list of names with prices after them. Two label rows in a row, and the
 * second one telling the reader that a name is a name. */
.woocommerce-checkout .goblin-checkout__aside table.shop_table thead { display: none; }
/* A line: the name takes the room, the number keeps its own and does not wrap. */
.woocommerce-checkout .goblin-checkout__aside tbody td.product-name {
	flex: 1 1 auto; min-width: 0;
	font-family: var(--goblin-ui); font-size: 0.82rem; line-height: 1.45; color: var(--goblin-ink);
}
.woocommerce-checkout .goblin-checkout__aside tbody td.product-total {
	flex: 0 0 auto; text-align: right; white-space: nowrap;
	font-family: var(--goblin-display); font-size: 0.88rem; font-weight: 600; color: var(--goblin-ink);
}
/* "× 2" is how many, not part of the name, so it is set as the small print the
 * rest of this plate uses rather than as the `<strong>` Woo prints it as. */
.woocommerce-checkout .goblin-checkout__aside td.product-name .product-quantity {
	font-weight: 600; color: var(--goblin-ink-soft); white-space: nowrap;
}
.woocommerce-checkout .goblin-checkout__aside tfoot th {
	flex: 0 0 auto;
	font-family: var(--goblin-ui); font-size: 0.78rem; font-weight: 600; line-height: 1.4;
	color: var(--goblin-ink-soft); text-align: left;
}
.woocommerce-checkout .goblin-checkout__aside tfoot td {
	flex: 1 1 auto; text-align: right;
	font-family: var(--goblin-display); font-size: 0.92rem; font-weight: 600; color: var(--goblin-ink);
}
.woocommerce-checkout .goblin-checkout__aside tfoot tr.order-total th { font-size: 0.86rem; color: var(--goblin-ink); }
.woocommerce-checkout .goblin-checkout__aside tfoot tr.order-total td { font-size: 1.22rem; }
.woocommerce-checkout .goblin-checkout__aside tfoot tr.cart-discount th,
.woocommerce-checkout .goblin-checkout__aside tfoot tr.cart-discount td { color: var(--goblin-green); }
/* Shipping is a choice rather than a number, so — exactly as on the cart — the
 * label breaks the line and the options sit under it at full width. */
.woocommerce-checkout .goblin-checkout__aside tfoot tr.woocommerce-shipping-totals th { flex: 0 0 100%; margin-bottom: 7px; }
.woocommerce-checkout .goblin-checkout__aside tfoot tr.woocommerce-shipping-totals td {
	flex: 0 0 100%; text-align: left;
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 400; color: var(--goblin-ink);
}

/* ---------- Payment ----------
 * WooCommerce tints this box `rgba(129,110,153,.14)` and draws a lilac arrow
 * under the selected method with a `::before` triangle. Both go: the plate it
 * sits in is the box, and the methods are a list of choices exactly like the
 * shipping ones above them — same radios, same spacing, same accent. */
.woocommerce-checkout #payment {
	margin-top: 4px; padding-top: 14px;
	background: none; border-radius: 0; border-top: 1px solid var(--goblin-edge);
}
.woocommerce-checkout #payment ul.payment_methods {
	margin: 0; padding: 0; border: 0;
	display: grid; gap: 10px; list-style: none;
}
.woocommerce-checkout #payment ul.payment_methods::before,
.woocommerce-checkout #payment ul.payment_methods::after,
.woocommerce-checkout #payment ul.payment_methods li::before,
.woocommerce-checkout #payment ul.payment_methods li::after { content: none; display: none; }
.woocommerce-checkout #payment ul.payment_methods li {
	margin: 0; padding: 0; line-height: 1.45; list-style: none;
}
.woocommerce-checkout #payment ul.payment_methods li input.input-radio {
	width: 15px; height: 15px; margin: 0 9px 0 0; accent-color: var(--goblin-gold);
}
.woocommerce-checkout #payment ul.payment_methods li label {
	display: inline; margin: 0;
	font-family: var(--goblin-ui); font-size: 0.85rem; font-weight: 500; color: var(--goblin-ink);
}
/* The method's own blurb, once chosen. Woo gives it the lilac again plus a
 * triangle; it is the stone band the archive toolbar sits on instead. */
.woocommerce-checkout #payment div.payment_box {
	margin: 8px 0 0; padding: 10px 12px;
	background: var(--goblin-stone); border-radius: var(--goblin-radius);
	font-size: 0.8rem; line-height: 1.5; color: var(--goblin-ink-soft);
}
.woocommerce-checkout #payment div.payment_box::before { content: none; display: none; }
.woocommerce-checkout #payment div.payment_box p:last-child { margin-bottom: 0; }

/* ---------- Terms, and the button ---------- */
.woocommerce-checkout .woocommerce-terms-and-conditions-wrapper { margin: 14px 0 0; }
.woocommerce-checkout .woocommerce-privacy-policy-text { font-size: 0.76rem; line-height: 1.5; color: var(--goblin-ink-soft); }
.woocommerce-checkout .woocommerce-privacy-policy-text p:last-child { margin-bottom: 0; }
/* The full terms, when the reader opens them: a stone well with its own scroll,
 * so a thousand words of delivery policy does not push the button off the page. */
.woocommerce-checkout .woocommerce-terms-and-conditions {
	margin: 12px 0 0; padding: 12px 14px;
	background: var(--goblin-stone);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	font-size: 0.8rem; line-height: 1.55; color: var(--goblin-ink-soft);
}
.woocommerce-checkout .woocommerce-terms-and-conditions h2 { font-size: 0.95rem; margin: 0 0 8px; }
.woocommerce-checkout .form-row.validate-required > .woocommerce-form__label-for-checkbox { margin-top: 12px; }
.woocommerce-checkout .woocommerce-terms-and-conditions-checkbox-text { font-size: 0.82rem; }

/* The one thing to press, so it is the cart's checkout button: the card's
 * add-to-cart at the product page's 48px, the full width of the plate it closes.
 * What it replaced was `button.alt` in #720eec — the lilac that is in no palette
 * on this site and that the cart and the product page have both already lost. */
.woocommerce-checkout .place-order { margin: 16px 0 0; padding: 0; }
.woocommerce-checkout #place_order {
	display: flex; align-items: center; justify-content: center; text-align: center;
	width: 100%; min-height: 48px; margin: 0; padding: 12px 22px; float: none;
	border: 0; border-radius: var(--goblin-radius);
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.95rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-transform: none;
	cursor: pointer;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce-checkout #place_order:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}

/* Every other button on the checkout is secondary — "Login", "Apply coupon" —
 * and secondary on this site is the pagination tile: white, one hairline, the
 * card shadow, gold on hover. */
.woocommerce-checkout form.login button.button,
.woocommerce-checkout form.checkout_coupon button.button {
	width: auto; float: none; margin: 0;
	padding: 9px 16px; min-height: 0;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.85rem; font-weight: 600;
	line-height: 1.3; letter-spacing: 0.01em; text-transform: none;
	white-space: nowrap; cursor: pointer;
}
.woocommerce-checkout form.login button.button:hover,
.woocommerce-checkout form.checkout_coupon button.button:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* WooCommerce's own "processing" veil, which is otherwise a white sheet with the
 * plugin's spinner in the middle of the page. */
.woocommerce-checkout .blockUI.blockOverlay { border-radius: var(--goblin-radius); }

/* ---------- Wide enough for two fields on a row ---------- */
@media (min-width: 520px) {
	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
	.woocommerce-checkout .form-row-wide,
	.woocommerce-checkout .form-row.notes { grid-column: 1 / -1; }
	.woocommerce-checkout .form-row-first { grid-column: 1; }
	.woocommerce-checkout .form-row-last { grid-column: 2; }
}

/* 1060 is where the summary can sit beside the fields instead of under them —
 * the same width the cart's summary steps at, so the two pages of the purchase
 * path change shape together. 380 rather than the cart's 330: this plate holds
 * the lines *and* the totals *and* the payment methods, and a product name in
 * 330 wraps to three lines beside its price.
 *
 * Deliberately **not** sticky, unlike the cart's summary. That one is six rows
 * and a button and is always shorter than the viewport; this one carries the
 * lines, the totals, the payment methods, the privacy text and the button, and a
 * sticky box taller than the screen pins its top and puts its bottom — which is
 * "Place order" — out of reach. */
@media (min-width: 1060px) {
	.woocommerce-checkout form.checkout {
		grid-template-columns: minmax(0, 1fr) 380px;
		gap: 26px;
	}
}

/* ---------- The account pages ----------
 * See inc/account.php. `/my-account/` logged in, and every endpoint under it:
 * the dashboard, the orders list, one order, downloads, the address book and
 * "Account details". Written **mobile first**, like the cart and the checkout
 * above and unlike the rest of this file: everything outside the `min-width`
 * blocks at the end of the section is the phone.
 *
 * Two objects, and both are the product card's plate — white, one hairline, the
 * shared radius, the card shadow: the endpoint menu, and the box beside it that
 * every endpoint prints into. Everything inside them is borrowed too. The active
 * row's gold left edge is the notice's coloured rule, the small uppercase
 * headings are the product meta rows' label, the fields are the checkout's (the
 * same rules, not a copy — see The fields above), "Order again" is the cart's
 * checkout button, `View` and the two pager ends are the pagination tile, and an
 * order's totals are the cart summary's rows.
 *
 * The menu is a plate rather than the plain text this design gives most of its
 * navigation, and that is the ground's doing: the paper halo carries ink over
 * the line-art pattern at hero and section-heading sizes, not at the 0.82rem a
 * six-item endpoint list wants. A plate is what small type sits on here.
 *
 * WooCommerce prints the menu and the content as two floats — 30% and 68% of
 * whatever holds them — and this replaces both with one grid. The grid's parent
 * is the `<div class="woocommerce">` the `[woocommerce_my_account]` shortcode
 * wraps its own output in, because that is already the only element that is a
 * parent of both and there is no hook between it and them. No wrapper is added
 * and no template is overridden.
 */

/* When the menu is there, and only then.
 *
 * `.woocommerce-account` alone is not the test and neither is `.logged-in`:
 * `/my-account/lost-password/` carries both and prints one narrow form with no
 * menu beside it, and so does the logged-out login screen. Both want the 820px
 * reading measure `page.php` caps a content page at; a list of orders beside a
 * menu wants the container's own 1280, exactly as the cart does.
 *
 * `:has()` is the honest way to say that — the two-column layout is on when
 * there are two columns — and it is used once already in this file, on the
 * empty notices wrapper. A browser without it gets the measure and one column,
 * which is the phone layout on a wide screen: plain, and nothing broken. */
.goblin-page__content:has(.woocommerce-MyAccount-navigation) { max-width: none; }
.woocommerce-account .woocommerce:has(> .woocommerce-MyAccount-navigation) {
	display: grid; align-items: start;
	gap: 16px;
	margin-top: 4px;
}
/* Woo's two floats, and the widths that go with them. */
.woocommerce-account .woocommerce-MyAccount-navigation,
.woocommerce-account .woocommerce-MyAccount-content {
	float: none; width: auto; margin: 0;
}
/* And the clearfix WooCommerce hangs off this exact element to contain those two
 * floats (`.woocommerce-account .woocommerce::before/::after`, woocommerce.css).
 * A pseudo-element is a grid item like any other, so left in they take a cell
 * each: `::before` claims the menu's, the menu is pushed into the content
 * column, and the content drops to a second row 236px wide with its orders table
 * hanging out of the plate. Same fix, and the same reason, as the cart's
 * `.cart-collaterals` and the login screen's `#customer_login`. */
.woocommerce-account .woocommerce:has(> .woocommerce-MyAccount-navigation)::before,
.woocommerce-account .woocommerce:has(> .woocommerce-MyAccount-navigation)::after { content: none; }

/* ---------- The endpoint menu ----------
 * A plate holding one link per row, and the rows are separated by hairlines
 * rather than spaced apart — six items with 6px between them is a stack of
 * buttons, six items sharing a rule is a menu.
 *
 * Two columns here and one at 900, which is the same grid changing its template
 * that the cart's lines make at 720. Six rows stacked on a phone is 230px of
 * menu before the first order, the same quarter-of-a-viewport the archive header
 * was rebuilt to stop spending; three rows of two is 115px and nothing scrolls
 * sideways to be found. The hairlines are drawn per item rather than by a 1px
 * grid gap over a grey ground, so an odd number of items — WooCommerce drops
 * "Downloads" for a customer who has never bought one — leaves a white cell
 * rather than a grey one. */
.woocommerce-account .woocommerce-MyAccount-navigation {
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow); overflow: hidden;
}
.woocommerce-account .woocommerce-MyAccount-navigation ul {
	display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
	margin: 0; padding: 0; list-style: none;
}
.woocommerce-account .woocommerce-MyAccount-navigation li { margin: 0; padding: 0; list-style: none; }
.woocommerce-account .woocommerce-MyAccount-navigation li:nth-child(n+3) { border-top: 1px solid var(--goblin-edge); }
.woocommerce-account .woocommerce-MyAccount-navigation li:nth-child(2n) { border-left: 1px solid var(--goblin-edge); }
.woocommerce-account .woocommerce-MyAccount-navigation li a {
	display: block; height: 100%;
	padding: 11px 13px;
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 600; line-height: 1.35;
	color: var(--goblin-ink-soft); text-decoration: none;
	transition: background-color 0.15s ease, color 0.15s ease;
}
.woocommerce-account .woocommerce-MyAccount-navigation li a:hover {
	background: var(--goblin-stone); color: var(--goblin-ink);
}
/* Where you are: the notice's coloured rule, in gold, on the leading edge — the
 * same 3px the notices carry, and the same idea. An inset shadow rather than a
 * border so the row does not move by 3px when it becomes the active one. */
.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
	box-shadow: inset 3px 0 0 var(--goblin-gold);
	color: var(--goblin-ink); font-weight: 700;
}
/* The way out is not one of the five places you can go, so it is set quieter and
 * turns red under the pointer — the same grey-until-hovered arrangement the
 * cart's remove has, and for the same reason: one destructive item in a list
 * should not be the first thing the eye lands on. */
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a { color: var(--goblin-gray); }
.woocommerce-account .woocommerce-MyAccount-navigation-link--customer-logout a:hover {
	background: var(--goblin-stone); color: var(--goblin-red-ink);
}

/* ---------- The box every endpoint prints into ---------- */
.woocommerce-account .woocommerce-MyAccount-content {
	padding: 16px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.6;
	color: var(--goblin-ink);
}
.woocommerce-account .woocommerce-MyAccount-content > p { margin: 0 0 12px; }
.woocommerce-account .woocommerce-MyAccount-content > *:last-child { margin-bottom: 0; }
/* A link in a sentence is the quiet one the "Lost your password?" link already
 * is — ink-soft with the hairline under it — and not the site's red, which is
 * the shop's accent and turns four links in two sentences into a warning. */
.woocommerce-account .woocommerce-MyAccount-content p a {
	color: var(--goblin-ink-soft);
	text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px;
}
.woocommerce-account .woocommerce-MyAccount-content p a:hover { color: var(--goblin-gold-ink); }
/* A notice printed inside this plate is a plate inside a plate; it keeps its
 * hairline and its coloured edge and gives up the shadow, which is what says
 * "this box is lying on the page" and is already said by the box around it. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-error,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-info,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-message { box-shadow: none; }

/* Every heading inside the box is a label for the block under it — "Order
 * details", "Billing address", "Shipping address" — and not a headline over the
 * page, which is what the `<h1>` in `.goblin-page__header` already is. The
 * product meta rows' label, same as the cart summary's `<h2>` and the checkout's
 * section headings. The tags are right; only the sizes were wrong. */
.woocommerce-account .woocommerce-MyAccount-content h2,
.woocommerce-account .woocommerce-MyAccount-content h3,
.woocommerce-account .woocommerce-MyAccount-content legend {
	margin: 0 0 12px; padding: 0;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.3;
	color: var(--goblin-ink-soft);
}

/* ---------- The dashboard ----------
 * Two paragraphs of WooCommerce's own copy, and the first is the only line on
 * the site that greets the reader by name. It gets the display face and a rule
 * under it so the page has a top rather than opening on a block of running text;
 * the second stays body copy, because it is a sentence of links. */
.woocommerce-dashboard .woocommerce-MyAccount-content > p:first-of-type {
	margin: 0 0 12px; padding-bottom: 12px;
	border-bottom: 1px solid var(--goblin-edge);
	font-family: var(--goblin-display); font-size: 1.02rem; font-weight: 600; line-height: 1.4;
	color: var(--goblin-ink);
}
.woocommerce-dashboard .woocommerce-MyAccount-content > p:first-of-type strong { font-weight: 600; }
.woocommerce-dashboard .woocommerce-MyAccount-content > p + p { color: var(--goblin-ink-soft); }

/* ---------- The orders list ----------
 * WooCommerce prints it as a `shop_table`, and on a phone an order is not a
 * record in one: it is a number, a date, a total and a way in. So the table is
 * unpicked into a grid whose template changes at 760px — six values across with
 * a header row above them, or a block with the number and its status on the
 * first line and the button in the bottom corner — which is the same trade the
 * cart's lines make at 720.
 *
 * The cells are placed by class on the phone and left to source order on the
 * desktop, because the header row's classes are `__header-order-*` and the body
 * row's are `__cell-order-*`: they cannot share one map the way the cart's `th`s
 * and `td`s do, but both rows do have the same five children in the same order.
 * The desktop block therefore returns every cell to `auto` rather than naming
 * five more areas. */
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads {
	display: block; width: 100%; margin: 0;
	background: none; border: 0; border-radius: 0;
	border-collapse: separate; border-spacing: 0;
	font-family: var(--goblin-ui); font-size: 0.86rem;
}
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table thead,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads thead { display: none; }
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table tbody,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads tbody { display: block; }
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table th,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table td,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads th,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads td {
	display: block; padding: 0; border: 0;
	font-weight: 400; text-align: left; line-height: 1.45;
}
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table tbody tr {
	display: grid; grid-template-columns: minmax(0, 1fr) auto;
	gap: 3px 14px;
	padding: 13px 0;
	border-top: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table tbody tr:first-child {
	padding-top: 0; border-top: 0;
}
/* The number is the row's name and its way in, so it is the row's biggest thing
 * and the whole of it is the link — set in ink rather than in the site's red,
 * which on ten rows of a list is ten warnings. */
.woocommerce-orders-table__cell-order-number {
	grid-column: 1; grid-row: 1;
	font-family: var(--goblin-display); font-size: 0.98rem; font-weight: 600;
}
.woocommerce-orders-table__cell-order-number a { color: var(--goblin-ink); text-decoration: none; }
.woocommerce-orders-table__cell-order-number a:hover { color: var(--goblin-gold-ink); }
/* The status is a word, not a badge — this design has no chips, so it is carried
 * by case, tracking and one colour, which is the same treatment the section
 * headings and the language switcher were given when their tiles came off.
 * Colour comes off the row's own `--status-*` class. */
.woocommerce-orders-table__cell-order-status {
	grid-column: 2; grid-row: 1;
	font-size: 0.66rem; font-weight: 700; letter-spacing: 0.12em;
	text-transform: uppercase; color: var(--goblin-gray);
}
/* It shares the right-hand column with the button under it, so it hangs off the
 * same edge. The prefix is the one the cells were set `left` with three rules
 * above; without it this loses to that rule whatever the source order. */
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table .woocommerce-orders-table__cell-order-status { text-align: right; }
.woocommerce-orders-table__row--status-completed .woocommerce-orders-table__cell-order-status { color: var(--goblin-green); }
.woocommerce-orders-table__row--status-processing .woocommerce-orders-table__cell-order-status,
.woocommerce-orders-table__row--status-on-hold .woocommerce-orders-table__cell-order-status { color: var(--goblin-gold-ink); }
.woocommerce-orders-table__row--status-cancelled .woocommerce-orders-table__cell-order-status,
.woocommerce-orders-table__row--status-failed .woocommerce-orders-table__cell-order-status,
.woocommerce-orders-table__row--status-refunded .woocommerce-orders-table__cell-order-status { color: var(--goblin-red-ink); }
.woocommerce-orders-table__cell-order-date {
	grid-column: 1; grid-row: 2;
	font-size: 0.78rem; color: var(--goblin-ink-soft);
}
.woocommerce-orders-table__cell-order-total {
	grid-column: 1; grid-row: 3;
	font-family: var(--goblin-display); font-weight: 600; color: var(--goblin-ink);
}
/* A flex row and not a cell with a button in it, because an order can carry more
 * than one action — "Pay" and "Cancel" both appear on a pending one. */
.woocommerce-orders-table__cell-order-actions {
	grid-column: 2; grid-row: 3; align-self: end;
	display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px;
}

/* ---------- Downloads ----------
 * The shop sells board games, so this table is empty for every customer it has
 * ever had and the endpoint prints a notice instead. It is styled anyway, at the
 * cost of one grid, because the day something downloadable is listed the page
 * should not be the only one in the account area still wearing WooCommerce's
 * borders. Rows are the orders list's, without the placement — a download is a
 * name, a remaining count and a button, and they read fine stacked. */
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads tbody tr {
	display: grid; gap: 3px;
	padding: 13px 0;
	border-top: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads tbody tr:first-child {
	padding-top: 0; border-top: 0;
}
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads td.download-file { margin-top: 6px; }

/* ---------- The buttons in a list ----------
 * `View`, `Pay`, `Cancel`, `Download` and the two ends of the pager are the
 * pagination tile — a white sheet, one hairline, the shared radius and the card
 * shadow, going gold under the pointer. That is already this site's vocabulary
 * for "a control that moves you through a list". Smaller than the pager's 44px
 * where it sits inside a row, at 34, because there it is one cell of five and
 * not the end of the page. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-orders-table__cell-order-actions a.button,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads a.button {
	display: inline-flex; align-items: center; justify-content: center;
	min-height: 34px; padding: 0 14px;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.78rem; font-weight: 600;
	line-height: 1.2; letter-spacing: 0; text-transform: none; text-decoration: none;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-orders-table__cell-order-actions a.button:hover,
.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-MyAccount-downloads a.button:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* ---------- The pager ----------
 * Not the pagination block above: the orders list is the one pager on the site
 * with no numbers in it (`woocommerce-pagination--without-numbers`, two `<a>`s
 * and no `<ul>`), so it gets the tile at the pager's own 44px here. `Previous`
 * is pushed to the far side by its own auto margin rather than by
 * `space-between`, which would put a lone `Next` — page one of two — on the
 * left, where the reader has just been told there is nothing. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-pagination--without-numbers {
	display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px;
	margin: 16px 0 0; padding-top: 14px;
	border-top: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-button--previous { margin-right: auto; }
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-pagination--without-numbers a.woocommerce-button {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 44px; height: 44px; padding: 0 16px;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-display); font-size: 0.9rem; font-weight: 600;
	line-height: 1; text-decoration: none;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-pagination--without-numbers a.woocommerce-button:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* ---------- One order ----------
 * `view-order`. The sentence at the top carries three `<mark>`s, which Woo
 * already strips the browser's yellow off; they are the values in it, so they
 * take the display face rather than the bold body copy they had.
 *
 * The `order_details` table below is the cart summary, twice: the goods are the
 * cart's lines, the `<tfoot>` is the cart's totals — label left, number right,
 * the last row bigger and in ink because it is the one number the page is about.
 * The two are the same object because they are the same thing, an order, read
 * before it is placed and after.
 *
 * **This block is shared with the thank-you page**, which prints the same table
 * and the same address blocks from the same template (`order/order-details.php`
 * and `order/order-details-customer.php`) — so every rule from here to the end
 * of Addresses carries `.woocommerce-order-received .woocommerce-order`
 * alongside the account scope rather than being written twice. The two prefixes
 * are two classes each, so they are the same specificity and neither can
 * quietly win over the other. Same arrangement as the fields, which the checkout
 * and the account pages share. An order is one object on this site and is set
 * once; if a rule here should apply on only one of the two pages, that is worth
 * saying out loud rather than by dropping a selector. The rest of the thank-you
 * page — its plate, its confirmation line and its overview strip — is in
 * The order pages below. */
.woocommerce-account .woocommerce-MyAccount-content .order-number,
.woocommerce-account .woocommerce-MyAccount-content .order-date,
.woocommerce-account .woocommerce-MyAccount-content .order-status {
	font-family: var(--goblin-display); font-weight: 600; color: var(--goblin-ink);
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-order-details,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details,
.woocommerce-order-received .woocommerce-order .woocommerce-order-details,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details {
	margin: 18px 0 0; padding-top: 16px;
	border-top: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details,
.woocommerce-order-received .woocommerce-order table.order_details {
	display: block; width: 100%; margin: 0;
	background: none; border: 0; border-radius: 0;
	border-collapse: separate; border-spacing: 0;
	font-family: var(--goblin-ui); font-size: 0.86rem;
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details thead,
.woocommerce-account .woocommerce-MyAccount-content table.order_details tbody,
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot,
.woocommerce-order-received .woocommerce-order table.order_details thead,
.woocommerce-order-received .woocommerce-order table.order_details tbody,
.woocommerce-order-received .woocommerce-order table.order_details tfoot { display: block; }
.woocommerce-account .woocommerce-MyAccount-content table.order_details th,
.woocommerce-account .woocommerce-MyAccount-content table.order_details td,
.woocommerce-order-received .woocommerce-order table.order_details th,
.woocommerce-order-received .woocommerce-order table.order_details td {
	padding: 0; border: 0; text-align: left; line-height: 1.45;
}
/* The header keeps its row — two words that name two columns, which is worth a
 * line on an order of six items — set as the small label everything else in this
 * box uses. */
.woocommerce-account .woocommerce-MyAccount-content table.order_details thead tr,
.woocommerce-order-received .woocommerce-order table.order_details thead tr {
	display: grid; grid-template-columns: minmax(0, 1fr) auto;
	gap: 14px; padding-bottom: 8px;
	border-bottom: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details thead th,
.woocommerce-order-received .woocommerce-order table.order_details thead th {
	font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em;
	text-transform: uppercase; color: var(--goblin-ink-soft);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details thead th.product-total,
.woocommerce-order-received .woocommerce-order table.order_details thead th.product-total { text-align: right; }
.woocommerce-account .woocommerce-MyAccount-content table.order_details tbody tr,
.woocommerce-order-received .woocommerce-order table.order_details tbody tr {
	display: grid; grid-template-columns: minmax(0, 1fr) auto;
	gap: 4px 14px; padding: 11px 0;
	border-bottom: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details td.product-name a,
.woocommerce-order-received .woocommerce-order table.order_details td.product-name a {
	color: var(--goblin-ink); font-weight: 500; text-decoration: none;
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details td.product-name a:hover,
.woocommerce-order-received .woocommerce-order table.order_details td.product-name a:hover { color: var(--goblin-gold-ink); }
.woocommerce-account .woocommerce-MyAccount-content table.order_details .product-quantity,
.woocommerce-order-received .woocommerce-order table.order_details .product-quantity {
	font-weight: 600; color: var(--goblin-ink-soft); white-space: nowrap;
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details td.product-total,
.woocommerce-order-received .woocommerce-order table.order_details td.product-total {
	text-align: right; white-space: nowrap;
	font-family: var(--goblin-display); font-weight: 600; color: var(--goblin-ink);
}
/* The cart summary's rows. */
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot tr,
.woocommerce-order-received .woocommerce-order table.order_details tfoot tr {
	display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
	gap: 6px 14px; padding: 9px 0;
	border-bottom: 1px solid var(--goblin-edge);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot tr:last-child,
.woocommerce-order-received .woocommerce-order table.order_details tfoot tr:last-child { border-bottom: 0; }
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot th,
.woocommerce-order-received .woocommerce-order table.order_details tfoot th {
	flex: 0 0 auto;
	font-family: var(--goblin-ui); font-size: 0.78rem; font-weight: 600;
	color: var(--goblin-ink-soft);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot td,
.woocommerce-order-received .woocommerce-order table.order_details tfoot td {
	flex: 1 1 auto; text-align: right;
	font-family: var(--goblin-display); font-size: 0.92rem; font-weight: 600;
	color: var(--goblin-ink);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot tr:last-child th,
.woocommerce-order-received .woocommerce-order table.order_details tfoot tr:last-child th {
	font-size: 0.86rem; color: var(--goblin-ink);
}
.woocommerce-account .woocommerce-MyAccount-content table.order_details tfoot tr:last-child td,
.woocommerce-order-received .woocommerce-order table.order_details tfoot tr:last-child td { font-size: 1.22rem; }

/* "Order again" is the one thing on this page that puts something in the cart,
 * so it is the cart's checkout button: gold, at the product page's 48px. It is
 * not full width — that button is the single action of a summary column, and
 * this one sits under a table in a box the width of the page. */
.woocommerce-account .woocommerce-MyAccount-content p.order-again { margin: 16px 0 0; }
.woocommerce-account .woocommerce-MyAccount-content p.order-again a.button {
	display: inline-flex; align-items: center; justify-content: center;
	min-height: 48px; padding: 12px 26px;
	background: var(--goblin-gold); color: #241a05;
	border: 0; border-radius: var(--goblin-radius);
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.95rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-transform: none; text-decoration: none;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce-account .woocommerce-MyAccount-content p.order-again a.button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}

/* ---------- Addresses ----------
 * Two of them, and each is a well inside the plate rather than a plate of its
 * own: stone with a hairline and no shadow. A card lying on a card is two things
 * the eye has to separate before it can read either, and there is nothing here
 * to separate — they are the same kind of thing twice.
 *
 * The address book's `col2-set` floats are dropped for the grid, and Woo's
 * clearfix pseudo-elements with them; left in, they take a grid cell each and
 * push the billing address into the second column. Same fix as the cart's
 * `.cart-collaterals` and the login screen's `#customer_login`. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Addresses { display: grid; gap: 14px; }
.woocommerce-account .woocommerce-MyAccount-content .col2-set::before,
.woocommerce-account .woocommerce-MyAccount-content .col2-set::after { content: none; }
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address {
	float: none; width: auto;
	padding: 14px;
	background: var(--goblin-stone);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address-title {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: 12px; margin: 0 0 8px;
}
/* This header has a clearfix of its own (`.woocommerce-account .addresses
 * .title::before/::after`), and a pseudo-element is a flex item exactly as it is
 * a grid item: left in, the row is four items and `space-between` pins two empty
 * boxes to the edges with the heading and the link floating in the middle. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address-title::before,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address-title::after { content: none; }
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address-title h2 { margin: 0; }
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address-title a.edit {
	flex: 0 0 auto;
	font-size: 0.76rem; font-weight: 600; color: var(--goblin-ink-soft);
	text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px;
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Address-title a.edit:hover { color: var(--goblin-gold-ink); }
.woocommerce-account .woocommerce-MyAccount-content address,
.woocommerce-order-received .woocommerce-order address {
	margin: 0; padding: 0; border: 0;
	font-style: normal; font-size: 0.86rem; line-height: 1.65; color: var(--goblin-ink);
}
/* One order's billing block is the same well, standing on its own — and it is
 * the same well on the thank-you page, which prints this section from the same
 * template. See One order above for why both scopes are here. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details address,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details address {
	padding: 13px 14px;
	background: var(--goblin-stone);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
/* Billing and delivery are a pair — which address is which — so they are the
 * address book's grid, not the 48/48 floats WooCommerce prints them as. Those
 * floats had never been undone here, and on a phone they left two 201px columns
 * side by side in a 390px viewport with the second one hanging out of the plate:
 * the account page dropped the small-screen sheet that would have stacked them,
 * and the clearfix that contained them is `content: none` in Addresses below.
 *
 * The account's copy of this section survived on a technicality — it sits in a
 * grid item, which contains a float the way a clearfix does — and the thank-you
 * page's does not, so there the floats escaped the plate altogether and the
 * footer wrapped around them. A grid needs neither. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details .addresses,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details .addresses {
	display: grid; gap: 14px;
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details .col-1,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details .col-2,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details .col-1,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details .col-2 {
	float: none; width: auto; margin: 0;
}
/* The phone and the email are two more lines of the address, so they are set as
 * lines of it. WooCommerce hangs a glyph from its own icon font in front of each
 * and indents them 1.5em to clear it; the glyph is a chip's worth of decoration
 * on a page that has none, and on any reader whose browser has not fetched that
 * font it is a tofu box — which is exactly what it renders as today. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details--phone,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details--email,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details--phone,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details--email {
	margin: 6px 0 0; padding-left: 0;
	font-size: 0.82rem; color: var(--goblin-ink-soft);
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details--phone::before,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details--email::before,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details--phone::before,
.woocommerce-order-received .woocommerce-order .woocommerce-customer-details--email::before { content: none; }

/* ---------- The two forms ----------
 * The address book's edit screen and "Account details". The fields themselves
 * are the checkout's — those rules carry `.woocommerce-MyAccount-content` in
 * their selector lists, see The fields above — so what is left here is the grid
 * they sit in and the button under them.
 *
 * `form.edit-account` has no field wrapper of its own: its rows are direct
 * children of the form, mixed in with a `<fieldset>` and the paragraph holding
 * the submit. So the form is the grid on that page and the wrapper is the grid
 * on the other, and Woo's float clearing `<div class="clear">` is dropped in
 * both, because a grid does not clear anything and an empty div takes a cell. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-address-fields__field-wrapper,
.woocommerce-account .woocommerce-MyAccount-content form.edit-account { display: grid; gap: 12px; }
/* A measure, because a form is read down a column and not across a page: the box
 * these sit in is as wide as the orders list needs to be, and at 1280 that left
 * "Confirm new password" as a 945px field with eight characters in it. 720 is
 * the two name fields at about the width the checkout gives them. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-address-fields,
.woocommerce-account .woocommerce-MyAccount-content form.edit-account { max-width: 720px; }
.woocommerce-account .woocommerce-MyAccount-content .clear { display: none; }
.woocommerce-account .woocommerce-MyAccount-content form.edit-account > fieldset {
	margin: 4px 0 0; padding: 14px;
	background: var(--goblin-stone);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
}
.woocommerce-account .woocommerce-MyAccount-content form.edit-account > fieldset > .form-row + .form-row { margin-top: 12px; }
/* A `<legend>` is drawn straddling the fieldset's top border by the browser, and
 * this fieldset has a border — so "Password change" was sitting in a gap chewed
 * out of the top edge of the well. Floating it opts out of that rendering and
 * makes it an ordinary block; the row after it clears the float. */
.woocommerce-account .woocommerce-MyAccount-content form.edit-account > fieldset > legend {
	float: left; width: 100%;
}
.woocommerce-account .woocommerce-MyAccount-content form.edit-account > fieldset > legend + .form-row { clear: both; }

/* Two pieces of WooCommerce's float scaffolding on a field row, which a grid has
 * no use for: the 6px bottom margin that spaced the floats (the grid's own gap
 * does that now, and the margin is added to it) and the clearfix pair that
 * contained them. `content: " "` in a `display: table` box is a space with a line
 * box round it, so each row was carrying about 11px of empty table above and
 * below its label — the reason the fields looked further apart than the 12px
 * gap says they are.
 *
 * Scoped here rather than added to the shared rules above, deliberately: the
 * checkout carries both as well and is not this change. Worth doing there too,
 * next time that page is open. */
.woocommerce-account .woocommerce-MyAccount-content .form-row { margin: 0; }
.woocommerce-account .woocommerce-MyAccount-content .form-row::before,
.woocommerce-account .woocommerce-MyAccount-content .form-row::after { content: none; }
/* The hint under "Display name". Woo sets it in an `<em>` with no rule of its
 * own, so it inherited the field's size and read as a second label. */
.woocommerce-account .woocommerce-MyAccount-content .form-row span > em,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-password-hint {
	display: block; margin-top: 5px;
	font-size: 0.76rem; font-style: normal; line-height: 1.5; color: var(--goblin-ink-soft);
}
/* WooCommerce's strength meter, which ships as a pastel green/orange/red slab
 * across the field under it. It says one word; it is set as one word, in the
 * colour that word means — the same three colours the order statuses use. */
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-password-strength {
	margin-top: 6px; padding: 0;
	background: none; border: 0;
	font-family: var(--goblin-ui); font-size: 0.68rem; font-weight: 700;
	letter-spacing: 0.12em; text-transform: uppercase; text-align: left;
	color: var(--goblin-ink-soft);
}
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-password-strength.strong { color: var(--goblin-green); }
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-password-strength.good { color: var(--goblin-gold-ink); }
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-password-strength.bad,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-password-strength.short { color: var(--goblin-red-ink); }

/* The gold button, at the product page's 48px. Not full width, for the reason
 * "Order again" is not: this is a form inside a box as wide as the page, not the
 * single action of a summary column. */
.woocommerce-account .woocommerce-MyAccount-content form button.button,
.woocommerce-account .woocommerce-MyAccount-content form input.button {
	display: inline-flex; align-items: center; justify-content: center;
	min-height: 48px; margin: 0; padding: 12px 26px; float: none;
	background: var(--goblin-gold); color: #241a05;
	border: 0; border-radius: var(--goblin-radius);
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.95rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-transform: none; cursor: pointer;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce-account .woocommerce-MyAccount-content form button.button:hover,
.woocommerce-account .woocommerce-MyAccount-content form input.button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}
/* The paragraph the submit sits in also holds three hidden inputs, so it needs
 * no rule beyond closing the gap the form's own gap already opened. */
.woocommerce-account .woocommerce-MyAccount-content form.edit-account > p:last-of-type,
.woocommerce-account .woocommerce-MyAccount-content .woocommerce-address-fields > p:last-of-type { margin: 4px 0 0; }

/* ---------- Lost password ----------
 * `/my-account/lost-password/` and the reset form the emailed link lands on.
 * Neither has the endpoint menu beside it — WooCommerce prints the form on its
 * own — so this is the one account screen that is not in the grid above, and it
 * gets the login screen's plate at the width of the one field in it. */
.woocommerce-account form.woocommerce-ResetPassword {
	max-width: 460px; margin: 0;
	padding: 18px 18px 20px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
}
.woocommerce-account form.woocommerce-ResetPassword > p:first-child {
	margin: 0 0 14px;
	font-size: 0.85rem; line-height: 1.5; color: var(--goblin-ink-soft);
}
.woocommerce-account form.woocommerce-ResetPassword .form-row {
	float: none; width: auto; margin: 0 0 12px; padding: 0;
}
.woocommerce-account form.woocommerce-ResetPassword .form-row label {
	display: block; margin: 0 0 5px;
	font-family: var(--goblin-ui); font-size: 0.74rem; font-weight: 600; line-height: 1.35;
	color: var(--goblin-ink-soft);
}
.woocommerce-account form.woocommerce-ResetPassword .form-row label .required { color: var(--goblin-red); text-decoration: none; border: 0; }
.woocommerce-account form.woocommerce-ResetPassword input.input-text {
	display: block; width: 100%; margin: 0;
	padding: 9px 11px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	outline: 0; box-shadow: none;
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.4; color: var(--goblin-ink);
}
.woocommerce-account form.woocommerce-ResetPassword input.input-text:hover { border-color: var(--goblin-edge-dark); }
.woocommerce-account form.woocommerce-ResetPassword input.input-text:focus {
	border-color: var(--goblin-gold);
	box-shadow: 0 0 0 3px rgba(224, 168, 30, 0.22);
}
.woocommerce-account form.woocommerce-ResetPassword .clear { display: none; }
.woocommerce-account form.woocommerce-ResetPassword button.button {
	display: flex; align-items: center; justify-content: center;
	width: 100%; min-height: 48px; margin: 0; padding: 12px 22px; float: none;
	background: var(--goblin-gold); color: #241a05;
	border: 0; border-radius: var(--goblin-radius);
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.95rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-transform: none; cursor: pointer;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce-account form.woocommerce-ResetPassword button.button:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}

/* ---------- Wide enough for two fields on a row ----------
 * 620 rather than the checkout's 520: these forms sit inside a box that is
 * itself inside the grid, so the field row is about 100px narrower than the
 * checkout's at the same viewport. */
@media (min-width: 620px) {
	.woocommerce-account .woocommerce-MyAccount-content .woocommerce-address-fields__field-wrapper,
	.woocommerce-account .woocommerce-MyAccount-content form.edit-account {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
	.woocommerce-account .woocommerce-MyAccount-content .form-row-wide,
	.woocommerce-account .woocommerce-MyAccount-content form.edit-account > fieldset,
	.woocommerce-account .woocommerce-MyAccount-content form.edit-account > p:last-of-type { grid-column: 1 / -1; }
	.woocommerce-account .woocommerce-MyAccount-content .form-row-first { grid-column: 1; }
	.woocommerce-account .woocommerce-MyAccount-content .form-row-last { grid-column: 2; }
	/* Two addresses side by side. They are four short lines each and they are read
	 * as a pair — which is billing and which is delivery — so they go across as
	 * soon as they fit rather than waiting for the desktop breakpoint. The order's
	 * pair does the same at the same width, on both pages that print it. */
	.woocommerce-account .woocommerce-MyAccount-content .woocommerce-Addresses,
	.woocommerce-account .woocommerce-MyAccount-content .woocommerce-customer-details .addresses,
	.woocommerce-order-received .woocommerce-order .woocommerce-customer-details .addresses {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 16px;
	}
}

/* ---------- Wide enough for the orders list to be a table ----------
 * 760, which is where five columns stop being an abbreviation of an order and
 * start being a row of it. Below this the same cells are the block above; here
 * they go back to source order, which is the order the header row names them in. */
@media (min-width: 760px) {
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table thead { display: block; }
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table thead tr,
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table tbody tr {
		display: grid;
		grid-template-columns: minmax(86px, 0.8fr) minmax(92px, 0.9fr) minmax(92px, 0.9fr) minmax(118px, 1.1fr) minmax(0, auto);
		align-items: center; gap: 14px;
	}
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table thead tr {
		padding: 0 0 9px; border-bottom: 1px solid var(--goblin-edge);
	}
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table thead th {
		font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em;
		text-transform: uppercase; color: var(--goblin-ink-soft);
	}
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table tbody tr { padding: 12px 0; }
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table tbody tr:first-child {
		padding-top: 12px; border-top: 0;
	}
	/* Back to source order, all five of them, rather than five more named areas. */
	.woocommerce-orders-table__cell,
	.woocommerce-orders-table__header { grid-column: auto; grid-row: auto; }
	/* The two right-hand columns are numbers and a control, so they hang off the
	 * right edge — and the pair of rules that says so has to carry the same
	 * `table` prefix the cells were set `left` with three rules above, or it
	 * loses to it whatever the source order. */
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table .woocommerce-orders-table__header-order-total,
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table .woocommerce-orders-table__cell-order-total,
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table .woocommerce-orders-table__header-order-actions { text-align: right; }
	.woocommerce-account .woocommerce-MyAccount-content table.woocommerce-orders-table .woocommerce-orders-table__cell-order-status { text-align: left; }
	.woocommerce-orders-table__cell-order-date { font-size: 0.82rem; }
}

/* ---------- Wide enough for the menu to stand beside the page ----------
 * 900, the width the rest of this theme calls a desktop. The menu becomes one
 * column of six rows — the same grid, a different template — and the two of them
 * stop being stacked boxes and become a page with a side to it.
 *
 * 236px is what "Account details" needs at 0.82rem with its insets, plus enough
 * that the longest Macedonian label ("Информации за сметката") does not wrap. */
@media (min-width: 900px) {
	.woocommerce-account .woocommerce:has(> .woocommerce-MyAccount-navigation) {
		grid-template-columns: 236px minmax(0, 1fr);
		gap: 22px;
	}
	.woocommerce-account .woocommerce-MyAccount-navigation ul { grid-template-columns: minmax(0, 1fr); }
	.woocommerce-account .woocommerce-MyAccount-navigation li + li { border-top: 1px solid var(--goblin-edge); }
	.woocommerce-account .woocommerce-MyAccount-navigation li:nth-child(2n) { border-left: 0; }
	.woocommerce-account .woocommerce-MyAccount-content { padding: 20px; }
}

/* ---------- The order pages ----------
 * The last two screens on the purchase path: `/checkout/order-received/` — the
 * thank-you page — and `/checkout/order-pay/`, where an unpaid order is settled
 * from a link in an email. Both carry the `woocommerce-checkout` body class, so
 * the checkout's payment box, its terms well and its "Place order" button reach
 * order-pay already and are not repeated here. Written **mobile first**, like
 * the three sections above it.
 *
 * Neither is a new object either. The plate is the product card's, as it is on
 * the account pages; the order's table and its address wells are One order's,
 * shared rather than copied — see the note there; the overview strip is the
 * meta rows' label over the display face, which is how every label-and-number
 * pair on this site is set; and everything below the table on order-pay is the
 * checkout's, inherited by the body class rather than written again.
 *
 * They were the two screens `is_account_page()` did not reach when the account
 * area was done, and the two that kept WooCommerce's own appearance after the
 * checkout was: `is_checkout()` is what covers them, and the only page in this
 * theme that had ever tested for it was the one with the form on it. */

/* Both are receipts, so both take a reading measure rather than the container.
 * The checkout gives up the measure because a form standing beside a summary
 * needs the width; a list of what was bought and where it is going does not,
 * and at 1280px the thank-you page put two four-line addresses 700px apart.
 *
 * The `:not()` pair is on the checkout's own rule above rather than a second
 * rule here, because both selectors would otherwise be two classes and the one
 * that won would be the one that happened to be written second.
 *
 * order-pay is narrower still. It is the checkout's summary plate with nothing
 * beside it — the lines, the total, the payment methods and one button — so it
 * is set at the width that plate is a plate at, not at the width of a page of
 * prose. 560 rather than the aside's 380: standing alone it is the only thing
 * on the page, and a 380px column under a full-width heading reads as a leftover. */
.woocommerce-order-received .goblin-page__content { max-width: var(--wp--custom--layout--content-size, 820px); }
.woocommerce-order-pay .goblin-page__content { max-width: 560px; }

/* ---------- The thank-you page ----------
 * `.woocommerce-order` is the plate: the shortcode's own wrapper around the
 * whole receipt, already the only element that is a parent of all four parts of
 * it, so nothing is added and no template is overridden. Same plate, same
 * insets and same body face as the box every account endpoint prints into,
 * because it holds the same thing. */
.woocommerce-order-received .woocommerce-order {
	padding: 16px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.6;
	color: var(--goblin-ink);
}
/* "Order details", "Billing address", "Shipping address" — labels for the block
 * under them, not headlines over the page, which is what the `<h1>` above the
 * plate already is. The product meta rows' label, exactly as in the account
 * plate and the checkout's section headings. */
.woocommerce-order-received .woocommerce-order h2 {
	margin: 0 0 12px; padding: 0;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.3;
	color: var(--goblin-ink-soft);
}
/* The one line on the page addressed to the reader, so it is set the way the
 * dashboard's greeting is: the display face, a size up, with a rule under it.
 * It is not a notice — it carries `woocommerce-notice--success` but none of the
 * three classes the notice plate is built on, which is why it has been plain
 * body copy since the day it shipped. */
.woocommerce-order-received .woocommerce-thankyou-order-received {
	margin: 0 0 14px; padding: 0 0 12px;
	border-bottom: 1px solid var(--goblin-edge);
	font-family: var(--goblin-display); font-size: 1.02rem; font-weight: 600; line-height: 1.4;
	color: var(--goblin-ink);
}
/* A failed order says so in the error plate instead, and the two buttons under
 * it are the pagination tile like every other secondary button on the site. */
.woocommerce-order-received .woocommerce-thankyou-order-failed { color: var(--goblin-red-ink); }
.woocommerce-order-received .woocommerce-thankyou-order-failed-actions {
	display: flex; flex-wrap: wrap; gap: 10px; margin: 0 0 14px;
}
.woocommerce-order-received .woocommerce-thankyou-order-failed-actions a.button {
	padding: 9px 16px; min-height: 0;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.85rem; font-weight: 600;
	line-height: 1.3; text-transform: none; text-decoration: none;
}
.woocommerce-order-received .woocommerce-thankyou-order-failed-actions a.button:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* ---------- The overview strip ----------
 * Five facts about the order — its number, its date, the email it went to, the
 * total and how it was paid — and they are the only ones a reader coming back
 * to this page from a mailbox is looking for. So they go in a stone well at the
 * top of the plate, above the list of what was in it: the same well the address
 * blocks below use, which is what "a group of short facts" looks like here.
 *
 * WooCommerce prints them as floated `<li>`s separated by dashed rules, at
 * 0.715em uppercase with the value in a `<strong>` under it. The label part of
 * that reading is right and is kept — it is the meta rows' label either way —
 * and the floats are not: five of them in a 390px viewport is five rows of one
 * item with a dashed rule hanging off the end of each.
 *
 * On a phone each fact is a row instead, label left and value right, which is
 * the shape every other label-and-number pair on this site takes and is about
 * 100px shorter than five stacked pairs. From 700px up they are columns in the
 * well, because by then five rows across a 600px box is five words and a lot of
 * white space between each and its own value.
 *
 * The `<ul>` carries `order_details` as well, which is the class the *table*
 * below is set by. Everything here names `ul.order_details` or the overview
 * class for that reason; a bare `.order_details` would set both. */
.woocommerce-order-received .woocommerce-order ul.order_details {
	margin: 0; padding: 14px;
	background: var(--goblin-stone);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	list-style: none;
}
/* Woo's clearfix for those floats. Harmless as a block, and two empty items the
 * moment this becomes a grid — the same trap the account menu's grid and the
 * address book's both hit. */
.woocommerce-order-received .woocommerce-order ul.order_details::before,
.woocommerce-order-received .woocommerce-order ul.order_details::after { content: none; }
.woocommerce-order-received .woocommerce-order ul.order_details li {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: 6px 14px;
	float: none; margin: 0; padding: 5px 0;
	border-right: 0; list-style: none;
	font-family: var(--goblin-ui); font-size: 0.66rem; font-weight: 700;
	letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.3;
	color: var(--goblin-ink-soft);
}
.woocommerce-order-received .woocommerce-order ul.order_details li:first-child { padding-top: 0; }
.woocommerce-order-received .woocommerce-order ul.order_details li:last-child { padding-bottom: 0; }
/* The value beside its label. The display face, because every one of the five is
 * a number or a reference — and `anywhere` because one of them is an email
 * address, which is a single unbreakable word wider than the room it gets on a
 * phone. */
.woocommerce-order-received .woocommerce-order ul.order_details li strong {
	flex: 0 1 auto; text-align: right;
	font-family: var(--goblin-display); font-size: 0.95rem; font-weight: 600;
	letter-spacing: 0; text-transform: none; line-height: 1.4;
	color: var(--goblin-ink); overflow-wrap: anywhere;
}
/* The strip is the top of the plate, so the section under it does not need the
 * rule the account page draws between its opening sentence and the table. */
.woocommerce-order-received .woocommerce-order ul.order_details + .woocommerce-order-details {
	margin-top: 16px; padding-top: 0; border-top: 0;
}

/* ---------- Verify your email ----------
 * The screen a **guest** meets on this page, and on this shop that is most of
 * them: with guest checkout on and no session left — a confirmation email opened
 * an hour later, on a phone that was not the one that ordered — WooCommerce does
 * not print the receipt at all. It prints one sentence, one field and a button,
 * and asks for the address the order was placed with.
 *
 * It had never been styled, because nobody had opened this page as a guest: the
 * field is the checkout's already (the body class carries those rules here), so
 * what was left was a form standing on the bare ground with the browser's own
 * grey button on it. It gets the plate the receipt would have got, at the width
 * of the one field in it — the same treatment as Lost password, which is the
 * other screen on this site that is one field and a button.
 *
 * The confirmation sentence above it is styled by the rule above, which is
 * deliberately not scoped to `.woocommerce-order`: on this screen it is the only
 * thing that says the order arrived at all. */
.woocommerce-order-received form.woocommerce-verify-email {
	display: grid; gap: 12px; max-width: 460px; margin: 0;
	padding: 16px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.6;
	color: var(--goblin-ink);
}
.woocommerce-order-received form.woocommerce-verify-email > p { margin: 0; }
.woocommerce-order-received form.woocommerce-verify-email > p:first-of-type { color: var(--goblin-ink-soft); }
/* "login" is a link in a sentence, so it is the quiet one the account plate's
 * links are and not the shop's red, which is the accent and reads as a warning
 * on the one screen a reader is already being told they cannot see something. */
.woocommerce-order-received form.woocommerce-verify-email p a {
	color: var(--goblin-ink-soft);
	text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px;
}
.woocommerce-order-received form.woocommerce-verify-email p a:hover { color: var(--goblin-gold-ink); }
/* The confirmation sentence's rule is the top of the receipt plate below it, and
 * there is no receipt on this screen — a 820px hairline over a 460px form is a
 * line under nothing. */
.woocommerce-order-received .woocommerce-thankyou-order-received:has(+ form.woocommerce-verify-email) {
	padding-bottom: 0; border-bottom: 0;
}
/* Secondary, because it is one of two ways in and the other is a link in the
 * sentence above it — so it is the pagination tile, like every other secondary
 * button on the site. Justified left because the form is the width of its field
 * and a full-width button would make the field look like a label for it. */
.woocommerce-order-received form.woocommerce-verify-email button.button {
	justify-self: start;
	width: auto; float: none; margin: 0;
	padding: 9px 16px; min-height: 0;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.85rem; font-weight: 600;
	line-height: 1.3; letter-spacing: 0.01em; text-transform: none;
	white-space: nowrap; cursor: pointer;
}
.woocommerce-order-received form.woocommerce-verify-email button.button:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}

/* ---------- Pay for order ----------
 * `form#order_review` is the plate, and it is the only wrapper the template
 * gives — the table, the payment methods, the terms and the button are all
 * inside it. The checkout's `#payment` rules, its terms well and its
 * `#place_order` reach every one of those through the shared body class, so
 * what is left here is the plate and the table in it. */
.woocommerce-order-pay form#order_review {
	padding: 16px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.6;
	color: var(--goblin-ink);
}
/* Three columns rather than the checkout's two — WooCommerce gives this table a
 * quantity of its own instead of printing it after the name — so a line is a
 * grid rather than the summary's flex row. The totals below are the flex row,
 * as they are everywhere else. */
.woocommerce-order-pay form#order_review > table.shop_table {
	display: block; width: 100%; margin: 0;
	background: none; border: 0; border-radius: 0;
	border-collapse: separate; border-spacing: 0;
	font-family: var(--goblin-ui); font-size: 0.86rem;
}
.woocommerce-order-pay form#order_review > table.shop_table thead,
.woocommerce-order-pay form#order_review > table.shop_table tbody,
.woocommerce-order-pay form#order_review > table.shop_table tfoot { display: block; }
.woocommerce-order-pay form#order_review > table.shop_table th,
.woocommerce-order-pay form#order_review > table.shop_table td {
	padding: 0; border: 0; text-align: left; line-height: 1.45;
}
.woocommerce-order-pay form#order_review > table.shop_table thead tr,
.woocommerce-order-pay form#order_review > table.shop_table tbody tr {
	display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
	align-items: baseline; gap: 4px 12px;
	border-bottom: 1px solid var(--goblin-edge);
}
.woocommerce-order-pay form#order_review > table.shop_table thead tr { padding-bottom: 8px; }
.woocommerce-order-pay form#order_review > table.shop_table tbody tr { padding: 11px 0; }
.woocommerce-order-pay form#order_review > table.shop_table thead th {
	font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em;
	text-transform: uppercase; color: var(--goblin-ink-soft);
}
.woocommerce-order-pay form#order_review > table.shop_table thead th.product-quantity,
.woocommerce-order-pay form#order_review > table.shop_table thead th.product-total { text-align: right; }
.woocommerce-order-pay form#order_review > table.shop_table td.product-name {
	min-width: 0; color: var(--goblin-ink);
}
/* "× 1" is how many, not part of the name — the small print the rest of the
 * plate uses, and not the `<strong>` Woo prints it as. */
.woocommerce-order-pay form#order_review > table.shop_table td.product-quantity {
	text-align: right; white-space: nowrap;
	font-weight: 600; color: var(--goblin-ink-soft);
}
.woocommerce-order-pay form#order_review > table.shop_table td.product-subtotal {
	text-align: right; white-space: nowrap;
	font-family: var(--goblin-display); font-weight: 600; color: var(--goblin-ink);
}
/* The cart summary's rows, once more: label left, number right, the last one
 * bigger and in ink because it is the number the page is asking to be paid. */
.woocommerce-order-pay form#order_review > table.shop_table tfoot tr {
	display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
	gap: 6px 14px; padding: 9px 0;
	border-bottom: 1px solid var(--goblin-edge);
}
.woocommerce-order-pay form#order_review > table.shop_table tfoot tr:last-child { border-bottom: 0; }
.woocommerce-order-pay form#order_review > table.shop_table tfoot th {
	flex: 0 0 auto;
	font-size: 0.78rem; font-weight: 600; color: var(--goblin-ink-soft);
}
.woocommerce-order-pay form#order_review > table.shop_table tfoot td {
	flex: 1 1 auto; text-align: right;
	font-family: var(--goblin-display); font-size: 0.92rem; font-weight: 600;
	color: var(--goblin-ink);
}
.woocommerce-order-pay form#order_review > table.shop_table tfoot tr:last-child th {
	font-size: 0.86rem; color: var(--goblin-ink);
}
.woocommerce-order-pay form#order_review > table.shop_table tfoot tr:last-child td { font-size: 1.22rem; }
/* The payment box closes the plate here rather than opening a second one, so it
 * takes the rule the checkout's does and nothing else. Woo wraps the terms and
 * the button in a `.form-row`, which the field rules would otherwise treat as a
 * field. */
.woocommerce-order-pay #payment > .form-row { margin: 0; padding: 0; }
.woocommerce-order-pay #payment > .form-row > #place_order { margin-top: 16px; }

/* ---------- Wide enough for the overview to be columns ----------
 * 700, which is where the well is wide enough for the five facts to stand side
 * by side rather than under one another. The track is 190px and it is the email
 * address that sets it: the other four values are a number or a date and would
 * sit happily in 150, but the email is one unbreakable word about 190 wide, and
 * a narrower track breaks it after the "gmail.c". `auto-fit` then puts as many
 * across as fit — two here, three at the full measure. */
@media (min-width: 700px) {
	.woocommerce-order-received .woocommerce-order ul.order_details {
		display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
		gap: 12px 16px;
	}
	.woocommerce-order-received .woocommerce-order ul.order_details li {
		display: block; padding: 0;
	}
	.woocommerce-order-received .woocommerce-order ul.order_details li strong {
		display: block; margin-top: 4px; text-align: left;
	}
}

/* ---------- Login and register ----------
 * `/my-account/` logged out, and the only page on the site that is two forms of
 * equal weight side by side. WooCommerce prints them as a `col2-set` floated
 * 47/47 with the fields unstyled and two `button.alt`s; they are the checkout's
 * fields in two of the checkout's plates.
 *
 * The two forms take different buttons on purpose. Guest checkout is on, so an
 * account is optional and the reason a reader is on this page is almost always
 * that they already have one: "Log in" is the gold button and "Register" is the
 * secondary plate. Two gold buttons side by side would be two primary actions,
 * which is the one thing a page asking a single question should not have. */
.woocommerce-account #customer_login { display: grid; gap: 18px; }
.woocommerce-account #customer_login::before,
.woocommerce-account #customer_login::after { content: none; }
.woocommerce-account #customer_login > .u-column1,
.woocommerce-account #customer_login > .u-column2 {
	float: none; width: auto; margin: 0;
	padding: 18px 18px 20px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
}
/* A real heading, not the small-caps label: these two words are the question the
 * page is asking, and there are only two of them on it. */
.woocommerce-account #customer_login > div > h2 {
	margin: 0 0 14px;
	font-family: var(--goblin-display); font-size: 1.05rem; font-weight: 600; line-height: 1.2;
	color: var(--goblin-ink);
}
/* Woo gives `form.login` and `form.register` a border, 20px of padding, a 5px
 * radius and 2em of margin of their own (`woocommerce.css`, shared with the
 * checkout's coupon form). Inside the plates above that is a box drawn round a
 * box, with the outer one's padding between them — which is what this page has
 * looked like since the plates went on. The plate is the box; the form is what
 * is in it. */
.woocommerce-account #customer_login form.login,
.woocommerce-account #customer_login form.register {
	margin: 0; padding: 0;
	border: 0; border-radius: 0;
}
.woocommerce-account #customer_login .form-row { float: none; width: auto; margin: 0 0 12px; padding: 0; }
.woocommerce-account #customer_login .form-row label {
	display: block; margin: 0 0 5px;
	font-family: var(--goblin-ui); font-size: 0.74rem; font-weight: 600; line-height: 1.35;
	color: var(--goblin-ink-soft);
}
.woocommerce-account #customer_login .form-row label .required { color: var(--goblin-red); text-decoration: none; border: 0; }
.woocommerce-account #customer_login input.input-text {
	display: block; width: 100%; margin: 0;
	padding: 9px 11px;
	background: #fff;
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	outline: 0; box-shadow: none;
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.4; color: var(--goblin-ink);
}
.woocommerce-account #customer_login input.input-text:hover { border-color: var(--goblin-edge-dark); }
.woocommerce-account #customer_login input.input-text:focus {
	border-color: var(--goblin-gold);
	box-shadow: 0 0 0 3px rgba(224, 168, 30, 0.22);
}
/* "Remember me" and the button share Woo's one `<p class="form-row">`, so the
 * checkbox takes a line of its own above the button — a 15px control and two
 * words sat beside a 48px gold button is a row whose two halves have nothing to
 * do with each other. Same placed-control arrangement as the checkout's rows;
 * see the note there for why these are not flex. */
.woocommerce-account #customer_login label.woocommerce-form-login__rememberme {
	display: block; position: relative;
	margin: 0 0 14px; padding-left: 24px;
	font-family: var(--goblin-ui); font-size: 0.82rem; font-weight: 400; line-height: 1.5;
	color: var(--goblin-ink); cursor: pointer;
}
.woocommerce-account #customer_login .woocommerce-form__input-checkbox {
	position: absolute; left: 0; top: 0.28em;
	width: 15px; height: 15px; margin: 0; accent-color: var(--goblin-gold);
}
.woocommerce-account #customer_login .woocommerce-privacy-policy-text {
	margin: 0 0 14px; font-size: 0.76rem; line-height: 1.5; color: var(--goblin-ink-soft);
}
.woocommerce-account #customer_login .woocommerce-privacy-policy-text p { margin: 0; }

/* The gold button, at the product page's 48px, full width of its plate. */
.woocommerce-account #customer_login .woocommerce-form-login__submit {
	display: flex; align-items: center; justify-content: center; text-align: center;
	width: 100%; min-height: 48px; margin: 0; padding: 12px 22px; float: none;
	border: 0; border-radius: var(--goblin-radius);
	background: var(--goblin-gold); color: #241a05;
	box-shadow: 0 1px 2px rgba(27, 31, 36, 0.16);
	font-family: var(--goblin-ui); font-size: 0.95rem; font-weight: 700;
	line-height: 1.25; letter-spacing: 0.01em; text-transform: none; cursor: pointer;
	transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.woocommerce-account #customer_login .woocommerce-form-login__submit:hover {
	background: #d29a10; color: #241a05;
	box-shadow: 0 2px 6px rgba(27, 31, 36, 0.22);
}
/* And the secondary plate for the other one. */
.woocommerce-account #customer_login .woocommerce-form-register__submit {
	display: flex; align-items: center; justify-content: center; text-align: center;
	width: 100%; min-height: 48px; margin: 0; padding: 12px 22px; float: none;
	background: #fff; color: var(--goblin-ink);
	border: 1px solid var(--goblin-edge); border-radius: var(--goblin-radius);
	box-shadow: var(--goblin-shadow);
	font-family: var(--goblin-ui); font-size: 0.92rem; font-weight: 600;
	line-height: 1.25; letter-spacing: 0.01em; text-transform: none; cursor: pointer;
}
.woocommerce-account #customer_login .woocommerce-form-register__submit:hover {
	background: var(--goblin-gold); border-color: var(--goblin-gold); color: #241a05;
}
.woocommerce-account #customer_login .woocommerce-LostPassword { margin: 12px 0 0; font-size: 0.8rem; }
.woocommerce-account #customer_login .woocommerce-LostPassword a {
	color: var(--goblin-ink-soft); text-decoration-color: var(--goblin-edge-dark); text-underline-offset: 3px;
}
.woocommerce-account #customer_login .woocommerce-LostPassword a:hover { color: var(--goblin-gold-ink); }

/* 760 is where two forms of five short rows each stop being two narrow columns
 * and become two readable ones. Below it they stack, login first — the reason
 * most readers are here. */
@media (min-width: 760px) {
	.woocommerce-account #customer_login {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 20px;
	}
}

/* ---------- Pages / lists ---------- */
.goblin-page, .goblin-list, .goblin-404 { padding-block: clamp(1.5rem, 1rem + 2vw, 3rem); }
/* The same clamp the archive title takes, for the same reason: 2em is the
 * browser's default `h1` — a headline for a document, not a title for a page in
 * a storefront — and it is the one heading size on the site that a phone was
 * never asked about. Landing at ~25px on a phone and 32px on a desktop, so the
 * desktop keeps what it had. */
.goblin-page__title { font-size: clamp(1.55rem, 1.2rem + 1.4vw, 2rem); }
.goblin-page__content { max-width: var(--wp--custom--layout--content-size, 820px); }
.goblin-list__items { display: grid; gap: 1.25rem; }
.goblin-list__item { border-bottom: 1px solid var(--goblin-edge); padding-bottom: 1rem; }
/* Search results are products and text entries in one list — the products in the
 * product grid's columns, everything else across the full width of it. Without
 * the span a page sitting between two products would take one column and leave
 * the rest of its row empty. */
.goblin-list__items--mixed > .goblin-list__item { grid-column: 1 / -1; }

/* ---------- Footer ----------
 * The dark plate of the same scene the hero uses, so it needs no inversion — it
 * is placed and cropped exactly like the light one. Holding it just under full
 * opacity seats it on the ink ground rather than replacing it, which keeps the
 * brighter objects (the pale board, the mug, the face-up cards) far enough back
 * for the footer text to stay legible over them. The scrim deepens downward so
 * the link columns — the busiest crop — sit on the darkest part while the
 * newsletter block above keeps the artwork vivid.
 */
.goblin-footer {
	position: relative; isolation: isolate; overflow: hidden;
	background: var(--goblin-ink); color: #eef0f2; margin-top: 0;
}
.goblin-footer__texture {
	position: absolute; inset: 0; z-index: 0; pointer-events: none;
	background:
		linear-gradient(180deg, rgba(27, 31, 36, 0) 0%, rgba(27, 31, 36, 0.3) 42%, rgba(27, 31, 36, 0.58) 100%),
		url("../img/bg-footer.webp") center / cover no-repeat;
	opacity: 0.92;
}
/* Everything that is not the texture sits above it. */
.goblin-footer > .goblin-container,
.goblin-footer__bar { position: relative; z-index: 1; }

.goblin-footer a { color: #eef0f2; text-decoration: none; }
.goblin-footer a:hover { color: var(--goblin-gold); }
.goblin-footer__newsletter {
	text-align: center; padding-block: 46px 38px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
.goblin-footer__logo { display: inline-flex; margin-bottom: 20px; }
.goblin-footer__logo img {
	height: 40px; width: auto; display: block;
	filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.65)) drop-shadow(0 0 4px rgba(0, 0, 0, 0.65));
}
.goblin-footer__newsletter strong {
	display: block; max-width: 32ch; margin-inline: auto;
	font-family: var(--goblin-display);
	font-size: clamp(1.05rem, 0.92rem + 0.55vw, 1.4rem); font-weight: 600;
	line-height: 1.3; color: #fff; letter-spacing: -0.015em;
}
.goblin-footer__newsletter p {
	max-width: 48ch; margin: 12px auto 0; color: #c3cad1;
	font-size: clamp(0.86rem, 0.83rem + 0.15vw, 0.95rem);
}
/* Dark-ground counterpart of the paper halo on the light bands: same trick, ink
 * instead of white, so the two blocks over artwork are treated the same way. */
@supports (paint-order: stroke) {
	.goblin-footer__newsletter strong,
	.goblin-footer__newsletter p,
	.goblin-footer__facts {
		-webkit-text-stroke-color: var(--goblin-ink); paint-order: stroke fill;
	}
	.goblin-footer__newsletter strong {
		-webkit-text-stroke-width: clamp(4px, 3.63px + 0.1vw, 5px);
		text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.45);
	}
	.goblin-footer__newsletter p,
	.goblin-footer__facts { -webkit-text-stroke-width: 3px; }
}
/* Shop facts, between the newsletter and the link columns. Same three the hero
 * used to carry, restyled for this ground: no plate — the footer is already an
 * opaque dark band, so light text on it needs nothing behind it — and the icons
 * take the gold the footer headings use rather than the light band's darker
 * gold-ink. It carries the same hairline the newsletter and the bottom bar do, so
 * the footer stays a stack of ruled bands. */
.goblin-footer__facts {
	list-style: none; margin: 0; padding-inline: 0;
	padding-block: clamp(20px, 17.4px + 0.66vw, 27px);
	border-bottom: 1px solid rgba(255, 255, 255, 0.14);
	display: flex; flex-wrap: wrap; justify-content: center;
	gap: 10px clamp(1.25rem, 0.4rem + 3.4vw, 3.25rem);
	font-family: var(--goblin-ui); font-size: 0.88rem; line-height: 1.45;
	color: #dce1e6;
}
.goblin-footer__fact { display: inline-flex; align-items: center; gap: 10px; }
/* The halo above is a text stroke, which does nothing for an SVG, so the icons get
 * the footer logo's treatment instead — a doubled dark glow. Both sit in the upper
 * band where the scrim is lightest and the artwork still vivid. */
.goblin-footer__fact svg {
	flex: 0 0 auto; width: 18px; height: 18px;
	color: var(--goblin-gold);
	filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.7)) drop-shadow(0 0 3px rgba(0, 0, 0, 0.7));
}
/* Same rule the hero strip had, for the same reason: below three-across, stack as
 * a left-aligned block rather than letting each line centre on its own. Centred
 * ragged rows read as a mistake. Breakpoint measured, not guessed — see below. */
@media (max-width: 1015px) {
	.goblin-footer__facts {
		flex-direction: column; align-items: flex-start;
		width: fit-content; margin-inline: auto;
	}
}

.goblin-footer__cols {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: 26px 34px; padding-block: 46px;
}
.goblin-footer__heading {
	font-family: var(--goblin-ui);
	font-size: 0.72rem; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase;
	color: var(--goblin-gold); margin: 0 0 16px; padding-bottom: 11px;
	border-bottom: 1px solid rgba(231, 166, 20, 0.32);
}
.goblin-footer__menu { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.goblin-footer__menu a, .goblin-footer__contact address { font-size: 0.9rem; }
.goblin-footer__contact address { font-style: normal; line-height: 1.9; color: #dce1e6; }
/* Social: plain links in a row, not bordered chips. They share the .goblin-chip
 * class with the archive publisher list, so the reset has to be explicit. */
.goblin-footer__social { margin-top: 18px; display: flex; flex-wrap: wrap; gap: 8px 20px; }
.goblin-footer__social .goblin-chip {
	background: none; border: 0; padding: 0; border-radius: 0;
	color: #eef0f2; font-size: 0.85rem; font-weight: 600;
}
.goblin-footer__social .goblin-chip:hover { background: none; color: var(--goblin-gold); }
.goblin-footer__bar {
	border-top: 1px solid rgba(255, 255, 255, 0.14);
	padding-block: 16px; font-size: 0.8rem; color: #c3cad1; text-align: center;
}

/* ---------- Cookie notice ----------
 * A bar along the bottom of the viewport. It is the last element in the document
 * and fixed, so it sits over the page without a z-index argument with anything —
 * the 70 is only there to clear the sticky header (50) and the menu flyouts (60),
 * both of which can be open when the bar is still up.
 *
 * Nothing about it animates in. The bar is server-rendered only for readers who
 * have not dismissed it (inc/cookie-notice.php), so there is no moment where it
 * exists but should not be seen — and a bar that slides up a beat after paint is
 * just a second layout shift charged to the same reader.
 *
 * Ink ground rather than the footer's darker one: it can come to rest over any
 * part of any page, so it has to read as a layer above the page rather than as a
 * band of it. */
.goblin-cookies {
	position: fixed; inset: auto 0 0 0; z-index: 70;
	background: var(--goblin-ink); color: #eef0f2;
	border-top: 3px solid var(--goblin-gold);
	box-shadow: 0 -8px 24px rgba(27, 31, 36, 0.24);
	padding-block: 14px;
}
.goblin-cookies__inner {
	display: flex; align-items: center; gap: 14px 28px; flex-wrap: wrap;
}
/* Measured, not just wrapped: the message is three lines of small type and at a
 * desktop width it would otherwise run the whole way to the button. */
.goblin-cookies__text {
	margin: 0; max-width: 74ch;
	font-size: 0.86rem; line-height: 1.6; color: #dce1e6;
}
.goblin-cookies__actions { display: flex; align-items: center; gap: 22px; margin-left: auto; }
.goblin-cookies__link {
	color: #eef0f2; font-size: 0.82rem; font-weight: 600;
	text-decoration: underline; text-underline-offset: 3px; white-space: nowrap;
}
.goblin-cookies__link:hover { color: var(--goblin-gold); }
/* The plate is a white sheet with a 2px ink edge and an ink shadow, which on the
 * ink ground is a white rectangle with nothing around it. The gold takes both
 * over — same shape, same press on hover, legible ground. */
.goblin-cookies__accept { border-color: var(--goblin-gold); box-shadow: 3px 3px 0 var(--goblin-gold); }
.goblin-cookies__accept:hover { box-shadow: 1px 1px 0 var(--goblin-gold); }

/* On a phone the row becomes a stack and the button goes full width: at 360px the
 * actions row and the text cannot share a line without the message setting two
 * words wide. */
@media (max-width: 600px) {
	.goblin-cookies { padding-block: 12px; }
	.goblin-cookies__inner { gap: 12px; }
	.goblin-cookies__text { font-size: 0.8rem; }
	.goblin-cookies__actions { margin-left: 0; width: 100%; justify-content: space-between; }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
	.goblin-grid { --goblin-cols: 2 !important; }

	/* One row, not two: burger + brand + search + cart/langs all share the line.
	 *
	 * The search used to sit on its own line below, which made the sticky header
	 * ~110px of a phone viewport charged against every screenful — enough that the
	 * band had to scroll away and be reserved back with `--goblin-search-h`. Fitting
	 * it into the row removes the second line, and with it that whole mechanism.
	 *
	 * `min-width: 0` is what makes it fit at all: a flex item will not shrink past
	 * an <input>'s intrinsic width without it, and the row would overflow instead. */
	.goblin-header__inner { flex-wrap: nowrap; gap: 0.6rem; padding-block: 10px; }
	.goblin-nav-toggle { order: 1; display: inline-flex; }
	.goblin-header__brand { order: 2; }
	.goblin-header__logo img { height: 32px; }
	.goblin-header__search { order: 3; flex: 1 1 auto; min-width: 0; max-width: none; }
	.goblin-header__actions { order: 4; gap: 14px; }
	.goblin-header__actions .goblin-header__link { display: none; }
	/* Tighter than the desktop field: 16px text (see the base rule — it is what stops
	 * iOS zooming the page) costs width the phone row does not have, and the
	 * magnifier does not need 2.4rem of runway at this size. */
	.goblin-header__search .search-field {
		padding: 0.45rem 0.7rem 0.45rem 2.05rem;
		background-position: 0.7rem center;
	}

	/* Focused, the field takes the rest of the row: with only ~150px to type into,
	 * the cart and the language switcher are worth more as width than as buttons
	 * while a query is being entered. They come straight back on blur.
	 *
	 * `~` and not a class toggle — the actions follow the search in the DOM, so the
	 * whole behaviour is a sibling selector and needs no JS. */
	.goblin-header__search:focus-within ~ .goblin-header__actions { display: none; }

	/* Open menu takes the whole screen: the header itself goes fixed and becomes a
	 * flex column, so its own top row stays put (burger turns into the X) and the
	 * nav fills the rest and scrolls. Every depth-2 submenu is expanded inline, so
	 * the list is far taller than the viewport — `min-height: 0` lets the flex item
	 * actually shrink to the leftover space instead of overflowing the screen. */
	body.goblin-nav-open { overflow: hidden; }
	body.goblin-nav-open .goblin-header {
		position: fixed; inset: 0; z-index: 60;
		display: flex; flex-direction: column;
		background: #fff; box-shadow: none;
	}
	body.goblin-nav-open .goblin-header__inner { flex: 0 0 auto; }

	.goblin-header__nav { display: none; }
	.goblin-header__nav.is-open {
		display: block; flex: 1 1 auto; min-height: 0;
		background: #fff; border: 0;
		padding-block: 0.5rem 2.5rem;
		overflow-y: auto; overscroll-behavior: contain;
		-webkit-overflow-scrolling: touch;
	}
	/* The account items are ordinary top-level rows here — everything that styles
	 * them is the `.goblin-menu > li` block below. All this does is let them out. */
	.goblin-menu > .goblin-menu__account { display: block; }
	/* The band is a stacked panel here, not a rail: the list is the rail's track, so
	 * its sideways scrolling has to be handed back (the panel scrolls vertically),
	 * and the arrows and fades have nothing to do. */
	.goblin-menu {
		flex-direction: column; column-gap: 0; font-size: 1rem;
		overflow: visible; padding-block: 0;
	}
	.goblin-rail--nav .goblin-rail__nav { display: none; }
	.goblin-rail--nav::before,
	.goblin-rail--nav::after { content: none; }
	.goblin-menu > li { border-bottom: 1px solid var(--goblin-edge); }
	.goblin-menu > li:last-child { border-bottom: none; }
	.goblin-menu > li > a { padding: 0.8rem 0; font-weight: 700; }
	.goblin-menu > li > a::after { display: none; }
	.goblin-menu .sub-menu {
		position: static; display: block; left: auto;
		min-width: 0; padding: 0 0 0.6rem 0.9rem;
		border: none; border-radius: 0; box-shadow: none;
	}
	.goblin-menu .sub-menu a { padding: 0.4rem 0; font-size: 0.9rem; color: var(--goblin-gray); }

	/* The arrows stay on touch. They were display:none here on the theory that a
	 * finger pans the row anyway — but panning is something you have to already
	 * know is possible, and this is the width where the row shows barely two cards
	 * and hides the most. They shrink and tuck into the container's 1rem gutter
	 * instead, so they clear the card faces rather than sitting on them. */
	.goblin-rail--products .goblin-rail__nav { width: 32px; height: 32px; font-size: 1.05rem; }
	.goblin-rail--products .goblin-rail__nav--prev { left: -10px; }
	.goblin-rail--products .goblin-rail__nav--next { right: -10px; }
	.goblin-rail__scrollbar { width: min(180px, 60%); margin-top: 13px; }
	.goblin-rail__more { gap: 11px; }
	.goblin-rail__more-mark { width: 40px; height: 40px; font-size: 1.25rem; }
	.goblin-rail__more-label { font-size: 0.9rem; -webkit-text-stroke-width: 4px; }

	/* Card interiors tighten with the cards themselves. Only the title size and the
	 * inset are restated — the price size is written as the title's, and the text
	 * block's reserved height is calculated from both, so they follow on their own. */
	.goblin-product-card { --goblin-card-title-size: 0.82rem; --goblin-card-pad-x: 11px; }
	.goblin-product-card__media img { padding: 11px; }
	.goblin-product-card__text { padding: 10px var(--goblin-card-pad-x) 11px; }
	.goblin-badges { top: 8px; left: 8px; gap: 4px; }
	.goblin-badge { padding: 2px 7px 3px; font-size: 0.57rem; }
	.goblin-card__media img { padding: 12px; }
	/* Tokens only — .goblin-card__body's reserved height is calculated from these,
	 * so restating the sizes and the padding moves it without a second sum here. */
	.goblin-card {
		--goblin-cat-label-size: 0.9rem;
		--goblin-cat-sub-size: 0.72rem;
		--goblin-cat-body-pt: 10px;
		--goblin-cat-body-px: 12px;
		--goblin-cat-body-pb: 12px;
	}

	.goblin-footer__newsletter { padding-block: 32px 28px; }
	.goblin-footer__cols { padding-block: 32px; }

	/* Above 900px the stacked facts are a left-aligned block that is itself centred
	 * (see the max-width: 1015px rule), which works while the footer around them is
	 * a wide centred masthead. On a phone the columns under them are a flush-left
	 * stack, and a centred block floating above a left-aligned one reads as a
	 * misalignment rather than as a choice — so down here the block goes flush left
	 * too and the icons line up with the column headings below. */
	.goblin-footer__facts { width: auto; margin-inline: 0; }

	/* The footer's crop is the one thing that does not survive the narrow viewport
	 * unchanged. `cover` scales to whichever axis needs more, and on a phone the
	 * footer is roughly three times taller than it is wide against a 16:9 image —
	 * so the artwork comes in about four times life size and the newsletter copy
	 * ends up sitting on one enormous bright meeple. The objects cannot be kept at
	 * desktop scale (anything but `cover` leaves the column area uncovered), so the
	 * scrim takes over instead: it starts at a quarter rather than nothing and ends
	 * near opaque, which turns the crop into a dark texture and hands the text back
	 * its contrast. Anchoring the crop at the top keeps the flat-lay's denser half
	 * behind the newsletter, where the scrim is lightest. */
	.goblin-footer__texture {
		background:
			linear-gradient(180deg, rgba(27, 31, 36, 0.25) 0%, rgba(27, 31, 36, 0.6) 42%, rgba(27, 31, 36, 0.82) 100%),
			url("../img/bg-footer.webp") center top / cover no-repeat;
	}
}
@media (max-width: 560px) {
	/* Burger + logo + search + cart + three language codes do not fit one line with
	 * the word "Cart" spelled out. The bag glyph carries the link on its own here;
	 * the label stays for screen readers so it still announces itself. */
	.goblin-cart__label {
		position: absolute; width: 1px; height: 1px;
		overflow: hidden; clip: rect(1px, 1px, 1px, 1px); white-space: nowrap;
	}
}
/* No single-column fallback for the tile grid. The old skin dropped to one column
 * below 520px, which turned eight category tiles into eight full-width posters and
 * a very long scroll; the design keeps them two-up all the way down to 390px,
 * where a tile is still ~170px wide and its 4:3 art is perfectly readable. */

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
	/* The blanket 0.01ms above would leave the crawl parked at the end of its run
	 * rather than at the start. Same picture either way, but say it outright. */
	.goblin-ticker__track { animation: none; }
}

/* ---------- The two faces ----------
 * Both self-hosted (OFL), no Google Fonts request. Variable woff2 subsets split
 * by unicode-range: Cyrillic for Macedonian, Latin for English/Albanian and the
 * Latin brand names in the nav, latin-ext only fetched when a page actually
 * contains one of its glyphs.
 *
 * Inter carries body and UI at weight axis 400–900. Geologica carries headings,
 * prices and category names at 400–700 — the axis Google serves, and more than
 * this design asks for (it uses 600 and 700).
 */
@font-face {
	font-family: 'Inter';
	src: url('../fonts/inter-cyrillic.woff2') format('woff2');
	font-weight: 400 900; font-style: normal; font-display: swap;
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
	font-family: 'Inter';
	src: url('../fonts/inter-latin-ext.woff2') format('woff2');
	font-weight: 400 900; font-style: normal; font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Inter';
	src: url('../fonts/inter-latin.woff2') format('woff2');
	font-weight: 400 900; font-style: normal; font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Geologica';
	src: url('../fonts/geologica-cyrillic.woff2') format('woff2');
	font-weight: 400 700; font-style: normal; font-display: swap;
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
	font-family: 'Geologica';
	src: url('../fonts/geologica-latin-ext.woff2') format('woff2');
	font-weight: 400 700; font-style: normal; font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Geologica';
	src: url('../fonts/geologica-latin.woff2') format('woff2');
	font-weight: 400 700; font-style: normal; font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
