/*
  Winspace storefront — art direction.

  The brief was Nordic and modern, but the first pass read as timid: grey placeholder boxes,
  cautious type, no brand anywhere. This is the corrective.

  Three decisions drive everything below.

  1. Winspace shoot on seamless white. The first attempt kept that white as a plate under each
     product, which is how the hero ended up as a giant white box. The backgrounds are now cut
     out to transparency instead, so a frameset sits directly on the black with nothing behind
     it. Grid tiles use a mid grey rather than white or black, because the range runs from a
     pearl-white frameset to a matt-black cockpit and either extreme swallows one of them.

  2. Drama comes from contrast between bands, not from decoration. Full-bleed near-black
     sections butt directly against white ones. No shadows, no gradients, no rounded cards.

  3. Type carries the brand. The wordmark is an oblique grotesk, so the interface uses Barlow
     — squarish, technical, a little European-motorsport — at a much larger scale than before,
     with tight tracking on display sizes and generous air around it.
*/

:root {
  --ink: #0B0C0E;
  --ink-2: #34383D;
  --ink-3: #6E747B;
  --ink-4: #9DA3AA;

  --paper: #FFFFFF;
  --canvas: #F3F3F1;
  --canvas-2: #E9E9E6;
  --line: #DEDEDA;
  --line-2: #C6C6C1;
  --tile: #E8E7E3;
  --tile-hover: #DEDDD8;

  --night: #0B0C0E;
  --night-2: #16181B;
  --night-line: #2A2D31;

  --signal: #C8102E;
  --positive: #17714B;

  --font: "Barlow", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --font-condensed: "Barlow Semi Condensed", var(--font);

  /* A wide, deliberate type scale — the previous one topped out too low to carry a hero. */
  --t-micro: 0.6875rem;
  --t-small: 0.8125rem;
  --t-body: clamp(0.95rem, 0.92rem + 0.16vw, 1.0625rem);
  --t-lead: clamp(1.125rem, 1.02rem + 0.5vw, 1.5rem);
  --t-h3: clamp(1.25rem, 1.1rem + 0.7vw, 1.75rem);
  --t-h2: clamp(1.9rem, 1.5rem + 1.9vw, 3.25rem);
  --t-h1: clamp(2.6rem, 1.8rem + 3.6vw, 5.5rem);
  --t-mega: clamp(3.4rem, 1.9rem + 6.6vw, 9rem);

  --gutter: clamp(1.25rem, 0.85rem + 1.9vw, 3.25rem);
  --shell: 1560px;
  --measure: 62ch;

  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: 1.55;
  font-feature-settings: "kern", "liga", "tnum";
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 0.98; letter-spacing: -0.025em; }
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); line-height: 1.1; }

p { margin: 0 0 1em; max-width: var(--measure); }

a { color: inherit; text-decoration: none; }

img, svg { display: block; max-width: 100%; }

:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }

/* Blazor's FocusOnNavigate moves focus to the <h1> after every navigation so a screen reader
   announces the new page. That heading is not interactive — it only carries tabindex="-1" to
   be focusable at all — so a visible ring around it is noise, and it was drawing a red box
   around the hero headline. Interactive elements keep their focus indicator. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible { outline: none; }

::selection { background: var(--ink); color: var(--paper); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- primitives */

.shell { width: min(100% - (var(--gutter) * 2), var(--shell)); margin-inline: auto; }

.band { padding-block: clamp(3rem, 2rem + 3vw, 5.5rem); }
.band--tight { padding-block: clamp(2rem, 1.5rem + 1.6vw, 3rem); }
.band--night { background: var(--night); color: #F2F2F0; }
.band--canvas { background: var(--canvas); }

.band--night a { color: inherit; }

/* An eyebrow is a small, tracked, uppercase label. Used everywhere a section starts, which
   is what gives the page its rhythm without needing rules or boxes. */
.eyebrow {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 1.25rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.band--night .eyebrow { color: var(--ink-4); }
.band--night .eyebrow::after { background: var(--night-line); }

.lead { font-size: var(--t-lead); color: var(--ink-2); line-height: 1.45; }
.band--night .lead { color: #B9BDC2; }

.rule { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* ---------------------------------------------------------------- masthead */

.masthead {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--paper) 90%, transparent);
  backdrop-filter: saturate(1.6) blur(16px);
  border-bottom: 1px solid var(--line);
}

.masthead__inner {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2.75rem);
  min-height: 74px;
}

/* The supplied vectors are painted as CSS masks rather than <img>, so a single file serves
   every context and takes its colour from whatever it sits on — ink on the white masthead,
   bone on the dark footer — with no second asset and no inline SVG in the markup.
   The aspect ratios come from the artwork's own viewBox. */
.wordmark {
  display: block;
  height: 26px;
  aspect-ratio: 667.5 / 136.9;
  background: currentColor;
  -webkit-mask: url("/brand/winspace-wordmark.svg") no-repeat center / contain;
  mask: url("/brand/winspace-wordmark.svg") no-repeat center / contain;
  color: var(--ink);
}

/* The alternate uppercase logotype. Swap the class to try it. */
.wordmark--uppercase {
  aspect-ratio: 667.7 / 69.4;
  -webkit-mask-image: url("/brand/winspace-wordmark-uppercase.svg");
  mask-image: url("/brand/winspace-wordmark-uppercase.svg");
}

.shield {
  display: block;
  height: 34px;
  aspect-ratio: 104 / 125.6;
  background: currentColor;
  -webkit-mask: url("/brand/winspace-shield.svg") no-repeat center / contain;
  mask: url("/brand/winspace-shield.svg") no-repeat center / contain;
}

.mainnav {
  display: flex;
  align-items: center;
  gap: clamp(0.85rem, 1.8vw, 2rem);
  margin-inline-end: auto;
  flex-wrap: wrap;
}

.mainnav a {
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding-block: 0.4rem;
  position: relative;
  transition: color 0.18s var(--ease);
}

.mainnav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.24s var(--ease);
}

.mainnav a:hover { color: var(--ink); }
.mainnav a:hover::after { transform: scaleX(1); }

.masthead__actions { display: flex; align-items: center; gap: 1rem; }

/* The native control was rendering with default browser chrome — a grey bevelled box that
   looked pasted on. Stripped back to a flat field with our own chevron. */
.market-switch select {
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  background-color: transparent;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%),
                    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: right 0.85rem center, right 0.55rem center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  border: 1px solid var(--line-2);
  border-radius: 0;
  padding: 0.5rem 2rem 0.5rem 0.7rem;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color 0.16s var(--ease);
}

.market-switch select:hover { border-color: var(--ink); }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 1.05rem 2rem;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}

.btn:hover { background: transparent; color: var(--ink); }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-2); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* On a dark band the default button would paint near-black on near-black and vanish, and the
   ghost button's near-black label would disappear entirely. The hero is dark too, so it has
   to be in this selector list — leaving it out is exactly how both hero buttons ended up
   invisible. */
.band--night .btn,
.hero .btn { background: #F2F2F0; color: var(--night); border-color: #F2F2F0; }

.band--night .btn:hover,
.hero .btn:hover { background: transparent; color: #F2F2F0; }

.band--night .btn--ghost,
.hero .btn--ghost { background: transparent; color: #F2F2F0; border-color: #4A4E54; }

.band--night .btn--ghost:hover,
.hero .btn--ghost:hover { background: #F2F2F0; color: var(--night); border-color: #F2F2F0; }

.btn--block { width: 100%; }
.btn[disabled] { opacity: 0.35; pointer-events: none; }

/* ---------------------------------------------------------------- hero */

/* Full-bleed photograph with the copy sitting on it, the way Factor, Canyon and Cervélo all
   open. The earlier version put text in one column and a product in the other, which left the
   page opening on a large area of nothing. An image edge to edge is what carries the weight. */
.hero {
  position: relative;
  min-height: min(88vh, 900px);
  display: grid;
  align-items: end;
  background: var(--night);
  color: #F2F2F0;
  overflow: hidden;
  isolation: isolate;
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 55%;
}

/* Two scrims: one up from the bottom to seat the headline, one in from the left so the copy
   never fights the photograph. Without these the text sits on whatever happens to be behind. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, rgba(6, 7, 8, 0.92) 0%, rgba(6, 7, 8, 0.55) 38%, rgba(6, 7, 8, 0.12) 70%),
    linear-gradient(to right, rgba(6, 7, 8, 0.78) 0%, rgba(6, 7, 8, 0.25) 45%, transparent 75%);
}

.hero__inner {
  position: relative;
  padding-block: clamp(3rem, 2rem + 5vh, 5.5rem);
}

.hero h1 {
  font-size: var(--t-mega);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 0.9;
  margin-bottom: 1.75rem;
  text-wrap: balance;
}

/* The oblique of the wordmark, echoed once. Used on a single word so it reads as emphasis
   rather than as a gimmick applied to everything. */
.hero h1 em {
  font-style: italic;
  font-weight: 600;
}

.hero .lead { max-width: 44ch; margin-bottom: 2.5rem; }

.hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

.hero__copy { max-width: 58ch; }

.hero__meta {
  display: flex;
  gap: 2.5rem;
  margin-top: 2.25rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  flex-wrap: wrap;
}

.hero__stat { display: flex; flex-direction: column; gap: 0.2rem; }

.hero__stat dt {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.hero__stat dd {
  margin: 0;
  font-size: var(--t-h3);
  font-weight: 600;
  letter-spacing: -0.02em;
}

/* ---------------------------------------------------------------- section heads */

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-bottom: clamp(2rem, 1.2rem + 2.4vw, 3.5rem);
}

.section-head h2 { text-wrap: balance; }

.section-head__link {
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 0.2rem;
  transition: border-color 0.2s var(--ease);
}

.section-head__link:hover { border-color: var(--ink); }

/* ---------------------------------------------------------------- product grid */

.grid {
  display: grid;
  gap: clamp(2rem, 1.2rem + 2.6vw, 3.5rem) clamp(1rem, 0.6rem + 1.6vw, 2rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
}

.card { display: flex; flex-direction: column; height: 100%; }

/* A mid-tone tile, not white and not black. The range runs from a pearl-white frameset to a
   matt-black cockpit, and either extreme of tile would swallow one of them. */
.card__media {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--tile);
  overflow: hidden;
  display: grid;
  place-items: center;
  margin-bottom: 1.25rem;
  transition: background 0.3s var(--ease);
}

.card:hover .card__media { background: var(--tile-hover); }

/* The backgrounds are cut out, so no blend mode is needed — and multiply here would darken
   the product against the tile instead of leaving it clean. */
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 7%;
  transition: transform 0.6s var(--ease);
}

.card:hover .card__media img { transform: scale(1.04); }

.card__placeholder {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.card__flag {
  position: absolute;
  top: 0.85rem;
  left: 0.85rem;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: var(--ink);
  color: var(--paper);
  padding: 0.3rem 0.55rem;
}

.card__brand {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.45rem;
}

.card__name {
  font-size: var(--t-h3);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.08;
  margin-bottom: 0.45rem;
}

.card__desc {
  font-size: var(--t-small);
  color: var(--ink-3);
  margin: 0 0 1rem;
  max-width: 34ch;
}

.card__price {
  margin-top: auto;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
  font-size: var(--t-body);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}

.card__price .from {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---------------------------------------------------------------- category tiles */

/* Category tiles carry a complete bike, not a name in an empty box. The previous version was
   a label and a count floating in 250px of white, which is what made the page read as
   unfinished — minimal is not the same as empty. */
.tiles {
  display: grid;
  gap: 2px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}

.tile {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--night-2);
  color: #F2F2F0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(1.25rem, 1rem + 1vw, 2rem);
  isolation: isolate;
}

.tile__img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Tight sides so the machine fills the tile; the bottom inset is only what the label needs. */
  padding: 6% 3% 20%;
  transition: transform 0.7s var(--ease);
}

.tile::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, rgba(8, 9, 11, 0.92) 8%, rgba(8, 9, 11, 0.2) 42%, transparent 65%);
}

.tile:hover .tile__img { transform: scale(1.05); }

.tile__name {
  font-size: var(--t-h2);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
}

/* A line of substance rather than a product count: what is actually in the category. */
.tile__desc {
  margin-top: 0.5rem;
  font-size: var(--t-small);
  color: #B7BCC2;
  max-width: 30ch;
}

/* ---------------------------------------------------------------- feature band */

/* A full-bleed photograph with copy on it, used once mid-page to break the rhythm of grids.
   Same construction as the hero but shorter and right-aligned, so the two do not read as
   the same slab twice. */
.feature {
  position: relative;
  min-height: min(62vh, 620px);
  display: grid;
  align-items: center;
  background: var(--night);
  color: #F2F2F0;
  overflow: hidden;
  isolation: isolate;
}

.feature__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.feature::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to left, rgba(6, 7, 8, 0.9) 0%, rgba(6, 7, 8, 0.55) 40%, transparent 78%);
}

.feature__inner {
  position: relative;
  display: flex;
  justify-content: flex-end;
  padding-block: clamp(3rem, 2rem + 4vw, 5rem);
}

.feature__copy { max-width: 46ch; }
.feature__copy h2 { margin-bottom: 1rem; }
.feature__copy .lead { margin-bottom: 2rem; }

.feature .eyebrow { color: var(--ink-4); }
.feature .eyebrow::after { background: rgba(255, 255, 255, 0.2); }
.feature .lead { color: #C2C6CB; }

.feature .btn { background: #F2F2F0; color: var(--night); border-color: #F2F2F0; }
.feature .btn:hover { background: transparent; color: #F2F2F0; }

/* ---------------------------------------------------------------- product page */

.product {
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 4.5rem);
  grid-template-columns: 1fr;
  align-items: start;
}

@media (min-width: 960px) {
  .product { grid-template-columns: minmax(0, 1.25fr) minmax(360px, 0.75fr); }
  .product__buy { position: sticky; top: 106px; }
}

.gallery { display: grid; gap: 0.5rem; }

.gallery__main {
  aspect-ratio: 1 / 1;
  background: var(--tile);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.gallery__main img { width: 100%; height: 100%; object-fit: contain; padding: 5%; }

.gallery__strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; }

.gallery__thumb {
  aspect-ratio: 1 / 1;
  background: var(--tile);
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 0;
}

.gallery__thumb img { width: 100%; height: 100%; object-fit: contain; padding: 10%; }
.gallery__thumb[aria-pressed="true"] { border-color: var(--ink); }

.product__brand {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.9rem;
}

.product__title { font-size: var(--t-h2); margin-bottom: 1rem; text-wrap: balance; }

.product__sku {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.5rem;
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
}

.product__price {
  font-size: var(--t-h2);
  font-weight: 600;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin-bottom: 0.5rem;
}

.product__vatnote { font-size: var(--t-small); color: var(--ink-3); margin-bottom: 2.5rem; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--line-2);
  color: var(--ink-3);
}

.badge--stock { color: var(--positive); border-color: color-mix(in srgb, var(--positive) 35%, transparent); }
.badge--lead { color: var(--signal); border-color: color-mix(in srgb, var(--signal) 30%, transparent); }

/* ---------------------------------------------------------------- options */

.option { margin-bottom: 2rem; }

.option__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 0.75rem;
}

.option__label {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.option__value { font-size: var(--t-small); font-weight: 500; }

.choices { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.choice {
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: 0.06em;
  min-width: 3.5rem;
  padding: 0.7rem 1rem;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line-2);
  cursor: pointer;
  transition: border-color 0.16s var(--ease), background 0.16s var(--ease), color 0.16s var(--ease);
}

.choice:hover { border-color: var(--ink); }
.choice[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* An unavailable combination stays visible and struck through rather than disappearing, so
   the customer can see the option exists and what it would take to get it. */
.choice--unavailable { opacity: 0.3; text-decoration: line-through; cursor: not-allowed; }

select.choice { width: 100%; min-width: 0; }

.swatches { display: flex; flex-wrap: wrap; gap: 0.55rem; }

.swatch {
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border: 1px solid var(--line-2);
  cursor: pointer;
  transition: transform 0.16s var(--ease), box-shadow 0.16s var(--ease);
}

.swatch:hover { transform: translateY(-2px); }
.swatch[aria-pressed="true"] { box-shadow: 0 0 0 1px var(--paper) inset, 0 0 0 2px var(--ink); }
.swatch--unavailable { opacity: 0.25; cursor: not-allowed; }

/* ---------------------------------------------------------------- specs + prose */

.specs { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.specs th, .specs td { text-align: left; padding: 0.85rem 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.specs th { font-weight: 500; color: var(--ink-3); width: 42%; }

.prose { max-width: var(--measure); }
.prose h2 { margin: 3rem 0 1rem; }
.prose h3 { margin: 2rem 0 0.6rem; }
.prose ul { padding-left: 1.15rem; }
.prose li { margin-bottom: 0.45rem; }

.notice {
  border-left: 2px solid var(--ink);
  background: var(--canvas);
  padding: 1.25rem 1.5rem;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.notice p:last-child { margin-bottom: 0; }
.notice strong { color: var(--ink); }

/* ---------------------------------------------------------------- rail + crumbs */

.rail { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 2.5rem; }

.rail a {
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.55rem 1rem;
  border: 1px solid var(--line);
  color: var(--ink-2);
  transition: border-color 0.16s var(--ease), color 0.16s var(--ease);
}

.rail a:hover { border-color: var(--ink); color: var(--ink); }
.rail a.is-active { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.breadcrumb {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.5rem;
}

.breadcrumb a:hover { color: var(--ink); }

/* ---------------------------------------------------------------- assembly strip */

.assembly {
  display: grid;
  gap: clamp(1.5rem, 1rem + 3vw, 4rem);
  align-items: center;
}

@media (min-width: 860px) { .assembly { grid-template-columns: 1.1fr 1fr; } }

.steps { display: grid; gap: 1px; background: var(--night-line); }

.step { background: var(--night); padding: 1.5rem 0 1.5rem 0; display: flex; gap: 1.25rem; }

.step__n {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--ink-4);
  padding-top: 0.35rem;
  min-width: 2.5rem;
}

.step h3 { font-size: var(--t-body); font-weight: 600; margin-bottom: 0.25rem; }
.step p { font-size: var(--t-small); color: #A9AEB4; margin: 0; }

/* ---------------------------------------------------------------- footer */

.footer { background: var(--night); color: #C9CDD2; padding-block: clamp(3rem, 2rem + 3.5vw, 5.5rem); }

.footer__top {
  display: grid;
  gap: 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  padding-bottom: 3rem;
  border-bottom: 1px solid var(--night-line);
}

.footer__brand { grid-column: 1 / -1; }
@media (min-width: 900px) { .footer__brand { grid-column: span 2; } }

.footer__brand .wordmark { color: #F2F2F0; margin-bottom: 1.25rem; height: 30px; }
.footer__brand p { font-size: var(--t-small); color: var(--ink-4); max-width: 34ch; }

.footer h4 {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #F2F2F0;
  margin-bottom: 1rem;
}

.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: 0.6rem; }
.footer li a { font-size: var(--t-small); color: var(--ink-4); transition: color 0.16s var(--ease); }
.footer li a:hover { color: #F2F2F0; }

.colophon {
  padding-top: 1.75rem;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.colophon__shield { height: 26px; width: auto; color: var(--ink-4); opacity: 0.7; }

/* ---------------------------------------------------------------- misc */

#blazor-error-ui {
  display: none;
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 1000;
  padding: 0.9rem 1.25rem;
  background: var(--signal);
  color: #fff;
  font-size: var(--t-small);
}

#blazor-error-ui .dismiss { cursor: pointer; float: right; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ================================================================ admin + auth

   The admin is a different product from the storefront: dense, functional, read at a desk.
   It shares the tokens and the typeface but not the editorial spacing — a table of variants
   wants rows you can scan, not air.
*/

.auth-shell {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  background: var(--night);
  padding: var(--gutter);
}

.auth__card {
  width: min(100%, 400px);
  background: var(--paper);
  padding: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
}

.auth__mark { height: 22px; margin-bottom: 2rem; color: var(--ink); }
.auth__title { font-size: var(--t-h2); margin-bottom: 0.4rem; }
.auth__sub { font-size: var(--t-small); color: var(--ink-3); margin-bottom: 1.75rem; }

.auth__error {
  border-left: 2px solid var(--signal);
  background: color-mix(in srgb, var(--signal) 7%, transparent);
  color: var(--ink);
  padding: 0.75rem 1rem;
  font-size: var(--t-small);
  margin-bottom: 1.25rem;
}

.auth__foot { margin: 1.5rem 0 0; font-size: var(--t-small); color: var(--ink-3); }
.auth__foot a { border-bottom: 1px solid var(--line-2); }

.field { display: block; margin-bottom: 1.1rem; }

.field__label {
  display: block;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.4rem;
}

.field__input {
  width: 100%;
  font: inherit;
  font-size: var(--t-body);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: 0;
  padding: 0.7rem 0.85rem;
  transition: border-color 0.16s var(--ease);
}

.field__input:focus { border-color: var(--ink); }

.field--check {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: var(--t-small);
  color: var(--ink-2);
  margin-bottom: 1.5rem;
}

.validation-message { display: block; margin-top: 0.35rem; font-size: var(--t-small); color: var(--signal); }

/* ---------------------------------------------------------------- admin shell */

.admin { display: grid; grid-template-columns: 1fr; min-height: 100dvh; }

@media (min-width: 900px) {
  .admin { grid-template-columns: 248px minmax(0, 1fr); }
  .admin__side { position: sticky; top: 0; height: 100dvh; }
}

.admin__side {
  background: var(--night);
  color: #C9CDD2;
  padding: 1.5rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}

.admin__brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  color: #F2F2F0;
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.admin__shield { height: 26px; color: #F2F2F0; }

.admin__nav { display: flex; flex-direction: column; gap: 0.1rem; }

.admin__group {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #6B7178;
  margin: 1.25rem 0 0.4rem;
}

.admin__nav a {
  font-size: var(--t-small);
  color: #C9CDD2;
  padding: 0.5rem 0.7rem;
  border-left: 2px solid transparent;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}

.admin__nav a:hover { color: #F2F2F0; background: rgba(255, 255, 255, 0.05); }

.admin__nav a.active {
  color: #F2F2F0;
  background: rgba(255, 255, 255, 0.07);
  border-left-color: #F2F2F0;
}

.admin__user { margin-top: auto; display: flex; flex-direction: column; gap: 0.6rem; }
.admin__who { font-size: var(--t-small); color: #8B9096; }

.admin__signout {
  font: inherit;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: transparent;
  color: #C9CDD2;
  border: 1px solid #33383E;
  padding: 0.5rem 0.8rem;
  cursor: pointer;
  width: 100%;
}

.admin__signout:hover { background: #F2F2F0; color: var(--night); border-color: #F2F2F0; }
.admin__shoplink { font-size: var(--t-small); color: #8B9096; }
.admin__shoplink:hover { color: #F2F2F0; }

.admin__main { padding: clamp(1.5rem, 1rem + 2vw, 3rem); background: var(--canvas); }

.admin__head { margin-bottom: 2rem; }
.admin__head h1 { font-size: var(--t-h2); }
.admin__lede { color: var(--ink-3); font-size: var(--t-small); margin: 0.5rem 0 0; max-width: 70ch; }

.admin__crumb {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.6rem;
}

.admin__crumb a:hover { color: var(--ink); }

.admin__section { margin-top: 2.5rem; }
.admin__section h2 { font-size: var(--t-h3); margin-bottom: 1rem; }
.admin__empty { color: var(--ink-3); }
.admin__list { padding-left: 1.15rem; color: var(--ink-2); font-size: var(--t-small); }
.admin__list li { margin-bottom: 0.4rem; }

.admin__ok {
  border-left: 2px solid var(--positive);
  background: color-mix(in srgb, var(--positive) 8%, transparent);
  padding: 0.7rem 1rem;
  font-size: var(--t-small);
  margin-bottom: 1.5rem;
}

.admin__filters { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; }
.admin__filters .field__input { width: min(100%, 340px); }
.admin__clear { font-size: var(--t-small); color: var(--ink-3); }

.admin__form {
  display: grid;
  gap: 0 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  background: var(--paper);
  padding: 1.5rem;
  margin-bottom: 1.25rem;
}

/* ---------------------------------------------------------------- stats + tables */

.stats {
  display: grid;
  gap: 1px;
  background: var(--line);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr));
}

.stat { background: var(--paper); padding: 1.25rem 1.4rem; display: flex; flex-direction: column; gap: 0.3rem; }

.stat__n { font-size: var(--t-h2); font-weight: 600; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }

.stat__l {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.grid-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--paper);
  font-size: var(--t-small);
}

.grid-table th, .grid-table td { text-align: left; padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--line); }

.grid-table th {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: var(--canvas-2);
  white-space: nowrap;
}

.grid-table tbody tr:hover { background: var(--canvas); }
.grid-table a { border-bottom: 1px solid var(--line-2); }
.grid-table a:hover { border-color: var(--ink); }

.num { text-align: right; font-variant-numeric: tabular-nums; }
.num--zero { color: var(--signal); }
.mono { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }

.pill {
  display: inline-block;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
  border: 1px solid var(--line-2);
  color: var(--ink-3);
}

.pill--active { color: var(--positive); border-color: color-mix(in srgb, var(--positive) 40%, transparent); }
.pill--draft { color: var(--warning, #8A5A22); }
.pill--archived, .pill--discontinued { opacity: 0.6; }

/* ================================================================ cart + checkout */

.cartlink {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-condensed);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--line-2);
  padding: 0.5rem 0.85rem;
  transition: border-color 0.16s var(--ease);
  white-space: nowrap;
}

.cartlink:hover { border-color: var(--ink); }

.cartlink__n {
  display: inline-grid;
  place-items: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.3rem;
  background: var(--ink);
  color: var(--paper);
  font-size: var(--t-micro);
  font-variant-numeric: tabular-nums;
}

.added {
  margin-top: 1rem;
  border-left: 2px solid var(--positive);
  background: color-mix(in srgb, var(--positive) 8%, transparent);
  padding: 0.7rem 1rem;
  font-size: var(--t-small);
}

.added a { border-bottom: 1px solid var(--line-2); }

/* The basket and the checkout share a two-column shape: the goods on the left, a summary that
   sticks on the right. Same furniture in both places, so the second step never feels like a
   different site. */
.basket, .checkout {
  display: grid;
  gap: clamp(1.5rem, 1rem + 2.5vw, 3.5rem);
  align-items: start;
}

@media (min-width: 900px) {
  .basket, .checkout { grid-template-columns: minmax(0, 1fr) minmax(320px, 380px); }
  .summary { position: sticky; top: 100px; }
}

.line {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) auto;
  gap: 1rem;
  align-items: center;
  padding: 1.25rem 0;
  border-top: 1px solid var(--line);
}

.basket__lines .line:last-child { border-bottom: 1px solid var(--line); }

@media (min-width: 620px) {
  .line { grid-template-columns: 96px minmax(0, 1fr) auto auto; }
}

.line__media {
  aspect-ratio: 1 / 1;
  background: var(--tile);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.line__media img { width: 100%; height: 100%; object-fit: contain; padding: 8%; }

.line__name { font-weight: 600; display: block; }
.line__variant { font-size: var(--t-small); color: var(--ink-3); margin: 0.2rem 0 0; }
.line__sku {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.1em;
  color: var(--ink-4);
  margin: 0.25rem 0 0;
}

.line__warn { font-size: var(--t-small); color: var(--signal); margin: 0.4rem 0 0; }

.line__qty { display: flex; align-items: center; gap: 0.15rem; }

.qty__btn {
  font: inherit;
  font-size: 1rem;
  width: 2.1rem;
  height: 2.1rem;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.15s var(--ease);
}

.qty__btn:hover { border-color: var(--ink); }

.qty__n {
  min-width: 2.2rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.line__money { display: flex; flex-direction: column; align-items: flex-end; gap: 0.15rem; }
.line__total { font-weight: 600; font-variant-numeric: tabular-nums; }
.line__unit { font-size: var(--t-micro); color: var(--ink-3); }

.line__remove {
  font: inherit;
  font-size: var(--t-micro);
  font-family: var(--font-condensed);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  background: none;
  border: 0;
  padding: 0.3rem 0 0;
  color: var(--ink-3);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.line__remove:hover { color: var(--signal); }

/* ---------------------------------------------------------------- summary */

.summary { background: var(--canvas); padding: clamp(1.25rem, 1rem + 1vw, 1.75rem); }

.summary__title {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 1rem;
}

.summary__title + .summary__title { margin-top: 1.75rem; }

.summary__lines { list-style: none; margin: 0 0 1.25rem; padding: 0; font-size: var(--t-small); }

.summary__lines li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.35rem 0;
  color: var(--ink-2);
}

.summary__rows { margin: 0 0 1.5rem; font-size: var(--t-small); }

.summary__rows > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.45rem 0;
}

.summary__rows dt { color: var(--ink-3); }
.summary__rows dd { margin: 0; font-variant-numeric: tabular-nums; }

.summary__total {
  border-top: 1px solid var(--line-2);
  margin-top: 0.4rem;
  padding-top: 0.8rem !important;
  font-size: var(--t-body);
  font-weight: 600;
}

.summary__total dt { color: var(--ink) !important; }

.summary__note { font-size: var(--t-micro); color: var(--ink-3); margin: 1rem 0 0; line-height: 1.5; }
.summary__back { display: inline-block; margin-top: 1rem; font-size: var(--t-small); color: var(--ink-3); }
.summary__back:hover { color: var(--ink); }

/* ---------------------------------------------------------------- checkout form */

.checkout__block { border: 0; padding: 0; margin: 0 0 2.25rem; }
.checkout__block legend { padding: 0; margin-bottom: 1rem; }

.checkout__row { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); }

.choice-row { display: block; margin-bottom: 1.25rem; }
.choice-row__item { display: flex; gap: 0.75rem; align-items: flex-start; padding: 0.9rem 0; border-top: 1px solid var(--line); }
.choice-row__item strong { display: block; font-weight: 600; }
.choice-row__item small { display: block; font-size: var(--t-small); color: var(--ink-3); margin-top: 0.15rem; }
.choice-row__item--disabled { opacity: 0.45; }

.admin__code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--t-micro);
  background: var(--ink);
  color: #E8E8E4;
  padding: 0.9rem 1rem;
  overflow-x: auto;
  margin: 0.75rem 0;
  line-height: 1.7;
}

/* ================================================================ configurator */

.hero--build { min-height: min(46vh, 420px); }

.build__help { font-size: var(--t-small); color: var(--ink-3); margin: 0 0 0.9rem; }

.build__models { display: grid; gap: 0.4rem; margin-bottom: 1.1rem; }

/* Models are rows rather than a dropdown: someone choosing a frameset is comparing price,
   delivery and whether the thing even fits, and a <select> shows none of that. Colour and
   size are not here — they are chosen below, on the model that was picked. */
.build__model {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  gap: 0.9rem;
  align-items: center;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 0.7rem 0.9rem;
  background: transparent;
  border: 1px solid var(--line);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.build__model:hover { border-color: var(--ink-3); }
.build__model.is-selected { border-color: var(--ink); background: var(--canvas); }

/* Incompatible models stay visible and explain themselves. Hiding them leaves the customer
   wondering why the frame they wanted vanished. */
.build__model.is-blocked { opacity: 0.5; cursor: not-allowed; }
.build__model.is-blocked .build__model-name { text-decoration: line-through; }

.build__model-media {
  aspect-ratio: 1 / 1;
  background: var(--tile);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.build__model-media img { width: 100%; height: 100%; object-fit: contain; padding: 8%; }

.build__model-body { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.build__model-name { font-weight: 600; font-size: var(--t-small); }
.build__model-note { font-size: var(--t-micro); color: var(--ink-4); }
.build__model.is-blocked .build__model-note { color: var(--signal); }

.build__model-price {
  font-variant-numeric: tabular-nums;
  font-size: var(--t-small);
  font-weight: 600;
  white-space: nowrap;
}

/* ---- colour and size, for the model that is selected ---- */

.build__choice { margin-bottom: 1rem; }

.build__choice-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 0.45rem;
}

.build__choice-label {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.build__choice-value { font-size: var(--t-small); font-weight: 600; }

.build__swatches { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.build__swatch {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font: inherit;
  font-size: var(--t-small);
  padding: 0.45rem 0.8rem;
  background: transparent;
  border: 1px solid var(--line);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.build__swatch:hover { border-color: var(--ink-3); }
.build__swatch.is-selected { border-color: var(--ink); background: var(--canvas); font-weight: 600; }

/* A combination that is not made stays on the page, struck through: a shopper can see the
   colour exists and that it is their size that rules it out. */
.build__swatch.is-blocked { opacity: 0.45; cursor: not-allowed; text-decoration: line-through; }

.build__swatch-dot {
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  flex: none;
}

.build__swatch-diff { font-size: var(--t-micro); color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* Colour rows read better with the swatch doing the work and the name kept quiet. */
.build__swatches--colour .build__swatch { padding-left: 0.5rem; }

/* ---------------------------------------------------------------- build in the basket */

.buildline { border-top: 1px solid var(--line); padding: 1.25rem 0; }
.basket__lines .buildline:last-of-type { border-bottom: 1px solid var(--line); }

.buildline__head { display: flex; justify-content: space-between; gap: 1rem; align-items: flex-start; }
.buildline__name { display: block; font-weight: 600; font-size: var(--t-h3); letter-spacing: -0.02em; }
.buildline__promise { display: block; font-size: var(--t-small); color: var(--ink-3); margin-top: 0.2rem; }

.buildline__money { text-align: right; display: flex; flex-direction: column; gap: 0.1rem; }
.buildline__was { font-size: var(--t-small); color: var(--ink-4); text-decoration: line-through; }
.buildline__saved { font-size: var(--t-micro); color: var(--positive); }

.buildline__parts { list-style: none; margin: 1rem 0 0; padding: 0 0 0 1rem; border-left: 2px solid var(--line); }

.buildline__parts li {
  display: grid;
  grid-template-columns: 90px minmax(0, 1fr) auto;
  gap: 0.75rem;
  padding: 0.3rem 0;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.buildline__parts em { color: var(--ink-3); font-style: normal; }

.buildline__slot {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.12em;
  color: var(--ink-4);
}

.buildline__partprice { font-variant-numeric: tabular-nums; color: var(--ink-3); }
.buildline__actions { margin-top: 0.75rem; }
.line__promise { font-size: var(--t-small); color: var(--ink-3); margin: 0.4rem 0 0; }

/* ================================================================ partner network */

.partner-grid {
  display: grid;
  gap: 1px;
  background: var(--line);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  margin: 2rem 0 3rem;
}

.partner-card {
  background: var(--paper);
  padding: 1.6rem 1.5rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.partner-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }

.partner-card__name { font-size: var(--t-h4, 1.1rem); letter-spacing: -0.01em; margin: 0; }
.partner-card__name a { border-bottom: 1px solid transparent; }
.partner-card__name a:hover { border-color: var(--ink); }

.partner-card__distance {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

.partner-card__address { color: var(--ink-2); font-size: var(--t-small); margin: 0; }
.partner-card__hours { color: var(--ink-3); font-size: var(--t-small); margin: 0; }

.partner-card__services { list-style: none; display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0; padding: 0; }

.partner-card__link { margin-top: auto; font-size: var(--t-small); }

.partner-detail__address { font-style: normal; color: var(--ink-2); margin-bottom: 1.2rem; }

.admin__filters-clear { font-size: var(--t-small); color: var(--ink-3); }

.field--inline { margin-bottom: 0; }

.checkbox { display: inline-flex; align-items: center; gap: 0.45rem; font-size: var(--t-small); }

.field__hint { display: block; margin-top: 0.35rem; font-size: var(--t-small); color: var(--ink-3); }

/* ---------------------------------------------------------------- partner portal */

/* The portal reuses the admin chrome; only the accent changes, so a partner is never in
   any doubt about which of the two places they are looking at. */
.admin--partner .admin__brand { color: var(--ink); }

.admin__split { display: grid; gap: 2rem; grid-template-columns: minmax(0, 1fr); }

@media (min-width: 60rem) {
  .admin__split { grid-template-columns: minmax(0, 1fr) 20rem; align-items: start; }
}

.admin__card { background: var(--paper); border: 1px solid var(--line); padding: 1.3rem 1.4rem; margin-bottom: 1.2rem; }
.admin__card h2 { font-size: var(--t-h4, 1.05rem); margin-bottom: 0.8rem; }

.admin__hint { color: var(--ink-3); font-size: var(--t-small); }

.grid-table__thumb { width: 3.5rem; }
.grid-table__thumb img { width: 3rem; height: 3rem; object-fit: contain; }

.line__slot {
  display: block;
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* A job the shop can act on today, marked in the list so nobody has to read every row. */
.grid-table tr.is-actionable td:first-child { box-shadow: inset 3px 0 0 var(--ink); }

.admin__form-row { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr)); }

.admin__head--action { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }

/* ---------------------------------------------------------------- order timeline */

.timeline { list-style: none; margin: 0 0 1.5rem; padding: 0; display: flex; flex-direction: column; gap: 0.9rem; }

.timeline__item {
  display: grid;
  gap: 0.15rem 1rem;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  font-size: var(--t-small);
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--line);
}

.timeline__item:last-child { border-bottom: 0; padding-bottom: 0; }

.timeline__when { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.timeline__what { color: var(--ink); }
.timeline__note { display: block; color: var(--ink-2); margin-top: 0.2rem; }
.timeline__who { grid-column: 2; color: var(--ink-3); font-size: var(--t-micro); }

.admin__subhead {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 1.2rem 0 0.4rem;
}

.admin__card .btn { margin-bottom: 0.3rem; }
.admin__card .btn--quiet { display: block; width: 100%; }

/* ---------------------------------------------------------------- dashboard */

.worklist {
  display: grid;
  gap: 1px;
  background: var(--line);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
}

.worklist__item {
  background: var(--paper);
  padding: 1.1rem 1.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  border-bottom: 0;
}

.worklist__item:hover { background: var(--canvas); }

.worklist__n { font-size: var(--t-h3); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }

.worklist__l {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Thirty bars, no library. Baseline-aligned so a quiet day reads as a short bar
   rather than a missing one. */
.chart {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 8rem;
  background: var(--paper);
  padding: 1rem;
  border: 1px solid var(--line);
}

.chart__col { flex: 1 1 0; height: 100%; display: flex; align-items: flex-end; }

.chart__bar {
  width: 100%;
  min-height: 2px;
  background: var(--ink);
  transition: background 0.15s ease;
}

.chart__col:hover .chart__bar { background: var(--signal, var(--ink)); }

/* ---------------------------------------------------------------- option editing */

/* Tight inputs so a table of eighteen articles stays a table rather than a form. */
.field__input--tight { width: 100%; min-width: 5.5rem; padding: 0.35rem 0.5rem; font-size: var(--t-small); }

.swatch-dot {
  display: inline-block;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  margin-right: 0.4rem;
  vertical-align: -1px;
}

/* A deactivated article stays in the table — orders point at it — but recedes. */
.grid-table tr.is-muted { opacity: 0.5; }

/* ---------------------------------------------------------------- campaigns */

/* One line above the masthead while something is running. Inverted, because a campaign that
   blends into the page is a discount given away without being noticed. */
.campaign-bar { background: var(--ink); color: var(--paper); }

.campaign-bar__inner {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.6rem 0;
  flex-wrap: wrap;
  font-size: var(--t-small);
}

.campaign-bar__badge {
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  padding: 0.15rem 0.5rem;
}

.campaign-bar__text { flex: 1 1 auto; }

.campaign-bar__link { color: inherit; border-bottom: 1px solid currentColor; white-space: nowrap; }

.card__flag--campaign { background: var(--ink); color: var(--paper); }

/* The old price, struck through beside the new one. */
.card__was { color: var(--ink-3); text-decoration: line-through; font-size: var(--t-small); margin-left: 0.5rem; }

.basket__code {
  border-top: 1px solid var(--line);
  padding-top: 1.1rem;
  margin: 1.1rem 0 1.4rem;
}

/* The input and its button are one control. Stretch rather than a matched height: the button
   then takes the input's height exactly, whatever the two typefaces do to their line boxes. */
.basket__code-row { display: flex; gap: 0.5rem; align-items: stretch; }
.basket__code-row .field__input { flex: 1 1 auto; min-width: 0; }
/* Margin is zeroed as well as padding: a stretched flex item fills the line including its
   margin, so the admin card's button spacing would otherwise make this one sit short. */
.basket__code-row .btn { flex: none; padding: 0 1.5rem; margin: 0; }

.summary__note--warn { color: var(--signal); }

/* A button that reads as a link — "remove this code" is not a primary action. */
.linkish {
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  color: var(--ink-3);
  text-decoration: underline;
  cursor: pointer;
}

.linkish:hover { color: var(--ink); }

/* ---------------------------------------------------------------- importing */

.import-images { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1rem; }

.import-images img {
  width: 6rem;
  height: 6rem;
  object-fit: contain;
  background: var(--tile);
  border: 1px solid var(--line);
}

/* ---------------------------------------------------------------- product images */

.image-grid {
  display: grid;
  gap: 1px;
  background: var(--line);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
}

.image-card { background: var(--paper); padding: 1.1rem; display: flex; flex-direction: column; gap: 0.8rem; }
.image-card.is-primary { box-shadow: inset 3px 0 0 var(--ink); }

.image-card__media { position: relative; aspect-ratio: 4 / 3; background: var(--tile); }
.image-card__media img { width: 100%; height: 100%; object-fit: contain; }

.image-card__flag {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-condensed);
  font-size: var(--t-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
}

.image-card__body { display: flex; flex-direction: column; gap: 0.5rem; }
.image-card__option { margin-bottom: 0.4rem; }

.image-card__option-name {
  display: block;
  font-size: var(--t-micro);
  color: var(--ink-3);
  margin-bottom: 0.25rem;
}

.image-card__values { display: flex; flex-wrap: wrap; gap: 0.3rem; }

/* Small enough that a row of six colours fits, big enough to hit. */
.chip {
  font: inherit;
  font-size: var(--t-micro);
  padding: 0.25rem 0.55rem;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--ink-2);
  cursor: pointer;
}

.chip:hover { border-color: var(--ink-3); }
.chip.is-selected { background: var(--ink); border-color: var(--ink); color: var(--paper); }
