/* The order flow, finished, and the chrome around it.
 *
 * Phase 10 step 11 wrote the order flow. Phase 11 step 8 added everything under "The chrome"
 * below, which is the front end's header, footer and page frame copied by hand so that a
 * visitor crossing origins sees one site. Beside this file and `to-top.js`, everything in this
 * theme is generated by `npm run theme` from `src/styles/tokens/` and `seed/ui-strings.json`.
 *
 * Why a stylesheet exists at all, when the point of the phase was theme.json
 * --------------------------------------------------------------------------
 * Because theme.json reaches almost none of this. Measured across the two shipped
 * stylesheets, `cart.css` at 77 KB and `checkout.css` at 166 KB: they reference exactly five
 * WordPress preset custom properties, three of them font sizes and two of them colours with a
 * hardcoded fallback. Against that they carry 150 literal hex colours, 86 `border-radius`
 * declarations almost all of them 4px, and hover states built on `opacity`. The count is in
 * `docs/refs/woocommerce-blocks.md`.
 *
 * So theme.json carries the type scale and the palette an editor can pick from, and this file
 * carries the colours, the radii, the shadows and the three sanctioned hover moves. Full
 * parity was chosen over a smaller subset on 2026-08-02, because the phase's exit criterion
 * is that the cart and checkout are visibly the same brand as the front end, and a checkout
 * whose error state is `#cc1818` next to a page whose one accent is `#C0392B` fails it.
 *
 * The line this file does not cross
 * ---------------------------------
 * Every selector below is a WooCommerce block class, styled from outside. No template is
 * overridden, no block is replaced, and nothing here changes what the checkout does. That is
 * the amended non goal in `CLAUDE.md`, and it is what keeps a WooCommerce, Paytrail or Posti
 * update able to change behaviour without breaking a layout this project owns.
 *
 * Which also means this file is expected to age. A class that disappears in a WooCommerce
 * release takes its rule with it and the control returns to WooCommerce's own look, which is
 * a visible regression rather than a broken page. That trade is the whole point.
 *
 * The rules being applied, by number, from CLAUDE.md
 * -------------------------------------------------
 *   1   two backgrounds, bone and ink. No third surface anywhere below.
 *   3   one accent, ember, and only where a rule 3 place is named. Not on a control.
 *   5   hover is fill inversion, lift or media zoom. Never opacity. No press states.
 *   6   buttons and inputs are a full pill, cards are 20px.
 *   7   shadows are warm, rgba(40,33,24,alpha), never neutral black.
 *   10  every hover has a paired focus-visible, and motion stops under reduce.
 */

/* The page ---------------------------------------------------------------------------- */

/* Ink under everything, so overscroll shows the dark layer and never white.
 *
 * Deliberately not the `.fn-ink` class on the body, even though the colour is the same.
 * `.fn-ink` also carries the inverted focus ring below, and on the body that rule would match
 * every link on the page, including the header, where a bone ring on the bone page is
 * invisible. That is `BaseLayout.astro`'s own finding, reproduced rather than rediscovered. */
body {
	background: var(--surface-ink);
}

/* The order flow's own body copy, which is smaller and looser than the root.
 *
 * Both values were the root's until Phase 11, when the root moved to the front end's 16px at 1.5
 * so that the chrome would match. Phase 10's choice is kept where it was actually about
 * something, which is the cart and the checkout themselves. */
.wp-block-woocommerce-cart,
.wp-block-woocommerce-checkout,
.woocommerce-order-received {
	font-size: var(--type-body-sm);
	line-height: var(--lh-body);
}

/* Border box everywhere, which is Preflight's rule and the front end's base.
 *
 * Without it a 40px circle with a 1px border is 42px wide, and the parity check said exactly
 * that about the bag and then about the header row that holds it. */
*,
::before,
::after {
	box-sizing: border-box;
}

/* Controls inherit their type, which is also Preflight's and not this file's idea.
 *
 * A `button` does not inherit `font-family` from its parent, so on a page with no Preflight the
 * back to top control drew its label in the browser's default face. The parity check found it as
 * `.to-top-label fontFamily: Inter on the front end, Arial on the shop`, which is a sentence no
 * screenshot would have produced. `text-transform` is the same story in reverse: a button does not
 * inherit it, so the bag was uppercase here and not there.
 *
 * Scoped to the chrome rather than applied to every control on the page. Preflight's own rule is
 * unscoped, and an unscoped copy here would reach WooCommerce's inputs and buttons, whose
 * typography Phase 10 already settled one selector at a time.
 *
 * Every selector is inside `:where()`, so the whole rule has zero specificity. Written the
 * obvious way first, it beat `.hdr-menu`'s own font weight and `.v-on-ink`'s own colour, and the
 * parity check reported both: a reset that outranks the rules it exists to support is not a
 * reset. Preflight gets this for free by being element selectors only. */
:where(.hdr, .ftr) :where(button, input) {
	font-family: inherit;
	font-size: 100%;
	font-weight: inherit;
	line-height: inherit;
	letter-spacing: inherit;
	text-transform: none;
	color: inherit;
}

/* The page surface, which is `.fn-page` and `.page` on the front end and is core's own wrapper
   here. `BaseLayout.astro` writes its own two elements; a commerce page is framed by
   WooCommerce's `page-cart.html`, which this project may not override, so the surface is
   attached to the element that template already renders inside.
 *
 * Every declaration is load bearing. The background and the dot grid are rule 1's bone surface,
 * copied from `.fn-page` in `src/styles/tokens/surfaces.css` rather than referenced, because the
 * class is not on this element. The stacking context is what lets the page cover the fixed
 * footer, and `assets/chrome.js` gives it the bottom padding that lets the page end above the
 * footer rather than under it. */
.wp-site-blocks {
	position: relative;
	z-index: 1;
	background-color: var(--surface-page);
	background-image: var(--dot-grid);
	background-size: var(--dot-grid-size);
	color: var(--text-strong);
}

/* The header's layout box.
 *
 * Core wraps a template part in the element its area names, so the sticky element is the wrapper
 * and `.hdr` is its only child at exactly its size. The `position: sticky` that `.hdr` carries
 * below is the front end's own rule, kept byte for byte so the parity check compares like with
 * like; inside a box its own height it has nowhere to travel and does nothing. */
.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 50;
}

/* `hidden` has to mean hidden.
 *
 * The front end gets this from Tailwind's Preflight, which is its base reset and ships this exact
 * rule. There is no Tailwind here, so without it an author rule that sets `display` beats the
 * browser's own `[hidden]`, and the mobile drawer, served closed on every page, is drawn open
 * under the header. Found on a 390px screenshot of the cart rather than by reading the markup,
 * which had `hidden` on it all along.
 *
 * Copied from Preflight verbatim, `:where()` and `!important` included: the `:where()` keeps the
 * selector at zero specificity so a component can still choose to draw something hidden, and the
 * `!important` is what makes an attribute beat a class at all. */
[hidden]:where(:not([hidden='until-found'])) {
	display: none !important;
}

/* Focus parity, rule 10, from `src/styles/global.css`.
 *
 * Upstream's `surfaces.css` ships `a:hover` with no `:focus-visible` pair, and the token layer
 * this theme generates is that file verbatim, so it arrives here carrying the same gap. The fix
 * belongs in an authored file on both sides, which is what this is. */
a:focus-visible {
	color: var(--ink-hover);
	box-shadow: var(--focus-ring);
	border-radius: var(--focus-ring-radius);
	outline: none;
}

/* On ink the same ring would disappear into the background, so it inverts. */
.fn-ink a:focus-visible {
	box-shadow: 0 0 0 2px var(--bone);
}

/* The chrome ---------------------------------------------------------------------------
 *
 * Every rule from here to the end of this section is the front end's, copied from the scoped
 * `<style>` blocks of `src/components/layout/Header.astro`, `Footer.astro`,
 * `src/components/brand/Logo.astro` and `Wordmark.astro`, `src/components/core/IconButton.astro`
 * and `src/components/content/FooterColumn.astro`. The class names in `functions.php` are those
 * components' class names for exactly this reason: one vocabulary, two renderers.
 *
 * This is a hand written copy and it is a second source of truth, chosen knowingly on
 * 2026-08-03 over extracting a shared stylesheet. What keeps it honest is the parity check in
 * `scripts/qa.mjs`, which compares the computed styles of both headers and both footers and
 * fails on a difference. A change made on the front end and not made here is a failed gate, not
 * a discovery six weeks later. */

/* The lockup. */
.logo {
	display: flex;
	flex-direction: column;
	align-items: center;
	/* Upstream geometry, below the smallest spacing token. Not worth a token, and recorded as
	   such in `DESIGN_TOKENS.md` since Phase 1. */
	gap: 2px;
	color: var(--text-strong);
}

.logo-flame {
	display: block;
	/* Without this the span's line box adds a few pixels under the flame and the lockup no
	   longer centres on the header row. */
	line-height: 0;
	color: inherit;
	transition:
		color var(--dur-base) ease,
		transform var(--dur-base) var(--ease-out-soft);
}

/* The documented exception to rules 3 and 5, confirmed in Phase 2 and verbatim from the design
   system: the flame turns ember and rises 2px, and the wordmark does not move. Rule 10 still
   applies to it, so the `:focus-visible` pair is written out. */
.logo:hover .logo-flame,
.logo:focus-visible .logo-flame {
	color: var(--accent);
	transform: translateY(-2px);
}

.wordmark {
	display: block;
	fill: currentColor;
}

.wordmark.fluid {
	width: 100%;
	height: auto;
}

/* Phase 13, finding F1. The lockup a fifth larger above the header breakpoint, mirroring
   `src/components/brand/Logo.astro`. Sizes and not a scale transform, so the flame's 2px hover
   lift keeps rising exactly 2px. */
@media (min-width: 901px) {
	.logo .wordmark {
		width: 61px;
		height: 17px;
	}

	.logo-flame svg {
		width: 27px;
		height: 34px;
	}
}

/* The circular control, `IconButton` at `md` and at `2xl`. The three sizes this theme never
   draws are not copied. */
.ibtn {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	padding: 0;
	border: 1px solid transparent;
	border-radius: var(--radius-round);
	cursor: pointer;
	transition: var(--t-hover);
	/* Not in `IconButton.astro`, and needed here for the same reason the reset above exists.
	   The front end's control is a `button`, which Preflight resets; the bag on these pages is a
	   link, which inherits the meta row's uppercase and drew a lettered tooltip nobody asked for.
	   The parity check named it. */
	text-transform: none;
}

.s-md {
	width: var(--control-md);
	height: var(--control-md);
}

.s-2xl {
	width: var(--control-2xl);
	height: var(--control-2xl);
	/* The 84px control stacks an icon over a micro label, which is why it is a column. */
	flex-direction: column;
	gap: var(--space-1);
}

/* Variant: ghost. Fill inversion on hover, rule 5. */
.v-ghost {
	background: var(--action-ghost-fill);
	border-color: var(--border-default);
	color: var(--text-strong);
}

.v-ghost:hover,
.v-ghost:focus-visible {
	background: var(--action-fill);
	border-color: var(--action-fill);
	color: var(--action-on-ink-fill);
}

/* Variant: on ink. Transparent, and the hover brightens rather than inverting, because there is
   no light fill to invert into on a dark section. */
.v-on-ink {
	background: transparent;
	border-color: var(--line-on-ink);
	color: var(--text-muted-on-ink);
	transition:
		color var(--dur-base) ease,
		border-color var(--dur-base) ease,
		transform var(--dur-base) ease;
}

.v-on-ink:hover,
.v-on-ink:focus-visible {
	color: var(--text-body-on-ink);
	border-color: var(--line-on-ink-hover);
	transform: translateY(-3px);
}

/* Rule 10. The ghost circle inverts to an ink fill on focus, which an ink ring would disappear
   into, so both variants use the offset ring. */
.ibtn:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring-offset);
}

.v-on-ink:focus-visible {
	box-shadow: var(--focus-ring-offset-on-ink);
}

/* The header --------------------------------------------------------------------------- */

.hdr {
	position: sticky;
	top: 0;
	z-index: 50;
	background: transparent;
	border-bottom: 1px solid transparent;
	transition:
		background var(--dur-base) ease,
		border-color var(--dur-base) ease,
		backdrop-filter var(--dur-base) ease;
}

/* Toggled from `assets/js/header.js` past 24px of scroll. */
.hdr.hdr-solid {
	background: var(--header-scrolled-bg);
	backdrop-filter: var(--header-scrolled-blur);
	/* Upstream literal, and the one value in this file with no token behind it. The design
	   system tokenizes the scrolled background and the blur but not this hairline: `--line` and
	   `--line-soft` are opaque bone greys, this is ink at 7 percent so what is behind the header
	   shows through it. `Header.astro` carries the same literal and lists it for the same reason,
	   which makes this the second place it lives. Named for `/done`. */
	border-bottom-color: rgba(30, 26, 21, 0.07);
}


.hdr-inner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: var(--header-pad);
}

.hdr-nav {
	display: flex;
	gap: clamp(18px, 2.6vw, 34px);
	font-size: var(--type-nav);
	font-weight: var(--weight-semibold);
	color: var(--text-body);
}

/* Rule 5: a colour transition, never opacity. Rule 10: the `:focus-visible` pair is not
   optional, and it is written out rather than grouped with `:hover`. */
.hdr-link {
	color: inherit;
	text-decoration: none;
	transition: color var(--dur-hover) ease;
}

.hdr-link:hover,
.hdr-link:focus-visible {
	color: var(--text-strong);
}

/* Placement only. The lockup's own appearance is `.logo` above. */
.hdr-logo {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
}

.hdr-meta {
	display: flex;
	align-items: center;
	gap: var(--space-8);
	font-size: var(--type-meta-sm);
	letter-spacing: var(--track-caps);
	text-transform: uppercase;
	color: var(--text-body);
}

.hdr-lang {
	display: inline-flex;
	align-items: baseline;
	/* Upstream sets the two codes and the slash apart by a single space, which is what the
	   drafted string spelled and what splitting it threw away. */
	gap: 0.32em;
	color: inherit;
	text-decoration: none;
	transition: color var(--dur-hover) ease;
}

/* The current language, darker than the rest of the meta row. Rule 5 is not in play: this is a
   resting state that marks which of the two is active, not a hover. */
.lang-on {
	color: var(--text-strong);
	font-weight: var(--weight-semibold);
}

.lang-sep,
.lang-off {
	color: inherit;
	transition: color var(--dur-hover) ease;
}

/* Only the half that is not current moves, because the current one is already at the strong
   colour and has nowhere to go. */
.hdr-lang:hover .lang-off,
.hdr-lang:focus-visible .lang-off {
	color: var(--text-strong);
}

.hdr-bag {
	position: relative;
	display: flex;
	align-items: center;
}

/* The positioning context the badge is placed against. */
.hdr-cart {
	position: relative;
}

/* The single sanctioned use of ember in the header, rule 3. Rendered only when the count is
   above zero, so there is no hidden state to style. */
.cart-count {
	position: absolute;
	top: -4px;
	right: -4px;
	min-width: 18px;
	height: 18px;
	padding: 0 var(--space-1);
	border-radius: 9px;
	background: var(--accent);
	color: var(--bone-3);
	font-size: var(--type-chip);
	font-weight: var(--weight-bold);
	letter-spacing: normal;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* The mobile disclosure, three bars in CSS. Phase 13 finding F7, mirroring
   `src/components/layout/Header.astro`. Rule 11 is still closed at thirteen glyphs: this is not
   an icon and nothing was added to the set. The word it used to spell is now the button's
   accessible name. */
.hdr-menu {
	display: none;
	padding: 0;
	border: none;
	background: none;
	color: inherit;
	cursor: pointer;
}

/* Phase 13, finding F13: integers everywhere. 20 by 14 with 2px bars puts the three of them at 0,
   6 and 12 on the pixel; the 24 by 16 with 1.75px bars it replaced put them at 0, 7.125 and 14.25,
   and three bars rasterised from three fractional offsets read as three different weights. */
.bars {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	width: 20px;
	height: 14px;
}

.bars > span {
	display: block;
	height: 2px;
	background: currentColor;
	border-radius: 1px;
	transition:
		transform var(--dur-base) var(--ease-out-soft),
		opacity var(--dur-base) ease,
		background var(--dur-hover) ease;
}

.hdr-menu:hover .bars > span,
.hdr-menu:focus-visible .bars > span {
	background: var(--text-strong);
}

.hdr-menu:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring-offset);
	border-radius: var(--radius-2);
}

/* Open, the three bars become a cross. A state and not a hover, which is why rule 5 is not in
   play and why the one opacity here is a reveal in reverse. */
.hdr-menu[aria-expanded='true'] .bars > span:nth-child(1) {
	transform: translateY(6px) rotate(45deg);
}

.hdr-menu[aria-expanded='true'] .bars > span:nth-child(2) {
	opacity: 0;
}

.hdr-menu[aria-expanded='true'] .bars > span:nth-child(3) {
	transform: translateY(-6px) rotate(-45deg);
}

/* The scroll lock, finding F14. `assets/js/nav.js` puts the attribute on the root while the panel
   is open. There is no Lenis on these pages at all, so this rule is the whole mechanism here. */
html[data-nav-open] {
	overflow: hidden;
}

/* The panel covers the screen and the header row paints over it, which is what the negative
   z-index inside `.hdr`'s stacking context buys. Rule 1 holds: this is the page background and
   not a third surface. The 72px is the row's measured height, 14px above and below a 44px
   lockup. */
/* Sized in viewport units rather than by `inset: 0`, which is Phase 13 finding F16: past 24px of
   scroll the header carries a `backdrop-filter`, and an element with a filter is the containing
   block for its fixed descendants, so `inset: 0` meant the header and the sheet came out header
   shaped. Mirrors `src/components/layout/Header.astro`. */
.hdr-drawer {
	position: fixed;
	top: 0;
	left: 0;
	width: 100vw;
	height: 100vh;
	height: 100dvh;
	z-index: -1;
	display: flex;
	flex-direction: column;
	gap: var(--space-8);
	padding: calc(72px + clamp(24px, 6vh, 56px)) var(--gutter) clamp(28px, 5vw, 40px);
	background: var(--surface-page);
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* The stagger. `assets/js/nav.js` adds `.open` a frame after removing `hidden`, which is what
   gives this something to run from. */
.hdr-drawer .drawer-link {
	opacity: 0;
	transform: translateY(12px);
	transition:
		opacity var(--dur-base) ease,
		transform var(--dur-base) var(--ease-out-soft),
		color var(--dur-hover) ease;
}

.hdr-drawer.open .drawer-link {
	opacity: 1;
	transform: none;
	transition-delay: calc(var(--i, 0) * 60ms);
}

.drawer-link {
	font-family: var(--font-display);
	font-size: var(--type-display-md);
	line-height: var(--lh-display);
	letter-spacing: normal;
	text-transform: none;
	text-decoration: none;
	color: var(--text-body);
	transition: color var(--dur-hover) ease;
}

.drawer-link:hover,
.drawer-link:focus-visible {
	color: var(--text-strong);
}

/* Upstream's own breakpoint. The mockups use six different ones and share no scale, so this
   stays a literal rather than becoming a token that claims a system exists. */
@media (max-width: 900px) {
	.hdr-nav {
		display: none;
	}

	.hdr-menu {
		display: inline-block;
	}

	.hdr-logo {
		position: static;
		transform: none;
	}
}

/* Above the breakpoint the panel never opens: `assets/js/nav.js` closes it when the viewport
   grows past 900, and this is the belt to that braces. */
@media (min-width: 901px) {
	.hdr-drawer {
		display: none;
	}
}

/* The footer --------------------------------------------------------------------------- */

.ftr {
	position: fixed;
	left: 0;
	bottom: 0;
	width: 100%;
	z-index: 0;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	/* The background and the on ink text colour come from `.fn-ink` and are not restated. */
	font-family: var(--font-text);
}

.ftr-cols {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: clamp(32px, 4vw, 72px);
	padding: clamp(52px, 6vw, 88px) var(--gutter) clamp(24px, 3vw, 40px);
}

.ftr-grid {
	flex: 1;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
	gap: clamp(28px, 3.4vw, 64px);
}

/* One column, from `FooterColumn.astro`. The head is the only uppercase rule 9 allows, and it is
   Bricolage rather than Inter, which is upstream's choice and the one place display type is used
   at 11px. */
.col-head {
	font-family: var(--font-display);
	font-size: var(--type-eyebrow);
	letter-spacing: var(--track-eyebrow);
	text-transform: uppercase;
	color: var(--text-label);
	margin-bottom: var(--space-8);
}

.col-body {
	display: flex;
	flex-direction: column;
	/* Upstream sets 12px between links and 9px between address lines. */
	gap: var(--space-5);
	font-size: var(--type-body-static);
}

.col-body.tight {
	gap: var(--space-3);
}

/* Phase 13, F25, the two column footer on a phone. Kept in step with `Footer.astro` and
   `FooterColumn.astro`, which is what `npm run qa`'s `chrome-parity` check measures: the front end
   got this first and the gate reported 60 failures on `/ostoskori/`, `/kassa/` and both checkouts
   until the same rules landed here. The reason those numbers are as they are is written on the
   front end copy and is not repeated.

   The one thing worth saying twice: `.ftr-cols` becoming a column is what gives `.ftr-grid` the
   full width between the gutters, and without that width two 160px tracks do not fit. The two
   declarations are one change and neither works alone. */
@media (max-width: 700px) {
	.ftr-cols {
		flex-direction: column;
		align-items: flex-end;
		gap: var(--space-8);
		padding-top: var(--space-10);
		padding-bottom: var(--space-7);
	}

	.ftr-grid {
		width: 100%;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--space-9) var(--space-8);
	}

	.col-head {
		margin-bottom: var(--space-5);
	}
}

.addr-line {
	color: var(--text-body-on-ink);
	line-height: var(--lh-normal);
}

/* `finferno-strong` in wp-admin. The brand name at the head of the address block. */
.addr-line.addr-name {
	color: var(--text-on-ink);
	font-weight: var(--weight-semibold);
}

/* Rule 13. Dimmed and monospaced, because it is data that is missing rather than copy that is
   short. Not invented, not removed. */
.addr-line.addr-stub {
	color: var(--text-muted-on-ink);
	font-family: var(--font-mono);
	font-size: var(--type-meta);
	line-height: var(--lh-normal);
}

/* `width: fit-content` is upstream's, and it keeps the hit area off the empty half of the column
   instead of spanning the grid track. */
.ftr-link {
	width: fit-content;
	color: var(--text-body-on-ink);
	text-decoration: none;
	transition: color var(--dur-hover) ease;
}

.ftr-link:hover,
.ftr-link:focus-visible {
	color: var(--text-on-ink);
}

/* Rule 9: uppercase with tracking, which is what a micro label is for. */
.to-top-label {
	font-size: var(--type-eyebrow);
	font-weight: var(--weight-bold);
	letter-spacing: var(--track-label);
	text-transform: uppercase;
}

/* The wordmark and the legal bar in one cell at the bottom of the page, both pinned to its
   bottom edge, the bar drawn over the mark. Every value here matches `Footer.astro`, where the
   reasoning is written out; the parity check measures the two against each other. */
.ftr-bottom {
	position: relative;
	display: grid;
}

.ftr-bottom > .ftr-word,
.ftr-bottom > .ftr-legal {
	grid-area: 1 / 1;
	align-self: end;
}

/* The veil, so the copyright and the four links stay legible over the letters. `--grad-film` is
   the design system's own protection gradient and is already used over three photographs
   elsewhere, which is why rule 1's ban on gradient backgrounds is not in play. */
.ftr-bottom::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background: var(--grad-film);
	pointer-events: none;
}

.ftr-word {
	display: block;
	overflow: hidden;
	color: var(--ink-word);
}

/* No `border-top`. A hairline drawn across the wordmark reads as a line through it rather than
   as a divider, and the veil separates the bar now. */
.ftr-legal {
	position: relative;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--space-7) clamp(20px, 2.5vw, 36px);
	padding: clamp(20px, 2.2vw, 30px) var(--gutter);
	font-size: var(--type-meta-sm);
	color: var(--text-muted-on-ink);
}

.legal-copy {
	line-height: var(--lh-normal);
}

/* No `margin-left: auto`, matching `Footer.astro`, where the reason is written out. Short version:
   `.ftr-legal`'s `space-between` already does the work on a wide screen, and on a narrow one the
   auto margin was what held the wrapped legal links against the right edge. */
.legal-nav {
	display: flex;
	gap: var(--space-8);
}

.legal-link {
	color: var(--grey-4);
	text-decoration: none;
	transition: color var(--dur-hover) ease;
}

.legal-link:hover,
.legal-link:focus-visible {
	color: var(--text-on-ink);
}

/* Type ---------------------------------------------------------------------------------- */

/* The page title, which is WooCommerce's and not this project's.
 *
 * `page-cart.html` and `page-checkout.html` both draw `wp:post-title`, and both are templates
 * this project may not override, so the heading exists whether the design asked for one or not.
 * It is styled rather than hidden: a page's only `h1` is not a decoration, and `display: none` on
 * it would take the page's name out of the accessibility tree to make a screenshot match.
 *
 * `--type-section` and not `--type-hero`, because it labels a page rather than opening one, and
 * because the cart's own content begins immediately under it. Sentence case is rule 9's and is
 * the editor's to keep: `Ostoskori` and `Kassa` are page titles in wp-admin, and nothing here
 * transforms them. */
.wp-block-post-title {
	font-family: var(--font-display);
	font-size: var(--type-section);
	font-weight: var(--weight-regular);
	line-height: var(--lh-display);
	letter-spacing: var(--track-display);
	color: var(--text-strong);
}

/* Rule 8. Bricolage for headings, tight, and the order flow's own headings included. */
.wc-block-components-title,
.wc-block-components-checkout-step__title,
.wc-block-cart__submit-container + *,
.woocommerce-order-received h1,
.woocommerce-order-received h2 {
	font-family: var(--font-display);
	font-weight: var(--weight-regular);
	line-height: var(--lh-display);
	letter-spacing: var(--track-display);
	color: var(--text-strong);
}

.wc-block-components-checkout-step__description,
.wc-block-components-order-summary__content {
	color: var(--text-body);
}

/* Rule 9. WooCommerce's step numbers and section labels are micro labels here. */
.wc-block-components-checkout-step__heading-content,
.wc-block-components-totals-item__label {
	font-size: var(--type-eyebrow);
	letter-spacing: var(--track-eyebrow);
	text-transform: uppercase;
	color: var(--text-label);
}

/* Controls -------------------------------------------------------------------------------
 *
 * Rule 6. Every button and every input is a full pill. 4px is the single most repeated value
 * in both shipped stylesheets and is the one that makes the checkout read as another
 * product. */

.wc-block-components-button,
.wc-block-components-checkout-place-order-button,
.wc-block-cart__submit-button,
.wc-block-components-totals-coupon__button {
	border-radius: var(--radius-pill);
	font-family: var(--font-text);
	font-size: var(--type-nav);
	font-weight: var(--weight-semibold);
	letter-spacing: normal;
	background: var(--action-fill);
	color: var(--action-label);
	border: none;
	box-shadow: none;
	transition: background-color var(--dur-hover) ease, color var(--dur-hover) ease;
}

/* Rule 5. Fill inversion, and explicitly not opacity: both shipped stylesheets set
   `opacity: .9` and `.8` on exactly these controls, and those declarations are what this
   overwrites. The `opacity: 1` is the correction rather than a style of its own. */
.wc-block-components-button:hover,
.wc-block-components-button:focus-visible,
.wc-block-components-checkout-place-order-button:hover,
.wc-block-components-checkout-place-order-button:focus-visible,
.wc-block-cart__submit-button:hover,
.wc-block-cart__submit-button:focus-visible,
.wc-block-components-totals-coupon__button:hover,
.wc-block-components-totals-coupon__button:focus-visible {
	background: var(--action-fill-hover);
	color: var(--action-label);
	opacity: 1;
}

/* The outlined variant, which the cart uses for "Continue shopping". */
.wc-block-components-button.outlined,
.wc-block-components-button:not(.is-link).outlined {
	background: var(--action-ghost-fill);
	color: var(--text-strong);
	box-shadow: inset 0 0 0 1px var(--action-ghost-border);
}

.wc-block-components-button.outlined:hover,
.wc-block-components-button.outlined:focus-visible {
	background: var(--action-fill);
	color: var(--action-label);
	opacity: 1;
}

/* A text link inside the flow. Rule 5's colour move, never opacity. */
.wc-block-components-button.is-link,
.wc-block-components-totals-shipping__change-address-button,
.wc-block-components-notice-banner .wc-forward {
	color: var(--text-strong);
	text-decoration: underline;
	transition: color var(--dur-hover) ease;
}

.wc-block-components-button.is-link:hover,
.wc-block-components-button.is-link:focus-visible,
.wc-block-components-totals-shipping__change-address-button:hover,
.wc-block-components-totals-shipping__change-address-button:focus-visible,
.wc-block-components-notice-banner .wc-forward:hover,
.wc-block-components-notice-banner .wc-forward:focus-visible {
	color: var(--accent);
	opacity: 1;
}

/* Inputs. Rule 6 again, and rule 7: no inner shadows anywhere in this system. */
.wc-block-components-text-input input[type='text'],
.wc-block-components-text-input input[type='email'],
.wc-block-components-text-input input[type='tel'],
.wc-block-components-text-input input[type='number'],
.wc-block-components-textarea,
.wc-block-components-combobox-control input,
.wc-block-components-select__container {
	border-radius: var(--radius-pill);
	border: 1px solid var(--border-default);
	background: var(--surface-card);
	color: var(--text-strong);
	font-family: var(--font-text);
	font-size: var(--type-body-sm);
	box-shadow: none;
	transition: border-color var(--dur-hover) ease;
}

.wc-block-components-text-input input:focus,
.wc-block-components-textarea:focus,
.wc-block-components-combobox-control input:focus {
	border-color: var(--text-strong);
	outline: 2px solid var(--ink);
	outline-offset: 2px;
	box-shadow: none;
}

.wc-block-components-text-input label,
.wc-block-components-checkbox__label,
.wc-block-components-radio-control__label {
	color: var(--text-body);
	font-size: var(--type-body-sm);
}

/* The quantity stepper on the cart line. Rule 6: an icon button is a perfect circle. */
.wc-block-components-quantity-selector {
	border-radius: var(--radius-pill);
	border: 1px solid var(--border-default);
	background: var(--surface-card);
}

.wc-block-components-quantity-selector__button {
	border-radius: var(--radius-round);
	color: var(--text-strong);
	background: transparent;
	transition: background-color var(--dur-hover) ease;
}

.wc-block-components-quantity-selector__button:hover,
.wc-block-components-quantity-selector__button:focus-visible {
	background: var(--surface-recessed);
	opacity: 1;
}

/* Surfaces --------------------------------------------------------------------------------
 *
 * Rule 6 for the radius, rule 7 for the shadow: warm and never neutral black, and no bordered
 * cards.
 *
 * One card per panel, and this is the correction to Phase 10's version of this rule rather than
 * a refinement of it. That version named six selectors in one list, and four of them are nested
 * inside the other two: WooCommerce builds the sidebar as a stack of `totals-wrapper` elements,
 * so painting them all produced white cards inside white cards, each with its own 20px radius and
 * its own shadow, and the inner ones bled past the outer one's edge because WooCommerce gives
 * them negative margins to reach it. Reported by the user with two screenshots, which is a worse
 * way to find it than the gate and is the reason check H exists for the chrome.
 *
 * Two panels are cards. Everything inside one is transparent. */

.wp-block-woocommerce-cart .wc-block-components-sidebar-layout .wc-block-cart__main,
.wp-block-woocommerce-cart .wc-block-components-sidebar-layout .wc-block-cart__sidebar,
.wp-block-woocommerce-checkout .wc-block-components-sidebar-layout .wc-block-checkout__sidebar,
.woocommerce-order-received .woocommerce-order-details,
.woocommerce-order-received .woocommerce-customer-details {
	border-radius: var(--radius-card);
	background: var(--surface-card);
	box-shadow: var(--shadow-card);
	border: none;
	/* WooCommerce lets its own content reach the panel edge, which is right for a column with no
	   fill and wrong for a card. The rows keep bleeding to the edge inside this, which is what
	   the hairlines further down are for. */
	padding: clamp(20px, 1.8vw, 28px);
}

/* The gutter between the two columns, which had to move before the padding above could exist.
 *
 * WooCommerce spaces the columns with `padding-right: 4.53%` on the main and `padding-left:
 * 2.26%` on the sidebar, which is the right call when neither has a fill: the padding is the
 * gutter. Give both a fill and the same padding is inside the card, so the gutter disappears and
 * the two cards touch, which is what the first attempt at this drew. The gap moves onto the flex
 * container and the widths become flex ratios of what is left, which is the same 65 to 35 the
 * percentages expressed.
 *
 * Above 782px only, which is WooCommerce's own breakpoint for stacking the two, read from
 * `assets/client/blocks/cart.css` rather than chosen here. Below it there is one column and no
 * gutter to place. */
@media (min-width: 783px) {
	.wp-block-woocommerce-cart .wc-block-components-sidebar-layout,
	.wp-block-woocommerce-checkout .wc-block-components-sidebar-layout {
		gap: clamp(16px, 2vw, 32px);
		/* Each card is its own height. A flex item stretches by default, which is invisible on two
		   columns with no fill and is a band of empty white under the shorter one the moment they
		   have one: a one line cart drew a card as tall as its own totals panel. */
		align-items: flex-start;
	}

	/* Width only. The first version of this zeroed `padding-right` on the main and `padding-left`
	   on the sidebar, to be rid of WooCommerce's percentage gutter, and those two declarations sit
	   after the card rule above and won: each card ended up with padding on one side and none on
	   the other, which is the crooked panel the user sent back. The card rule already overrides
	   both sides, so there is nothing here to undo. */
	.wp-block-woocommerce-cart .wc-block-components-sidebar-layout .wc-block-components-main,
	.wp-block-woocommerce-checkout .wc-block-components-sidebar-layout .wc-block-components-main {
		flex: 65 1 0;
		width: auto;
	}

	.wp-block-woocommerce-cart .wc-block-components-sidebar-layout .wc-block-components-sidebar,
	.wp-block-woocommerce-checkout .wc-block-components-sidebar-layout .wc-block-components-sidebar {
		flex: 35 1 0;
		width: auto;
	}
}

/* The card is the cart's left column and not the line item table inside it.
 *
 * `table.wc-block-cart-items` was the obvious target and cannot be one: WooCommerce ships
 * `background: none !important` on it, so this file drew a radius and a shadow around a
 * transparent box and the panel read as an outline of nothing. Matching an `!important` with
 * another was the alternative and was refused, because a stylesheet that wins by force is one
 * that stops being readable the first time somebody asks why. The column around the table has no
 * such rule and is the panel anyway. */

/* A separator between rows is a separator; above the first row it is a line under the card's own
   top padding with nothing above it. Visible on the phone checkout, where the summary collapses to
   a single row and drew a hairline over it. */
.wp-block-woocommerce-cart-order-summary-block > .wc-block-components-totals-wrapper:first-of-type,
.wc-block-components-checkout-order-summary__content > .wc-block-components-totals-wrapper:first-of-type,
/* The summary title carries a border on both of its edges, and the top one is the one that
   showed. Found by walking the sidebar and reading every computed border rather than by guessing
   at a class, after two selectors written from the markup as it looked turned out to match
   nothing: the totals wrappers are not children of the sidebar but of a block inside it. */
.wc-block-components-checkout-order-summary__title {
	border-top: none;
}

/* Nothing inside a panel is a second panel, and nothing inside one is framed.
 *
 * The order summary block carries a 1px border on all four sides, which is right in WooCommerce's
 * own design where the summary has no card around it and wrong the moment it does: it drew a
 * second rectangle inside the first, a few pixels off on every edge. The cart line table carries a
 * bottom border for the same reason, which inside a card is a rule under the last row with the
 * card's own padding below it. */
.wc-block-components-sidebar .wc-block-components-totals-wrapper,
.wc-block-components-sidebar .wc-block-components-order-summary,
.wc-block-components-checkout-order-summary__content,
.wc-block-components-order-summary__content {
	background: transparent;
	border-radius: 0;
	box-shadow: none;
	padding-left: 0;
	padding-right: 0;
}

.wp-block-woocommerce-checkout-order-summary-block,
.wp-block-woocommerce-cart-order-summary-block,
.wp-block-woocommerce-cart .wc-block-cart-items {
	border: none;
}

/* Collapsed, the summary is one row and needs no rules around it.
 *
 * Below WooCommerce's own breakpoint the order summary becomes a disclosure showing its title and
 * the total, and the title's two borders then sit inside the card's padding with nothing on either
 * side of them. The desktop rule further up is not enough on its own: a media query of
 * WooCommerce's own reinstates them with a longer selector. */
@media (max-width: 782px) {
	.wp-block-woocommerce-checkout
		.wp-block-woocommerce-checkout-order-summary-block
		.wc-block-components-checkout-order-summary__title {
		border-top: none;
		border-bottom: none;
	}
}

/* One inset, not two.
 *
 * WooCommerce insets every row by 16px and lets the separators run the full width of the block,
 * which is how a bordered box is meant to read. Inside a card the card's own padding is the inset,
 * so the 16px became a second one: the text sat a step in from the lines above and below it. The
 * rows now share their edge with the separators, and the only inset is the card's. */
/* The selectors are long because WooCommerce's are. Its own rules for these two insets are
   `.wp-block-woocommerce-checkout-order-summary-block .checkout-order-summary-block-fill
   .wc-block-components-totals-item` and a three class selector for the title, read from
   `assets/client/blocks/checkout.css`; a shorter one here loses and the row stays where it was,
   which is what the first attempt did. The cart needs none of this: WooCommerce already zeroes
   the same padding inside its own cart summary block. */
.wp-block-woocommerce-checkout .wp-block-woocommerce-checkout-order-summary-block .wc-block-components-totals-item,
.wp-block-woocommerce-checkout .wp-block-woocommerce-checkout-order-summary-block .wc-block-components-totals-coupon,
.wp-block-woocommerce-checkout .wc-block-components-sidebar .wc-block-components-panel,
.wc-block-cart-items__header th,
.wc-block-cart-items__row td:first-child,
.wc-block-cart-items__row td:last-child {
	padding-left: 0;
	padding-right: 0;
}

.wp-block-woocommerce-checkout
	.wp-block-woocommerce-checkout-order-summary-block
	.wc-block-components-checkout-order-summary__title
	.wc-block-components-checkout-order-summary__title-text {
	margin-left: 0;
}

/* The product thumbnail in a cart line. Rule 2: a cutout sits on the neutral plate. */
.wc-block-cart-item__image img,
.wc-block-components-order-summary-item__image img {
	border-radius: var(--radius-sm);
	background: var(--surface-plate);
}

.wc-block-components-product-name {
	font-family: var(--font-text);
	font-weight: var(--weight-semibold);
	color: var(--text-strong);
	text-decoration: none;
}

/* The sticky order summary, and the header it has to clear.
 *
 * WooCommerce sets `top: 24px` on this, which was right when the page above it scrolled away.
 * This site's header is sticky and 69px tall, so the summary parked underneath it and the order
 * total sat behind the bag. `--header-h` is published to the root by `assets/js/header.js`, the
 * same measurement the product gallery has used since Phase 5, and the fallback keeps the
 * arithmetic honest on a page where the script is blocked. */
.wp-block-woocommerce-checkout .wc-block-components-sidebar.wc-block-checkout__sidebar {
	top: calc(var(--header-h, 69px) + var(--space-6));
}

/* Rule 3. The order total is the number its section is about, and this is the one place ember is
   spent in the order flow. Nowhere else below carries it.
 *
 * `--type-display-md` and not `--type-stat`. A stat is a number a whole section is built around,
 * 40px at this viewport, and in a 386px sidebar beside its own label it ran into the panel edge.
 * This is the same decision Phase 9 made for the page title, one step down the scale to the size
 * the place can actually hold. */
.wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
	color: var(--accent);
	font-family: var(--font-display);
	font-size: var(--type-display-md);
	line-height: var(--lh-tight);
}

.wc-block-components-product-price__value,
.wc-block-components-totals-item__value {
	color: var(--text-strong);
	font-variant-numeric: tabular-nums;
}

/* Hairlines. Rule 7 forbids a bordered card, not a rule between rows.
 *
 * The four selectors added in Phase 11 are the separators inside a panel, which WooCommerce draws
 * in its own ink at 20 percent. Left alone they were the only lines on these pages not in the
 * design's own colour, which is visible where two of them meet a card edge. */
.wc-block-cart-items__row,
.wc-block-cart-items__row td,
.wc-block-components-totals-item,
.wc-block-components-totals-wrapper,
.wc-block-components-checkout-order-summary__title,
.wc-block-cart-items__header,
.wc-block-cart-items__header th,
.wp-block-woocommerce-cart-order-summary-block,
.wp-block-woocommerce-checkout-order-summary-coupon-form-block,
.wp-block-woocommerce-checkout-order-summary-totals-block {
	border-color: var(--border-subtle);
}

/* Notices ---------------------------------------------------------------------------------
 *
 * Rule 3 is the whole question here. WooCommerce draws four states in four colours it owns,
 * `#cc1818` for error, `#4ab866` for success, `#f0b849` for warning and `#0675c4` for info,
 * and none of the four is a colour this system has.
 *
 * They are not repainted in ember. Ember marks heat, quantity and the single number a section
 * is about, and an error is none of those; painting an error in the brand accent would also
 * make a failed payment look like a price. The states are drawn in ink on the two surfaces
 * the system already has, and the difference between them is carried by the icon WooCommerce
 * already ships and by the words, which is how the rest of this project distinguishes a stub
 * from a value. */
.wc-block-components-notice-banner {
	border-radius: var(--radius-card);
	border: none;
	box-shadow: var(--shadow-soft);
	background: var(--surface-recessed);
	color: var(--text-strong);
}

.wc-block-components-notice-banner.is-error {
	background: var(--surface-ink);
	color: var(--text-on-ink);
}

.wc-block-components-notice-banner.is-error a,
.wc-block-components-notice-banner.is-error .wc-block-components-button.is-link {
	color: var(--text-on-ink);
}

.wc-block-components-validation-error {
	color: var(--text-strong);
	font-size: var(--type-body-xs);
}

/* Rule 10. Every animation in the system stops here, without exception. WooCommerce ships
   its own spinners and slide transitions, and the rule does not carve out a plugin.
 *
 * The chrome's own guards are in the same block rather than beside each component, because a
 * reader checking rule 10 on these pages should find one list and not eleven. Every selector
 * below that starts a transform is also given `transform: none` at its hover pair, which is what
 * the front end's components each do in their own scoped block. */
@media (prefers-reduced-motion: reduce) {
	.wc-block-components-button,
	.wc-block-components-quantity-selector__button,
	.wc-block-components-text-input input,
	.hdr,
	.hdr-link,
	.hdr-lang,
	.lang-sep,
	.lang-off,
	.hdr-menu,
	.bars > span,
	.drawer-link,
	.hdr-drawer .drawer-link,
	.logo-flame,
	.ibtn,
	.v-on-ink,
	.ftr-link,
	.legal-link {
		transition: none;
	}

	.logo:hover .logo-flame,
	.logo:focus-visible .logo-flame,
	.v-on-ink:hover,
	.v-on-ink:focus-visible {
		transform: none;
	}

	/* The menu stagger, removed rather than shortened: an item is simply there when the panel
	   opens, with no delay left to run and no transform left applied. */
	.hdr-drawer .drawer-link {
		opacity: 1;
		transform: none;
	}

	.hdr-drawer.open .drawer-link {
		transition-delay: 0s;
	}

	.wc-block-components-spinner,
	.wc-block-components-loading-mask__children {
		animation: none;
	}
}
