/* Store styles. Loaded after paytrim/styles.css; uses only its variables.
   Sections: 1 base, 2 layout, 3 typography, 4 buttons, 5 forms, 6 panels, 7 badge and count,
   8 tables, 9 utilities, then the shell and the pages: 10 top bar and footer, 11 products,
   12 product detail, 13 cart, 14 status pages, 15 fake payment page, and 16 reduced motion.
   Breakpoints (media queries cannot use variables), mobile first: 640px and 960px, plus 1200px for
   the four-column product grid and 820px for the two-column product page. */

/* 1. Base: Ice page, body as a column so a footer can sit at the bottom, one focus style */
html { accent-color: var(--deep-sea); }
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}
img { height: auto; }

/* Focus: the design system's ring, plus a thin solid line so it stays visible on any background.
   The line is Freezing a little darker (--focus-line): plain Freezing is 3.1:1 on white but only
   2.8:1 on the Ice page, under the 3:1 a focus indicator needs. */
:root { --focus-line: oklch(from var(--border-focus) calc(l - 0.08) c h); }
a:focus-visible,
button:focus-visible {
  outline: var(--border-width-strong) solid var(--focus-line);
  outline-offset: var(--border-width);
  box-shadow: var(--focus-ring);
}

/* 2. Layout: main is the narrow column (--container-narrow); main.wide is the wide one
   (--container-max). --page-gutter is the side inset, shared with the nav so the two line up.
   --tap-h is the height of the small controls (stepper, add-to-cart button, back link, Remove):
   40px on phones so a finger can hit them, the compact 32px from 640px. --field-border is the edge
   of fields and steppers: neutral-500 (3.4:1 on white) instead of the lighter --border-default,
   which is only 1.5:1 and too faint to find a field by (WCAG 1.4.11 asks for 3:1). */
:root {
  --page-gutter: var(--space-4);
  --tap-h: var(--control-height);
  --field-border: var(--neutral-500);
  --field-border-hover: var(--neutral-700);
}
main {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
  gap: var(--space-4);
  width: 100%;
  max-width: var(--container-narrow);
  margin: 0 auto;
  padding: var(--space-6) var(--page-gutter) var(--space-12);
}
main.wide {
  max-width: var(--container-max);
  gap: var(--space-6);
}
@media (min-width: 640px) {
  :root {
    --page-gutter: var(--gutter-page);
    --tap-h: var(--control-height-sm);
  }
  main { padding-top: var(--space-8); padding-bottom: var(--space-16); }
}
@media (min-width: 960px) {
  main.wide { padding-top: var(--space-10); }
}

/* 3. Typography: heading scale from the tokens, the hero heading, eyebrow, tabular figures */
h1,
h2 {
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}
main > h1 { margin-bottom: var(--space-2); }

/* Display: the large marketing-style heading, for a hero */
.display {
  font-size: var(--text-display-2);
  font-weight: var(--font-weight-black);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}
.lead {
  color: var(--text-secondary);
  font-size: var(--text-body-lg);
  line-height: var(--leading-relaxed);
}

/* Eyebrow: the small themed line above a heading, sentence case (the tracking does the work) */
.eyebrow {
  display: block;
  color: var(--text-secondary);
  font-size: var(--text-caption);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-wide);
}
.eyebrow--inverse { color: color-mix(in srgb, var(--frosted) 80%, transparent); }

/* Numbers: tabular figures, also on the cart's amounts. (Quiet text uses --text-secondary;
   --text-muted is too faint for text.) */
.num,
.price,
.cart-line-price,
.cart-line-total,
.cart-quantity,
.cart-row,
.cart-total,
.cart-vat,
input[type="number"] { font-variant-numeric: tabular-nums; }
.price {
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
}

/* 4. Buttons: .button and every bare button share one look. The variants and sizes below only
   set --btn-* variables, so hover, press, focus and disabled are written once. */
button,
.button,
.back-link {
  --btn-bg: var(--action-primary-bg);
  --btn-bg-hover: var(--action-primary-bg-hover);
  --btn-bg-active: var(--action-primary-bg-active);
  --btn-fg: var(--action-primary-fg);
  --btn-fg-hover: var(--btn-fg);
  --btn-border: transparent;
  --btn-h: var(--control-height);
  --btn-px: var(--space-4);
  --btn-fs: var(--text-body-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--btn-h);
  padding: 0 var(--btn-px);
  border: var(--border-width) solid var(--btn-border);
  border-radius: var(--radius-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: inherit;
  font-size: var(--btn-fs);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: var(--transition-control);
}
button:hover,
.button:hover,
.back-link:hover {
  background: var(--btn-bg-hover);
  color: var(--btn-fg-hover);
  text-decoration: none;
}
button:active,
.button:active,
.back-link:active { background: var(--btn-bg-active); }
button:focus-visible,
.button:focus-visible,
.back-link:focus-visible { border-radius: var(--radius-sm); }

/* Disabled: neutral fill and text, no border colour, no hover or press change */
button:disabled,
button:disabled:hover,
button:disabled:active {
  border-color: transparent;
  background: var(--action-disabled-bg);
  color: var(--action-disabled-fg);
  cursor: not-allowed;
}

/* Variants: .button is primary (Deep Sea, one per view), plus secondary and ghost */
.button--secondary {
  --btn-bg: var(--action-secondary-bg);
  --btn-bg-hover: var(--action-secondary-bg-hover);
  --btn-bg-active: var(--deep-sea-12);
  --btn-fg: var(--action-secondary-fg);
  --btn-border: var(--action-secondary-border);
}
.button--ghost {
  --btn-bg: transparent;
  --btn-bg-hover: var(--action-ghost-bg-hover);
  --btn-bg-active: var(--deep-sea-12);
  --btn-fg: var(--action-ghost-fg);
}

/* Sizes: medium (40px) is the default, large is 48px; --block fills the width */
.button--lg {
  --btn-h: var(--control-height-lg);
  --btn-px: var(--space-6);
  --btn-fs: var(--text-body);
}
.button--block {
  display: flex;
  width: 100%;
}

/* The back link and the add-to-cart button have no button classes, so they are mapped onto the
   variants here; the cart's own buttons are styled in section 13 */
.back-link {
  --btn-bg: var(--action-secondary-bg);
  --btn-bg-hover: var(--action-secondary-bg-hover);
  --btn-bg-active: var(--deep-sea-12);
  --btn-fg: var(--action-secondary-fg);
  --btn-border: var(--action-secondary-border);
  --btn-h: var(--tap-h);
  --btn-px: var(--space-3);
  align-self: flex-start;
}
.add-to-cart button[type="submit"] {
  --btn-h: var(--tap-h);
  --btn-px: var(--space-3);
}

/* 5. Forms: label above or beside the control; controls are 40px with a --field-border edge and
   the focus ring. Fields are 16px on small screens so iOS does not zoom in on focus. */
form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-secondary);
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-medium);
}
input[type="number"],
select {
  height: var(--control-height);
  padding: 0 var(--space-3);
  border: var(--border-width) solid var(--field-border);
  border-radius: var(--radius-sm);
  background: var(--surface-card);
  color: var(--text-primary);
  font-family: inherit;
  font-size: var(--text-body);
  transition: var(--transition-control);
}
input[type="number"] { width: var(--space-16); }
input:enabled:hover,
select:enabled:hover { border-color: var(--field-border-hover); }
input:focus-visible,
select:focus-visible {
  outline: none;
  border-color: var(--border-brand);
  border-radius: var(--radius-sm);
  box-shadow: var(--focus-ring);
}
input:disabled,
select:disabled {
  border-color: var(--border-subtle);
  background: var(--surface-sunken);
  color: var(--text-disabled);
  cursor: not-allowed;
}
@media (min-width: 640px) {
  input[type="number"],
  select { font-size: var(--text-body-sm); }
}

/* Field: label and control stacked; the control fills the width */
.field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-1);
}
.field :is(input, select) { width: 100%; }

/* 6. Panels: a white card with a hairline border and the lightest shadow. A bare table gets the
   same look (at zero specificity, so any class overrides it). .band is the one Deep Sea block
   per view. */
.panel,
:where(table) {
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}
.panel { padding: var(--space-4); }
@media (min-width: 640px) {
  .panel { padding: var(--space-5); }
}
.panel--flush {
  padding: 0;
  overflow: hidden;
}
.receipt h2,
.cart-summary h2,
.cart-empty h2,
.product-block h2 {
  font-size: var(--text-heading-3);
  font-weight: var(--font-weight-semibold);
}

.band {
  padding: var(--space-8) var(--space-6);
  border: 0;
  border-radius: var(--radius-xl);
  background: var(--surface-brand);
  box-shadow: none;
  color: var(--text-on-brand);
}
.band h1 { color: var(--text-on-brand); }
.band .lead { color: color-mix(in srgb, var(--frosted) 80%, transparent); }
@media (min-width: 960px) {
  .band { padding: var(--space-12) var(--space-10); }
}

/* 7. Badge and count: a pill for a short status word (a neutral one by default, the warning
   badge marks the fake payment page), and the cart item count in the top bar. The warning text is
   a darker shade than the tint so it passes 4.5:1 contrast. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--space-5);
  padding: 0 var(--space-2);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-full);
  background: var(--neutral-100);
  color: var(--text-secondary);
  font-size: var(--text-caption);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  white-space: nowrap;
}
.badge--warning {
  border-color: transparent;
  background: var(--status-warning-surface);
  color: oklch(from var(--midnight-sun) calc(l - 0.32) c h);
}

/* Count: a round Deep Sea pill with a number; .count--muted for zero */
.count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-width: var(--space-5);
  height: var(--space-5);
  padding: 0 var(--space-1);
  border-radius: var(--radius-full);
  background: var(--action-primary-bg);
  color: var(--action-primary-fg);
  font-size: var(--text-caption);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.count--muted {
  background: var(--neutral-100);
  color: var(--text-secondary);
}

/* 8. Tables: hairline row rules, no vertical rules, small muted header labels. A bare table is a
   rounded card (separate borders so the radius shows); inside a .panel it is plain. */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  font-variant-numeric: tabular-nums;
}
th,
td {
  padding: var(--space-3) var(--space-2);
  border-bottom: var(--border-width) solid var(--border-subtle);
  text-align: left;
}
th:first-child,
td:first-child { padding-left: var(--space-4); }
th:last-child,
td:last-child { padding-right: var(--space-4); }
th {
  color: var(--text-secondary);
  font-size: var(--text-caption);
  font-weight: var(--font-weight-regular);
}
tbody tr:last-child td { border-bottom: none; }
tfoot td,
tfoot th {
  border-top: var(--border-width) solid var(--border-subtle);
  border-bottom: none;
  color: var(--text-primary);
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-semibold);
}
.table--zebra tbody tr:nth-child(even) { background: var(--surface-tint); }
.panel table {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
th.num,
td.num { text-align: right; }
@media (min-width: 640px) {
  th,
  td { padding-right: var(--space-3); padding-left: var(--space-3); }
  th:first-child,
  td:first-child { padding-left: var(--space-4); }
  th:last-child,
  td:last-child { padding-right: var(--space-4); }
}

/* 9. Utilities: a vertical flex stack with a small-gap modifier (the hero band) */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap, var(--space-4));
}
.stack--sm { --stack-gap: var(--space-2); }

/* 10. Shell: a sticky white top bar (logo left, links right) and a slim footer. Both line up
   with the page column: --shell-inset is the side padding that matches main's content edge, and
   --nav-width is the wide column when the page uses main.wide. */
body {
  --nav-width: var(--container-narrow);
  --shell-inset: max(var(--page-gutter), calc((100% - var(--nav-width)) / 2 + var(--page-gutter)));
}
body:has(main.wide) { --nav-width: var(--container-max); }

.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--surface-card);
  border-bottom: var(--border-width) solid var(--border-subtle);
}
nav {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--shell-inset);
}
nav a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--control-height);
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  transition: var(--transition-control);
}
nav a:hover {
  background: var(--action-ghost-bg-hover);
  color: var(--text-link);
  text-decoration: none;
}
nav a[aria-current="page"] { color: var(--text-link); }

/* The logo: first child, flush with the column edge; it pushes the links to the right */
nav a:first-child {
  margin-right: auto;
  padding: 0;
}
nav a:first-child:hover { background: none; }
nav a:first-child img {
  height: var(--space-5);
  width: auto;
}

/* Cart link: decorative icon, the word, then the count pill (a muted zero when the cart is
   empty). The last link's side padding hangs into the gutter so the pill meets the column edge. */
.cart-link img {
  width: var(--space-5);
  height: var(--space-5);
}
nav a:last-child { margin-right: calc(var(--space-2) * -1); }

/* Phones: nothing in the bar may shrink (a squeezed logo or count pill looks broken), so room is
   made instead. Below 400px the links give up some side padding; below 340px the cart icon goes
   and the logo gets a little smaller. A three-digit count then fits at 360px and at 320px. */
nav a { flex: none; }
@media (max-width: 399px) {
  nav a { padding: 0 var(--space-1); }
  nav a:last-child { margin-right: calc(var(--space-1) * -1); }
}
@media (max-width: 339px) {
  .cart-link img { display: none; }
  nav a:first-child img { height: calc(var(--space-4) + var(--space-1) / 2); }
}
@media (min-width: 640px) {
  nav { padding-top: var(--space-3); padding-bottom: var(--space-3); }
  nav a { padding: 0 var(--space-3); }
  nav a:last-child { margin-right: calc(var(--space-3) * -1); }
  nav a:first-child img { height: var(--space-6); }
}

/* Footer: hairline on top, quiet caption text; stacked on phones, split on wider screens.
   It sits at the bottom of short pages because main grows (section 2). */
footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-6);
  padding: var(--space-5) var(--shell-inset);
  background: var(--surface-card);
  border-top: var(--border-width) solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: var(--text-caption);
}
footer p { margin: 0; }
.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.footer-brand img {
  height: var(--space-4);
  width: auto;
  opacity: 0.6; /* the logo repeats the word before it, so it matches the quiet text colour */
}

/* 11. Products: the hero band and the grid of listing cards, the name block shared with the
   product page and cart, and the add-to-cart control (variation picker, quantity stepper and
   button) shared with the product page. */
.hero .display { font-size: var(--text-heading-1); }
.hero > h1 { max-width: 18em; }
.hero > .lead { max-width: 36em; }
@media (min-width: 640px) {
  .hero .display { font-size: var(--text-display-2); }
}

.product-heading {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.short-description {
  color: var(--text-secondary);
  font-size: var(--text-body-sm);
}

/* Grid: one column on phones, two from 640px, four from 1200px (the add-to-cart row needs
   about 250px, so three columns for four products would be too tight and leave an orphan). */
.products {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}
@media (min-width: 640px) {
  .products { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
  .products { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Listing card: a .panel with the photo on white at a fixed ratio, the name block (grows, so
   every card's price and add-to-cart row line up at the bottom), the price and the control.
   The name link is stretched over the whole card (via ::after); the add-to-cart control sits
   above that overlay (z-index) so it still works on its own. */
.product-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  transition: var(--transition-control);
}
.product-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}
.product-card-media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
.product-card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.product-card-body { flex: 1 1 auto; }
.product-card h2 {
  font-size: var(--text-body-lg);
  font-weight: var(--font-weight-semibold);
}
.product-card h2 a {
  color: inherit;
  text-decoration: none;
}
.product-card h2 a::after {
  content: "";
  position: absolute;
  inset: calc(var(--border-width) * -1);
  border-radius: var(--radius-md);
}
.product-card h2 a:focus-visible { outline: none; box-shadow: none; }
.product-card h2 a:focus-visible::after {
  outline: var(--border-width-strong) solid var(--focus-line);
  outline-offset: var(--border-width);
  box-shadow: var(--focus-ring);
}
.product-card-price { font-size: var(--text-heading-3); }
.product-card .add-to-cart {
  position: relative;
  z-index: 1;
}
.product-card .add-to-cart button[type="submit"] {
  --btn-px: var(--space-1);
  flex: 1 1 auto;
}

/* Add-to-cart control: the quantity stepper, then the button. The "−" and "+" buttons stay hidden
   until store.js has wired them up and marked the stepper .is-enhanced; without the script the
   plain number field still works. The native spinner arrows never show (they would flash before
   the script runs, and the buttons replace them). */
.add-to-cart {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.quantity-stepper {
  display: inline-flex;
  align-items: center;
}
.quantity-stepper input {
  width: var(--space-10);
  height: var(--tap-h);
  padding: 0 var(--space-1);
  text-align: center;
  appearance: textfield;
  -moz-appearance: textfield;
}
.quantity-stepper input::-webkit-outer-spin-button,
.quantity-stepper input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.quantity-stepper button { display: none; }

/* Wired up by the script: one joined control, neutral so the Deep Sea button is the only
   primary action. The input overlaps the buttons' borders by one pixel (so they read as one
   hairline) and the focused or hovered part is lifted above its neighbours. */
.quantity-stepper.is-enhanced button {
  --btn-bg: var(--action-secondary-bg);
  --btn-bg-hover: var(--surface-hover);
  --btn-bg-active: var(--border-subtle);
  --btn-fg: var(--text-primary);
  --btn-border: var(--field-border);
  --btn-h: var(--tap-h);
  --btn-fs: var(--text-body);
  position: relative;
  display: inline-flex;
  width: var(--tap-h);
  padding: 0;
  border-radius: 0;
}
.quantity-stepper.is-enhanced button:first-child {
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
.quantity-stepper.is-enhanced button:last-child {
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.quantity-stepper.is-enhanced button:hover,
.quantity-stepper.is-enhanced button:focus-visible { z-index: 1; }
.quantity-stepper.is-enhanced button:disabled,
.quantity-stepper.is-enhanced button:disabled:hover {
  border-color: var(--border-subtle);
}
.quantity-stepper.is-enhanced input {
  position: relative;
  margin: 0 calc(var(--border-width) * -1);
  border-radius: 0;
}
.quantity-stepper.is-enhanced input:hover,
.quantity-stepper.is-enhanced input:focus-visible {
  z-index: 1;
  border-radius: 0;
}

/* Variation picker: the first thing in the form when a product has variations. A muted caption
   over a row of pills that wraps onto more rows when the card is narrow. The fieldset takes the
   whole row of the flex form. Each radio is stretched over its pill and made transparent (not
   hidden), so the pill is the hit area and the arrow keys and Tab still work without a script.
   Selected: Deep Sea edge and text on the Snowflake tint, the edge made heavier with an inset
   line instead of a wider border, so nothing shifts; the Deep Sea button stays the only primary
   action. */
.variation-picker {
  flex: 1 1 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.variation-picker legend {
  margin-bottom: var(--space-2);
  padding: 0;
  color: var(--text-secondary);
  font-size: var(--text-caption);
  font-weight: var(--font-weight-medium);
}
.variation-options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.variation-option {
  position: relative;
  display: flex;
  min-width: 0;
}
.variation-option input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.variation-option span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap-h);
  min-height: var(--tap-h);
  padding: var(--space-1) var(--space-3);
  border: var(--border-width) solid var(--field-border);
  border-radius: var(--radius-sm);
  background: var(--surface-card);
  color: var(--text-primary);
  text-align: center;
  transition: var(--transition-control);
}
.variation-option:hover span { background: var(--surface-hover); }
.variation-option input:checked + span {
  border-color: var(--border-brand);
  background: var(--surface-tint);
  box-shadow: inset 0 0 0 var(--border-width) var(--border-brand);
  color: var(--text-link);
}
.variation-option input:focus-visible + span {
  outline: var(--border-width-strong) solid var(--focus-line);
  outline-offset: var(--border-width);
  box-shadow: var(--focus-ring);
}
.variation-option input:checked:focus-visible + span {
  box-shadow: inset 0 0 0 var(--border-width) var(--border-brand), var(--focus-ring);
}

/* 12. Product detail: a square photo panel beside one text column (name, short description,
   price, add-to-cart, then the description and the specs as quiet rows); stacked in the same order
   below 820px (the panel is 4:3 between 640px and 819px so it does not fill the screen). The
   section is only a layout grid. From 820px the photo stays in view while the column scrolls
   (under the 64px top bar). */
.product-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}
.product-media {
  aspect-ratio: 1;
  padding: var(--space-4);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}
.product-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-md);
}
.product-info {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}
.product-info:only-child { grid-column: 1 / -1; }
.product-info h1 { font-size: var(--text-heading-1); }
.product-info .short-description { font-size: var(--text-body); }
.product-info p { margin: 0; }

/* Price: one large light numeral (the design system's metric style), no shipping or stock claims */
.product-price {
  font-size: clamp(var(--text-heading-1), 3.75vw, var(--text-metric-lg));
  font-weight: var(--font-weight-light);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}

/* Add-to-cart at the comfortable size: 40px pills, stepper and button, the button fills the row */
.product-info .add-to-cart {
  gap: var(--space-3);
  max-width: 28rem;
}
.product-info .quantity-stepper input {
  width: var(--space-12);
  height: var(--control-height);
}
.product-info .quantity-stepper.is-enhanced button {
  --btn-h: var(--control-height);
  width: var(--control-height);
}
.product-info .add-to-cart button[type="submit"] {
  --btn-h: var(--control-height);
  --btn-px: var(--space-6);
  flex: 1 1 auto;
}
.product-info .variation-option span { min-height: var(--control-height); }

/* Description and specs: a divider under the buy area, then headings with their content */
.product-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.add-to-cart + .product-block {
  margin-top: var(--space-2);
  padding-top: var(--space-6);
  border-top: var(--border-width) solid var(--border-subtle);
}
.product-block + .product-block { margin-top: var(--space-4); }
.product-description {
  max-width: 60ch;
  font-size: var(--text-body);
  line-height: var(--leading-relaxed);
}
/* Specs reuse the .details rows (section 14); the values go regular so they sit calmly under the
   description (the compound selector outranks .details dd, which comes later in the file) */
.details.product-specs dd { font-weight: var(--font-weight-regular); }
@media (min-width: 640px) and (max-width: 819px) {
  .product-media { aspect-ratio: 4 / 3; }
}
@media (min-width: 820px) {
  .product-detail {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-10);
  }
  .product-media {
    position: sticky;
    top: calc(var(--space-16) + var(--space-4));
  }
}

/* 13. Cart: the lines panel and the order summary panel. Stacked below 960px; from 960px the
   summary sits beside the lines and stays in view while the lines scroll (under the 64px top
   bar). A line is a grid: on phones the photo, the name block and the line total share the top
   row with the stepper and Remove beneath; from 640px it is one row (photo, name block, stepper
   with Remove under it, line total). */
.cart {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}
.cart-lines {
  list-style: none;
  margin: 0;
}
.cart-line + .cart-line { border-top: var(--border-width) solid var(--border-subtle); }
.cart-line {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "image info total"
    "image actions actions";
  align-items: start;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-4);
}
.cart-line p { margin: 0; }
.cart-line img {
  grid-area: image;
  width: var(--space-16);
  height: var(--space-16);
  object-fit: cover;
  border-radius: var(--radius-md);
}
.cart-line-info {
  grid-area: info;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.cart-line-info a {
  padding-block: var(--space-2);
  margin-block: calc(var(--space-2) * -1);
  color: var(--text-primary);
  font-size: var(--text-body);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
}
.cart-line-info a:hover { text-decoration: underline; }
.cart-line-price {
  color: var(--text-secondary);
  font-size: var(--text-body-sm);
}
.cart-line-total {
  grid-area: total;
  font-size: var(--text-body);
  font-weight: var(--font-weight-semibold);
  text-align: right;
  white-space: nowrap;
}
.cart-line-actions {
  grid-area: actions;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
}

/* Quantity stepper: the neutral joined control of the listing (minus, the shown quantity, plus),
   one hairline around all three. The quantity box overlaps its neighbours' borders by one pixel
   and the hovered or focused part is lifted above them. A disabled button keeps a subtle border
   so the seam stays closed. */
.cart-stepper {
  display: inline-flex;
  align-items: center;
}
.cart-stepper button {
  --btn-bg: var(--action-secondary-bg);
  --btn-bg-hover: var(--surface-hover);
  --btn-bg-active: var(--border-subtle);
  --btn-fg: var(--text-primary);
  --btn-border: var(--field-border);
  --btn-h: var(--tap-h);
  --btn-fs: var(--text-body);
  position: relative;
  width: var(--tap-h);
  padding: 0;
  border-radius: 0;
}
.cart-stepper form:first-child button { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.cart-stepper form:last-child button { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.cart-stepper button:hover,
.cart-stepper button:focus-visible { z-index: 1; }
.cart-stepper button:disabled,
.cart-stepper button:disabled:hover { border-color: var(--border-subtle); }
.cart-quantity {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--space-10);
  height: var(--tap-h);
  margin: 0 calc(var(--border-width) * -1);
  padding: 0 var(--space-1);
  border: var(--border-width) solid var(--field-border);
  background: var(--surface-card);
  font-size: var(--text-body-sm);
  font-weight: var(--font-weight-medium);
}

/* Remove: a quiet text button, flush with the right edge of the line on phones */
.cart-remove button {
  --btn-bg: transparent;
  --btn-bg-hover: var(--action-ghost-bg-hover);
  --btn-bg-active: var(--deep-sea-12);
  --btn-fg: var(--text-secondary);
  --btn-fg-hover: var(--text-primary);
  --btn-h: var(--tap-h);
  --btn-px: var(--space-2);
}
.cart-remove { margin-right: calc(var(--space-2) * -1); }

/* Order summary: label and amount rows, Totalt as the biggest number, then the checkout button
   and one quiet line under it */
.cart-summary {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.cart-summary h2,
.cart-summary p { margin: 0; }
.cart-row,
.cart-total,
.cart-vat {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
}
.cart-row {
  font-size: var(--text-body-sm);
}
.cart-row span:first-child { color: var(--text-secondary); }
.cart-total {
  margin-top: var(--space-1);
  padding-top: var(--space-4);
  border-top: var(--border-width) solid var(--border-subtle);
  font-size: var(--text-body);
  font-weight: var(--font-weight-semibold);
}
.cart-total strong {
  font-size: var(--text-heading-2);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-snug);
  line-height: var(--leading-tight);
  white-space: nowrap;
}
.cart-vat {
  margin-top: calc(var(--space-1) * -1);
  color: var(--text-secondary);
  font-size: var(--text-caption);
}
.cart-checkout { margin-top: var(--space-2); }
.cart-note {
  color: var(--text-secondary);
  font-size: var(--text-caption);
  text-align: center;
}

/* Busy checkout button: store.js sets aria-busy and disables the button after the first click.
   It keeps readable text and shows a small ring; under reduced motion the ring stands still. */
.cart-checkout button[aria-busy="true"],
.cart-checkout button[aria-busy="true"]:hover,
.cart-checkout button[aria-busy="true"]:active {
  color: var(--neutral-700);
  cursor: progress;
}
.cart-checkout button[aria-busy="true"]::before {
  content: "";
  flex: none;
  width: var(--space-4);
  height: var(--space-4);
  border: var(--border-width-strong) solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-full);
  animation: cart-busy calc(var(--duration-slow) * 3) linear infinite;
}
@keyframes cart-busy { to { transform: rotate(360deg); } }

/* Empty state: a panel with a small icon, a heading, one line and the way back to the shop */
.cart-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-12) var(--space-4);
  text-align: center;
}
.cart-empty h2,
.cart-empty p { margin: 0; }
.cart-empty p {
  max-width: 28rem;
  color: var(--text-secondary);
}
.cart-empty-icon {
  width: var(--space-10);
  height: var(--space-10);
  color: var(--text-secondary);
}
.cart-empty .button { margin-top: var(--space-2); }

@media (min-width: 640px) {
  .cart-line {
    grid-template-columns: auto minmax(0, 1fr) auto 6rem;
    grid-template-areas: "image info actions total";
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-5);
  }
  .cart-line img {
    width: var(--space-20);
    height: var(--space-20);
  }
  .cart-line-actions {
    flex-direction: column;
    flex-wrap: nowrap;
    justify-content: center;
    gap: var(--space-1);
  }
  .cart-remove { margin-right: 0; }
  .cart-empty { padding: var(--space-16) var(--space-5); }
}
@media (min-width: 960px) {
  .cart {
    grid-template-columns: minmax(0, 1fr) 22rem;
    gap: var(--space-6);
  }
  .cart-summary {
    position: sticky;
    top: calc(var(--space-16) + var(--space-4));
  }
}

/* 14. Status pages: success and failed (pending and error reuse it). One centred panel holds a
   round tinted mark (see _status_mark.html), the h1 and a line of text, then optionally a callout,
   a details list and the action. The modifier only sets two local variables, --status-ink and
   --status-tint, from the status tokens (the inks are the same darker shades as the matching
   .badge, so icon and text keep their contrast). Status colour is for status, nothing else. */
.status--success,
.status-mark--success {
  --status-ink: oklch(from var(--mid-summer) calc(l - 0.20) c h);
  --status-tint: var(--status-success-surface);
}
.status--pending,
.status-mark--pending {
  --status-ink: oklch(from var(--midnight-sun) calc(l - 0.32) c h);
  --status-tint: var(--status-warning-surface);
}
.status--failed,
.status-mark--failed {
  --status-ink: oklch(from var(--strawberry) calc(l - 0.05) c h);
  --status-tint: var(--status-danger-surface);
}
.status--info,
.status-mark--info {
  --status-ink: var(--deep-sea);
  --status-tint: var(--surface-tint);
}

.status {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-4) var(--space-6);
  text-align: center;
}
.status h1 {
  margin: 0;
  font-size: var(--text-heading-2);
  text-wrap: balance;
}
.status-text {
  max-width: 28rem;
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-body);
  text-wrap: balance;
}
.status h1 + .status-text { margin-top: calc(-1 * var(--space-2)); }

/* The mark: 64px circle, 32px icon; the 1.5 stroke in the 24 grid draws as the 2px line */
.status-mark {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--space-16);
  height: var(--space-16);
  border-radius: var(--radius-full);
  background: var(--status-tint, var(--surface-tint));
  color: var(--status-ink, var(--deep-sea));
}
.status-mark svg {
  width: var(--space-8);
  height: var(--space-8);
  stroke-width: 1.5;
}

/* Callout: the one line that says why (a status colour tint, text stays primary for contrast) */
.status-callout {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  margin-top: var(--space-2);
  background: var(--status-tint, var(--surface-tint));
  text-align: left;
}
.status-callout-label {
  color: var(--status-ink, var(--deep-sea));
  font-size: var(--text-caption);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-wide);
}
.status-callout-text {
  margin: 0;
  font-size: var(--text-body);
  font-weight: var(--font-weight-medium);
}

/* Details: hairline between rows; label above value on phones, label left and value right from
   640px. Long ids wrap instead of overflowing. */
.details {
  display: flex;
  flex-direction: column;
  width: 100%;
  margin: 0;
  border-top: var(--border-width) solid var(--border-subtle);
  text-align: left;
}
.details > div {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) 0;
  border-bottom: var(--border-width) solid var(--border-subtle);
}
.details > div:last-child { border-bottom: 0; }
.details dt { color: var(--text-secondary); }
.details dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-medium);
  overflow-wrap: anywhere;
}

/* Action: full width on phones, content width from 640px, centred */
.status-actions {
  display: flex;
  justify-content: center;
  width: 100%;
}
.status-actions .button { width: 100%; }
.status .status-actions { margin-top: var(--space-2); }

/* Receipt: the order lines in a flush panel with a padded heading and a prominent total row */
/* A very wide table scrolls inside its panel instead of being clipped by the flush panel */
.receipt { overflow-x: auto; }
.receipt h2 { padding: var(--space-4) var(--space-4) var(--space-2); }
.receipt td.num { white-space: nowrap; }
.receipt tfoot th,
.receipt tfoot td {
  padding-top: var(--space-4);
  padding-bottom: var(--space-4);
  font-size: var(--text-body);
}
.receipt tfoot td {
  font-size: var(--text-heading-3);
  font-weight: var(--font-weight-bold);
}

@media (min-width: 640px) {
  .status { padding: var(--space-10) var(--space-8) var(--space-8); }
  .status h1 { font-size: var(--text-heading-1); }
  .details > div {
    flex-flow: row wrap;
    justify-content: space-between;
    gap: var(--space-1) var(--space-4);
  }
  .status-actions .button { width: auto; }
  .receipt h2 { padding: var(--space-5) var(--space-4) var(--space-2); }
}

/* 15. Fake payment page: the gateway simulation. One narrow white panel, left aligned: a warning
   badge (Testläge is a status), the h1 and a line of text, the order details with the amount as
   the biggest figure (the .details list from section 14), the one primary action, then the other
   outcomes under a hairline: the failure group (reason and button, boxed so they read as one
   action) and a quiet ghost button. No tints, so the view stays white on Ice. */
.payment {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  width: 100%;
  max-width: 32rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}
.payment-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
}
.payment-head h1 {
  font-size: var(--text-heading-2);
  text-wrap: balance;
}
.payment-lead {
  color: var(--text-secondary);
  font-size: var(--text-body);
  text-wrap: pretty;
}
.payment .payment-amount {
  font-size: var(--text-heading-1);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  white-space: nowrap;
}

.payment-other {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-top: var(--space-6);
  border-top: var(--border-width) solid var(--border-subtle);
}

/* Failure group: label above the select, the button under it on phones and beside it from 640px,
   aligned to the bottom edge of the select */
.payment-fail {
  align-items: stretch;
  gap: var(--space-3);
  padding: var(--space-4);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.payment-fail .field {
  flex: 1 1 100%;
  min-width: 0;
}
.payment-fail .button { flex: 1 1 100%; }

@media (min-width: 640px) {
  .payment { padding: var(--space-8); }
  .payment-head h1 { font-size: var(--text-heading-1); }
  .payment .details > div { align-items: baseline; }
  .payment-fail { align-items: flex-end; }
  .payment-fail .field { flex: 1 1 0; }
  .payment-fail .button { flex: none; }
}

/* 16. Reduced motion: every transition above runs on the duration tokens, so setting them to zero
   turns them all into instant changes */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-instant: 0ms;
    --duration-fast: 0ms;
    --duration-base: 0ms;
    --duration-slow: 0ms;
    --duration-reveal: 0ms;
  }
}
