@charset "utf-8";

/* ==========================================================================
   NOIR GRAIN · handcrafted end-grain boards, Slovakia
   Design system
   --------------------------------------------------------------------------
   The site commits to a single dark visual world. The brand is called Noir;
   a light mode would be a different company. color-scheme is declared so
   form controls, scrollbars and focus rings inherit the same world.

   Type: three families doing three jobs, and one doing the wordmark.
     Fraunces  · display. Sturdy transitional serif. Optical size is pinned
                 (see .disp) so the hairlines never thin out on dark ground.
     Inter     · everything you read. Set at 400, never lighter: light
                 weights on a near-black ground go grey and fall apart.
     Plex Mono · dimensions, prices, serial numbers. Spec-sheet voice.
     Cinzel    · the wordmark only, because the real mark is engraved in
                 roman capitals.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* Ground: warm, brown-biased near-black. Never pure #000. */
  --ink:        #0b0908;
  --ink-2:      #121010;
  --ink-3:      #1a1614;
  --ink-4:      #221c19;
  --line:       #2c2521;
  --line-soft:  #1f1a17;
  --line-raised: #443a33; /* the one rule value bright enough to read as an interactive edge */

  /* Accent: the gold of the engraved maker's mark */
  --bronze:     #c0904d;
  --bronze-lit: #e4c089;
  --bronze-dim: #6f5330;

  /* Type on ground: warm bone, not white */
  --bone:       #efe9e0;
  --bone-2:     #b0a69a; /* body copy: lifted from the brief's #a0968b so
                            16px/400 still reads comfortably on the ground */
  --bone-3:     #8d8479; /* labels and metadata. Do not go dimmer. */

  /* Species. These are data, not decoration: every board lists its mix. */
  --walnut: #493024;
  --cherry: #9e5a33;
  --oak:    #bf9a6a;
  --maple:  #e7d3ac;

  /* Type */
  --f-mark: "Cinzel", "Trajan Pro", Georgia, serif;
  --f-disp: "Fraunces", "Iowan Old Style", Georgia, serif;
  --f-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-mono: "IBM Plex Mono", "SFMono-Regular", Menlo, monospace;

  /* Scale: nothing smaller than 11px, and micro-type carries weight */
  --t-xs:   0.75rem;    /* 12 */
  --t-sm:   0.875rem;   /* 14 */
  --t-base: 1rem;       /* 16 */
  --t-md:   1.125rem;   /* 18 */
  --t-lg:   1.3125rem;  /* 21 */
  --t-xl:   1.875rem;
  --t-2xl:  2.5rem;
  --t-3xl:  3.5rem;
  --t-4xl:  4.75rem;

  /* Rhythm */
  --gut: 1.5rem;
  --pad: clamp(1.25rem, 5vw, 5rem);
  --band: clamp(4rem, 8vw, 7.5rem);
  --shell: 1400px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --------------------------------------------------------------------------
   Reset & base
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* the header is fixed, so in-page anchors have to clear it */
  scroll-padding-top: 92px;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--f-body);
  font-size: var(--t-base);
  font-weight: 400;
  line-height: 1.7;
  /* Deliberately NOT -webkit-font-smoothing: antialiased. On a near-black
     ground it strips weight off every glyph and the page reads grey. */
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

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

h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
}
button { cursor: pointer; }

/* Any component that sets its own `display` silently beats the user agent's
   [hidden] rule, so `hidden` in the markup stops meaning anything. It has to
   win here or it cannot be trusted anywhere. */
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 3px;
}

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

/* --------------------------------------------------------------------------
   Typographic primitives
   -------------------------------------------------------------------------- */

.disp {
  font-family: var(--f-disp);
  font-weight: 500;
  /* Pinning the optical size keeps the strokes solid. Left on auto, Fraunces
     climbs towards a Didone at large sizes and the thins disappear on dark. */
  font-variation-settings: "opsz" 30;
  line-height: 1.1;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.disp em {
  font-style: italic;
  color: var(--bronze-lit);
}

.d1 { font-size: clamp(2.5rem, 6vw, var(--t-4xl)); line-height: 1.04; }
.d2 { font-size: clamp(1.875rem, 4vw, var(--t-3xl)); line-height: 1.08; }
.d3 { font-size: clamp(1.5rem, 2.8vw, var(--t-2xl)); }

/* There is deliberately no eyebrow/kicker style. A tracked label above a
   heading is a crutch: the heading carries its own weight, and every one on
   this site was removed rather than restyled. */

.prose {
  color: var(--bone-2);
  max-width: 62ch;
}
.prose p + p { margin-top: 1em; }
.prose strong { color: var(--bone); font-weight: 600; }
.prose a {
  color: var(--bone);
  border-bottom: 1px solid var(--bronze-dim);
  transition: border-color 0.3s var(--ease);
}
.prose a:hover { border-bottom-color: var(--bronze); }

.dim  { color: var(--bone-2); }

/* Small tracked label: the one micro-type style on the site */
.label {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-3);
}

/* --------------------------------------------------------------------------
   Layout shells
   -------------------------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.band { padding-block: var(--band); }
.band--tight { padding-block: clamp(3rem, 5vw, 4.5rem); }
.band--top0 { padding-top: 0; }

.rule {
  height: 1px;
  background: var(--line);
  border: 0;
  margin: 0;
}

/* Section header: hairline rule, then the title, with an optional standfirst
   alongside. Both columns stay left-aligned: right-ragged body copy is
   measurably harder to read and this page has plenty to read. */
.sechead {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
  margin-bottom: clamp(2.5rem, 4vw, 3.5rem);
}
.sechead--plain { border-top: 0; padding-top: 0; }
/* The gap between a section's own rule and its heading. Was repeated as an
   inline style on nine section headers; it is a token, so it lives here. */
.sechead--pad { padding-top: clamp(2.5rem, 5vw, 4.5rem); }
.sechead__side {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  align-items: flex-start;
}
@media (min-width: 900px) {
  .sechead { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 3.5rem; align-items: end; }
}

/* No eyebrow sits above these headings any more, so the heading is the first
   thing in its column and carries its own weight. */
.sechead__t { margin-top: 0; max-width: 20ch; }

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

.btn {
  --btn-bg: transparent;
  --btn-fg: var(--bone);
  --btn-bd: var(--line-raised);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  padding: 0.95rem 1.9rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color 0.25s var(--ease), background 0.25s var(--ease), border-color 0.25s var(--ease);
}
.btn:hover { background: var(--bone); border-color: var(--bone); color: var(--ink); }

.btn--solid { --btn-bg: var(--bronze); --btn-fg: var(--ink); --btn-bd: var(--bronze); }
.btn--solid:hover { background: var(--bronze-lit); border-color: var(--bronze-lit); color: var(--ink); }

.btn--wide { width: 100%; }
.btn--sm { padding: 0.7rem 1.25rem; }

.btn[disabled] { opacity: 0.4; pointer-events: none; }

/* Text link with a rule under it */
.tlink {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bone);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--line);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.tlink:hover { color: var(--bronze-lit); border-bottom-color: var(--bronze); }
.tlink .arw { transition: transform 0.3s var(--ease); }
.tlink:hover .arw { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.hdr {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 90;
  background: rgba(11, 9, 8, 0);
  border-bottom: 1px solid transparent;
  transition: background 0.35s var(--ease), border-color 0.35s var(--ease);
}
.hdr::before {
  /* readability scrim while the header floats over the hero */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(11, 9, 8, 0.8), rgba(11, 9, 8, 0));
  pointer-events: none;
  transition: opacity 0.35s var(--ease);
}
.hdr.is-stuck {
  background: rgba(11, 9, 8, 0.95);
  border-bottom-color: var(--line);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.hdr.is-stuck::before { opacity: 0; }
/* Pages that don't open on a full-bleed hero start solid */
.hdr--solid { background: rgba(11, 9, 8, 0.95); border-bottom-color: var(--line); }
.hdr--solid::before { opacity: 0; }

.hdr__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  height: 76px;
  position: relative;
  z-index: 1;
}

/* Wordmark: roman capitals, as engraved into the board */
.mark { display: flex; align-items: center; gap: 0.8rem; }
/* The seal is a monogram, not a two-letter word: N sits high-left, G low-right,
   and the two overlap by a couple of pixels at the corner where they meet. The
   letters are absolutely placed in percentages so the whole mark scales from
   one width value. */
.mark__seal {
  position: relative;
  width: 34px; height: 34px;
  flex: none;
  border: 1px solid var(--bronze);
  border-radius: 50%;
  font-family: var(--f-mark);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--bronze);
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}
.mark__seal i {
  position: absolute;
  font-style: normal;
  line-height: 1;
}
.mark__seal i:first-child { top: 17%; left: 17%; }
.mark__seal i:last-child  { top: 41%; left: 40%; }
.mark:hover .mark__seal { background: var(--bronze); color: var(--ink); }
.mark__n {
  font-family: var(--f-mark);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  line-height: 1;
  color: var(--bone);
}

.nav { display: none; }
@media (min-width: 1000px) {
  .nav { display: flex; align-items: center; gap: 2.2rem; }
}
.nav__a {
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--bone-2);
  padding-block: 0.4rem;
  position: relative;
  transition: color 0.25s var(--ease);
}
.nav__a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--bronze);
  /* scaleX rather than width: animating width relayouts the nav on every
     frame of every hover. The origin makes it grow from the left. */
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.3s var(--ease);
}
.nav__a:hover { color: var(--bone); }
.nav__a:hover::after { transform: scaleX(1); }
.nav__a.is-here { color: var(--bone); }
.nav__a.is-here::after { transform: scaleX(1); }

.hdr__tools { display: flex; align-items: center; gap: 0.25rem; }

.icobtn {
  width: 42px; height: 42px;
  display: grid;
  place-items: center;
  color: var(--bone-2);
  position: relative;
  transition: color 0.25s var(--ease);
}
.icobtn:hover { color: var(--bronze-lit); }
.icobtn svg { width: 19px; height: 19px; }

.cartcount {
  position: absolute;
  top: 4px; right: 2px;
  min-width: 16px;
  height: 16px;
  padding-inline: 3px;
  background: var(--bronze);
  color: var(--ink);
  font-family: var(--f-mono);
  font-size: 0.625rem;
  font-weight: 500;
  line-height: 16px;
  text-align: center;
  border-radius: 50px;
  transform: scale(0);
  transition: transform 0.25s var(--ease);
}
.cartcount.is-on { transform: scale(1); }

.burger { display: grid; }
@media (min-width: 1000px) { .burger { display: none; } }

/* Mobile drawer */
.mnav {
  position: fixed;
  inset: 0;
  z-index: 95;
  background: var(--ink);
  padding: 76px var(--pad) var(--pad);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.25rem;
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform 0.45s var(--ease), visibility 0.45s;
}
.mnav.is-open { transform: translateY(0); visibility: visible; }
.mnav__a {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 30;
  font-size: clamp(1.75rem, 8vw, 2.5rem);
  line-height: 1.3;
  padding-block: 0.5rem;
  border-bottom: 1px solid var(--line-soft);
}
.mnav__a:hover { color: var(--bronze-lit); }
.mnav__foot { margin-top: 2.5rem; }

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

.hero {
  position: relative;
  min-height: 88vh; /* fallback for browsers without svh */
  min-height: min(92svh, 880px);
  display: flex;
  align-items: flex-end;
  padding-top: 76px;
  overflow: hidden;
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 62% 45%;
}
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, var(--ink) 2%, rgba(11, 9, 8, 0.84) 32%, rgba(11, 9, 8, 0.4) 62%, rgba(11, 9, 8, 0.12) 100%),
    linear-gradient(to right, rgba(11, 9, 8, 0.9) 0%, rgba(11, 9, 8, 0.35) 58%, rgba(11, 9, 8, 0.5) 100%);
}

.hero__in {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-bottom: clamp(3rem, 8vh, 5.5rem);
}
.hero__h { margin-top: 1.4rem; max-width: 16ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2.25rem; }

/* Compact page header for interior pages */
.phead {
  padding-top: calc(76px + clamp(3.5rem, 7vw, 6rem));
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
  border-bottom: 1px solid var(--line);
}
.phead__grid { display: grid; gap: 1.75rem; }
@media (min-width: 900px) {
  .phead__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 26rem); gap: 4rem; align-items: end; }
}
.phead__h { margin-top: 0; }

/* Breadcrumb: the only place a path is spelled out, on the detail page */
.crumb {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bone-3);
}
.crumb a { transition: color 0.25s var(--ease); }
.crumb a:hover { color: var(--bronze-lit); }

/* --------------------------------------------------------------------------
   Product cards
   -------------------------------------------------------------------------- */

.grid-p {
  display: grid;
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}
@media (min-width: 640px)  { .grid-p { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1160px) { .grid-p { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1160px) { .grid-p--3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  display: flex;
  flex-direction: column;
  background: var(--ink);
  padding: 1.1rem 1.1rem 1.35rem;
  position: relative;
  transition: background 0.35s var(--ease);
}
.card:hover { background: var(--ink-2); }
.card.is-hidden { display: none; }

.card__fig {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--ink-3);
  margin-bottom: 1.15rem;
}
.card__fig img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease);
}
.card:hover .card__fig img { transform: scale(1.04); }

.card__tag {
  position: absolute;
  top: 0; left: 0;
  background: var(--ink);
  color: var(--bronze);
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.4rem 0.7rem;
}

.card__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.card__n {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 24;
  font-size: 1.3125rem;
  line-height: 1.15;
}
.card__p {
  font-family: var(--f-mono);
  font-size: var(--t-sm);
  color: var(--bronze);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.card__dim {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  color: var(--bone-3);
  margin-top: 0.4rem;
}
.card__d {
  font-size: var(--t-sm);
  color: var(--bone-2);
  margin-top: 0.75rem;
  line-height: 1.6;
  flex: 1;
}
.card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line-soft);
}

/* Species swatches: real data: the woods in this board */
.woods { display: flex; align-items: center; gap: 0.3rem; }
.woods__s {
  width: 13px; height: 13px;
  flex: none;
  border: 1px solid rgba(239, 233, 224, 0.14);
}
.w-walnut { background: var(--walnut); }
.w-cherry { background: var(--cherry); }
.w-oak    { background: var(--oak); }
.w-maple  { background: var(--maple); }

.card__cta {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone-2);
  transition: color 0.25s var(--ease);
}
.card:hover .card__cta,
.card__cta:hover { color: var(--bronze-lit); }

/* --------------------------------------------------------------------------
   Filters
   -------------------------------------------------------------------------- */

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.75rem 2.5rem;
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--line);
}
.fgroup { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
.fgroup__l {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-3);
  margin-right: 0.4rem;
}
.chip {
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--line);
  font-size: var(--t-xs);
  font-weight: 500;
  color: var(--bone-2);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.chip:hover { color: var(--bone); border-color: var(--line-raised); }
.chip.is-on { background: var(--bronze); border-color: var(--bronze); color: var(--ink); font-weight: 600; }

.fcount {
  margin-left: auto;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--bone-3);
  font-variant-numeric: tabular-nums;
}

.empty {
  padding: 4rem 0;
  text-align: center;
  color: var(--bone-2);
}

/* --------------------------------------------------------------------------
   Split editorial blocks
   -------------------------------------------------------------------------- */

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .split--wide-l { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  .split--wide-r { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
}
.split--top { align-items: start; }
.split--pad { padding-top: clamp(2.5rem, 5vw, 4.5rem); }
.split__body { display: flex; flex-direction: column; align-items: flex-start; gap: 1.4rem; }
.split__body .prose { max-width: 48ch; }

.frame { position: relative; overflow: hidden; background: var(--ink-3); }
.frame img { width: 100%; height: 100%; object-fit: cover; }
.frame--tall { aspect-ratio: 4 / 5; }
.frame--wide { aspect-ratio: 3 / 2; }
.frame--sq   { aspect-ratio: 1 / 1; }

/* --------------------------------------------------------------------------
   Detail strip: crops, captioned
   -------------------------------------------------------------------------- */

.details {
  display: grid;
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}
@media (min-width: 700px)  { .details { grid-template-columns: repeat(3, 1fr); } }

.detail { background: var(--ink); padding-bottom: 1.6rem; }
.detail__fig { aspect-ratio: 5 / 4; overflow: hidden; background: var(--ink-3); }
.detail__fig img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease);
}
.detail:hover .detail__fig img { transform: scale(1.04); }
.detail__b { padding: 1.4rem 1.25rem 0; }
.detail__t {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 24;
  font-size: 1.1875rem;
  line-height: 1.2;
}
.detail__d { font-size: var(--t-sm); color: var(--bone-2); margin-top: 0.6rem; line-height: 1.6; }

/* --------------------------------------------------------------------------
   End grain vs edge grain: the one diagram on the site, and the page's one
   authored motion moment.

   Both figures are the same cross-section through a board at the same moment:
   a blade in the wood. The end-grain board's twenty fibres stand on end and
   each pivots about its own base, so the blade parts them like bristles; when
   it lifts they swing back and the surface closes with nothing left behind.
   The edge-grain board's nine layers lie flat and cannot pivot: the blade
   severs them, and the kerf it opens is still there after the blade is gone.

   Frame zero of the animation IS the resting pose (blade in, fibres parted,
   kerf open), so the diagram still argues with JavaScript off and under
   prefers-reduced-motion, and the cycle returns to it rather than snapping.
   -------------------------------------------------------------------------- */

.fibres {
  display: grid;
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}
@media (min-width: 760px) { .fibres { grid-template-columns: repeat(2, 1fr); } }

.fibre { background: var(--ink); padding: 1.6rem 1.6rem 1.8rem; }
.fibre__hd {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.3rem;
}
.fibre__t {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 24;
  font-size: 1.3125rem;
}
.fibre__v {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.3rem 0.6rem;
  border: 1px solid currentColor;
  white-space: nowrap;
}
.fibre__v--good { color: var(--bronze); }
.fibre__v--bad  { color: var(--bone-3); }
.fibre__d { font-size: var(--t-sm); color: var(--bone-2); margin-top: 1.3rem; line-height: 1.6; }

.mech__svg { display: block; width: 100%; height: auto; }

/* fill-box so the percentage origin resolves against each element's own box:
   every fibre has to pivot about its own base, not the viewBox's. */
.mech__svg .fb,
.mech__svg .mech__blade { transform-box: fill-box; }
/* 85%, not 100%: the fibres run 24 units below the frame so that rotating them
   cannot swing a bottom corner out of the shading (a bright sliver of raw
   maple) or leave a notch at the board's edge. The pivot stays on the old
   base line, which is where 85% of the taller box now falls. */
.mech__svg .fb { transform-origin: 50% 85%; transform: rotate(calc(var(--d) * 1deg)); }
.mech__svg .mech__blade { transform-origin: 50% 0; transform: translateY(0); }

/* The kerf needs no animation: at rest the blade is sitting in it, so lifting
   the blade is what reveals it. Wood does not un-cut itself. */

.is-cutting .mech__svg .fb        { animation: mechPart 5.6s var(--ease) both; }
.is-cutting .mech__svg .mech__blade { animation: mechLift 5.6s var(--ease) both; }

@keyframes mechLift {
  0%,  10% { transform: translateY(0); }
  30%, 62% { transform: translateY(-92px); }
  82%,100% { transform: translateY(0); }
}
@keyframes mechPart {
  0%,  12% { transform: rotate(calc(var(--d) * 1deg)); }
  28%      { transform: rotate(calc(var(--d) * -0.18deg)); }  /* springs past */
  36%, 64% { transform: rotate(0deg); }                       /* closed, no mark */
  84%,100% { transform: rotate(calc(var(--d) * 1deg)); }
}

/* The control rides the grid's bottom hairline, centred between the two
   figures, so it reads as belonging to the pair rather than to either one.
   Ground fill interrupts the rule, which is what makes it findable. */
.mech__ctl {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  /* .argue is a flex column with a band-sized gap; cancel that first, then
     pull up by half the control's height so it straddles the bottom rule. */
  margin-top: calc(-1.15rem - clamp(3rem, 6vw, 5rem));
}
.mech__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  background: var(--ink);
  color: var(--bone);
  border: 1px solid var(--line-raised);
  padding: 0.68rem 1.2rem;
  font-family: var(--f-body);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: color 0.3s var(--ease), background-color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.mech__btn svg { width: 13px; height: 13px; flex: none; transition: transform 0.5s var(--ease); }
.mech__btn:hover { background: var(--bone); color: var(--ink); border-color: var(--bone); }
.mech__btn:hover svg { transform: rotate(-150deg); }
/* No JavaScript, no replay, and therefore no rule to interrupt. */
.mech__ctl:has([hidden]) { display: none; }

@media (prefers-reduced-motion: reduce) {
  .is-cutting .mech__svg .fb,
  .is-cutting .mech__svg .mech__blade { animation: none; }
}

/* --------------------------------------------------------------------------
   Full-bleed banner
   -------------------------------------------------------------------------- */

.bleed { position: relative; overflow: hidden; }
.bleed__media { position: absolute; inset: 0; }
.bleed__media img,
.bleed__media video { width: 100%; height: 100%; object-fit: cover; }
/* pushes the crop down onto the bench, away from the signage on the wall */
.bleed__media--low img { object-position: 50% 76%; }
.bleed__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, rgba(11, 9, 8, 0.95) 0%, rgba(11, 9, 8, 0.78) 42%, rgba(11, 9, 8, 0.35) 100%);
}
.bleed__in {
  position: relative;
  z-index: 1;
  min-height: clamp(22rem, 46vw, 32rem);
  display: flex;
  align-items: center;
}
.bleed__body { max-width: 38rem; display: flex; flex-direction: column; align-items: flex-start; gap: 1.4rem; }

/* --------------------------------------------------------------------------
   Care kit / checklist
   -------------------------------------------------------------------------- */

/* Three siblings, so it is a hairline cell grid at a column count of one and
   not a stack of bordered rows. Same primitive as the rates and the creed. */
.kit {
  display: grid;
  gap: 1px;
  width: 100%;
  max-width: 27rem;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}
.kit__i {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  background: var(--ink);
  padding: 0.85rem 1rem;
  font-size: var(--t-sm);
}
.kit__i span:first-child { color: var(--bone); }
.kit__i span:last-child {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  color: var(--bone-3);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Spec table
   -------------------------------------------------------------------------- */

.specs { width: 100%; border-collapse: collapse; }
.specs th, .specs td {
  text-align: left;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
.specs th {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bone-3);
  width: 42%;
  padding-right: 1.5rem;
}
.specs td { font-size: var(--t-sm); color: var(--bone); font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   Product detail page
   -------------------------------------------------------------------------- */

.pd { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); }
@media (min-width: 1000px) {
  .pd { grid-template-columns: minmax(0, 1fr) minmax(0, 27rem); align-items: start; }
}

.gal { display: flex; flex-direction: column; gap: 1px; }
.gal__main {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--ink-3);
  position: relative;
}
.gal__main img { width: 100%; height: 100%; object-fit: cover; }
/* The thumb count varies by piece (the coasters have two views, a board has
   five), so the track count comes from the catalogue, not from this file. */
.gal__thumbs { display: grid; grid-template-columns: repeat(var(--n, 5), 1fr); gap: 1px; }
.gal__t {
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--ink-3);
  opacity: 0.45;
  transition: opacity 0.3s var(--ease);
  position: relative;
}
.gal__t img { width: 100%; height: 100%; object-fit: cover; }
.gal__t:hover { opacity: 0.8; }
.gal__t.is-on { opacity: 1; }
.gal__t.is-on::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--bronze);
}

/* Not sticky: this column carries the full spec sheet and the accordion,
   so it is taller than the viewport and pinning it would strand the bottom. */
.buy { display: flex; flex-direction: column; gap: 1.75rem; }

.buy__price {
  font-family: var(--f-mono);
  font-size: 1.5rem;
  color: var(--bronze);
  font-variant-numeric: tabular-nums;
}
.buy__vat { font-size: var(--t-xs); color: var(--bone-3); }

.opt { display: flex; flex-direction: column; gap: 0.85rem; }
.opt__hd {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.opt__l {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-3);
}
.opt__pick { font-size: var(--t-sm); color: var(--bone); }

.swatch-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); }

.sw {
  background: var(--ink);
  padding: 0.85rem 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: flex-start;
  text-align: left;
  transition: background 0.25s var(--ease);
}
.sw:hover { background: var(--ink-3); }
.sw.is-on { background: var(--ink-4); }
.sw.is-on .sw__n { color: var(--bronze-lit); }
.sw__bar { display: flex; width: 100%; height: 8px; }
.sw__bar i { flex: 1; }
.sw__n { font-size: var(--t-xs); font-weight: 500; color: var(--bone-2); line-height: 1.35; transition: color 0.25s var(--ease); }
.sw__x { font-family: var(--f-mono); font-size: 0.6875rem; color: var(--bone-3); font-variant-numeric: tabular-nums; }

.sizes { display: flex; flex-direction: column; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.size {
  background: var(--ink);
  padding: 0.9rem 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  text-align: left;
  transition: background 0.25s var(--ease);
}
.size:hover { background: var(--ink-3); }
.size.is-on { background: var(--ink-4); }
.size__n { font-size: var(--t-sm); font-weight: 500; color: var(--bone-2); }
.size.is-on .size__n { color: var(--bronze-lit); }
.size__d { font-family: var(--f-mono); font-size: 0.6875rem; color: var(--bone-3); font-variant-numeric: tabular-nums; }

.adds { display: flex; flex-direction: column; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.add {
  background: var(--ink);
  padding: 0.9rem 1rem;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  cursor: pointer;
  transition: background 0.25s var(--ease);
}
.add:hover { background: var(--ink-3); }
.add input { position: absolute; opacity: 0; pointer-events: none; }
.add__box {
  width: 16px; height: 16px;
  flex: none;
  border: 1px solid var(--line-raised);
  display: grid;
  place-items: center;
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.add__box::after {
  content: "";
  width: 8px; height: 8px;
  background: var(--ink);
  transform: scale(0);
  transition: transform 0.2s var(--ease);
}
.add input:checked + .add__box { background: var(--bronze); border-color: var(--bronze); }
.add input:checked + .add__box::after { transform: scale(1); }
.add input:focus-visible + .add__box { outline: 2px solid var(--bronze); outline-offset: 2px; }
.add__n { font-size: var(--t-sm); color: var(--bone-2); flex: 1; }
.add__p { font-family: var(--f-mono); font-size: 0.6875rem; color: var(--bone-3); font-variant-numeric: tabular-nums; }

.engrave { display: none; padding: 0 1rem 1rem; background: var(--ink); }
.engrave.is-on { display: block; }

.field { display: flex; flex-direction: column; gap: 0.5rem; }
.field__l {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-3);
}
.inp {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--ink-2);
  border: 1px solid var(--line);
  color: var(--bone);
  font-size: var(--t-sm);
  transition: border-color 0.25s var(--ease);
}
.inp::placeholder { color: var(--bone-3); }
.inp:focus { outline: none; border-color: var(--bronze); }
textarea.inp { resize: vertical; min-height: 8rem; line-height: 1.6; }
select.inp {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--bone-2) 50%), linear-gradient(135deg, var(--bone-2) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 2.5rem;
}

.leadtime {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone-2);
}
.leadtime::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--bronze);
  box-shadow: 0 0 0 3px rgba(192, 144, 77, 0.16);
  flex: none;
}

/* --------------------------------------------------------------------------
   Accordion
   -------------------------------------------------------------------------- */

.acc { border-top: 1px solid var(--line); }
.acc__i { border-bottom: 1px solid var(--line); }
.acc__b {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.3rem 0;
  text-align: left;
  font-size: var(--t-base);
  font-weight: 500;
  color: var(--bone);
  transition: color 0.25s var(--ease);
}
.acc__b:hover { color: var(--bronze-lit); }
.acc__sign { position: relative; width: 12px; height: 12px; flex: none; }
.acc__sign::before,
.acc__sign::after {
  content: "";
  position: absolute;
  background: var(--bronze);
  transition: transform 0.3s var(--ease);
}
.acc__sign::before { top: 50%; left: 0; width: 12px; height: 1px; margin-top: -0.5px; }
.acc__sign::after  { left: 50%; top: 0; width: 1px; height: 12px; margin-left: -0.5px; }
.acc__i.is-open .acc__sign::after { transform: rotate(90deg); }
.acc__p {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s var(--ease);
}
.acc__i.is-open .acc__p { grid-template-rows: 1fr; }
.acc__p > div { overflow: hidden; }
.acc__p .prose { padding-bottom: 1.4rem; font-size: var(--t-sm); }

/* --------------------------------------------------------------------------
   Steps: a real sequence, so it is numbered
   -------------------------------------------------------------------------- */

.steps { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); }
@media (min-width: 640px)  { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.step { background: var(--ink); padding: 1.9rem 1.5rem 2rem; display: flex; flex-direction: column; gap: 0.85rem; }
.step__n {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bronze);
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--line);
}
.step__t {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 24;
  font-size: 1.3125rem;
  line-height: 1.2;
}
.step__d { font-size: var(--t-sm); color: var(--bone-2); line-height: 1.6; }

/* --------------------------------------------------------------------------
   Figures / stats
   -------------------------------------------------------------------------- */

.figs { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); }
@media (min-width: 560px)  { .figs { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .figs { grid-template-columns: repeat(4, 1fr); } }
.fig { background: var(--ink); padding: 1.75rem 1.5rem; display: flex; flex-direction: column; gap: 0.5rem; }
.fig__v {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 30;
  font-size: clamp(2rem, 3.4vw, 2.75rem);
  line-height: 1;
  color: var(--bone);
  font-variant-numeric: tabular-nums;
}
.fig__v sup { font-size: 0.38em; vertical-align: super; color: var(--bronze); }
.fig__l { font-size: var(--t-sm); color: var(--bone-2); line-height: 1.5; }

/* --------------------------------------------------------------------------
   The rack: the four species, as stock
   -------------------------------------------------------------------------- */

.rack { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); }
@media (min-width: 560px)  { .rack { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .rack { grid-template-columns: repeat(4, 1fr); } }
.rack__i { background: var(--ink); display: flex; flex-direction: column; }
/* Now a photograph of the finished surface of that species, cropped from one
   frame so all four share a lens, an angle and a light. This replaced a
   procedural feTurbulence field on 2026-08-07: on a page whose whole claim is
   that the colour is the wood, generated grain was still a paint chip. */
.rack__c { display: block; width: 100%; height: 88px; object-fit: cover; }
.rack__b { padding: 1.4rem 1.25rem 1.75rem; display: flex; flex-direction: column; gap: 0.6rem; flex: 1; }
.rack__n {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 24;
  font-size: 1.3125rem;
  line-height: 1.15;
}
.rack__m {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--bone-3);
  font-variant-numeric: tabular-nums;
}
.rack__d { font-size: var(--t-sm); color: var(--bone-2); line-height: 1.6; }

/* --------------------------------------------------------------------------
   The three rules: care's spine

   Everything a keeper has to do is three sentences long, so the page is built
   as those three and their elaboration rather than as five equal sections.
   A single-column hairline grid: the same primitive as every other grid on
   the site, at a column count of one, so it reads as a ruled ledger and not
   as three cards. Each rule keeps its own prohibition instead of sending the
   reader to a separate Never column to cross-reference.
   -------------------------------------------------------------------------- */

.creed { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); }
.creed__i {
  background: var(--ink);
  padding: clamp(1.75rem, 3.5vw, 2.75rem);
  display: grid;
  gap: 1.75rem;
}
@media (min-width: 900px) {
  .creed__i {
    grid-template-columns: minmax(0, 19rem) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 4rem);
  }
}
.creed__k { display: flex; flex-direction: column; gap: 0.85rem; }
.creed__n {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bronze);
  /* The same hairline under the label that a construction step carries, so a
     rule cell and a step cell are recognisably the same object. */
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--line);
}
.creed__t {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 30;
  /* the Subhead step: the ramp's per-item display size, same as a product
     name on a detail page. Was an invented clamp sitting between Title and
     Subhead, which is a type step the system does not have. */
  font-size: clamp(1.5rem, 2.8vw, 2.5rem);
  line-height: 1.1;
  max-width: 13ch;
}
/* Legal register. The cell grid is right for terms — a clause is exactly the
   label-plus-body shape the creed already is — but eleven clauses set at the
   care page's 40px imperative would shout at the one reader who came here to
   be reassured. The title drops one documented step to Title Small and widens
   so a clause name lands on one line or two, never three. */
.creed--legal .creed__t { font-size: var(--t-xl); max-width: 20ch; }
.creed--legal .creed__d + .creed__d { margin-top: -0.4rem; }
.creed__b { display: flex; flex-direction: column; gap: 1.4rem; align-items: flex-start; }
.creed__d { color: var(--bone-2); line-height: 1.7; max-width: 54ch; }
.creed__no { display: flex; gap: 1rem; padding-top: 1.15rem; border-top: 1px solid var(--line); max-width: 54ch; }
.creed__x {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone-3);
  flex: none;
  padding-top: 0.3rem;
}
.creed__no span + span { font-size: var(--t-sm); color: var(--bone-2); line-height: 1.65; }

/* .ritual is gone. It was a stacked list with border separators, built to keep
   the oiling from looking like the workshop's construction grid; what it
   actually did was put the one thing on the page that was not made from the
   hairline cell grid inside the one section that most needed to look built.
   The oiling is now a four-cell .steps grid in its own section. Two ruled
   tables on two pages is the system working, not a collision: the whole point
   of the primitive is that a construction sequence and a care procedure
   resolve to the same table. */

/* --------------------------------------------------------------------------
   Shipping rates: four destinations as cells rather than seven table rows
   -------------------------------------------------------------------------- */

.rates { display: grid; gap: 1px; background: var(--line-soft); border: 1px solid var(--line-soft); }
@media (min-width: 640px)  { .rates { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .rates { grid-template-columns: repeat(4, 1fr); } }
.rate { background: var(--ink); padding: 1.6rem 1.4rem 1.8rem; display: flex; flex-direction: column; gap: 0.6rem; }
.rate__w {
  font-family: var(--f-disp);
  font-weight: 500;
  font-variation-settings: "opsz" 24;
  font-size: 1.1875rem;
  line-height: 1.2;
}
.rate__p {
  font-family: var(--f-mono);
  /* the Total step. 1.125rem is the Lede size: a sans reading size, not one
     of the ramp's mono steps, and a shipping cost is a total. */
  font-size: 1.25rem;
  color: var(--bronze);
  font-variant-numeric: tabular-nums;
}
.rate__t { font-size: var(--t-sm); color: var(--bone-3); line-height: 1.5; }

.shipfoot { display: grid; gap: 1.5rem; margin-top: clamp(2rem, 4vw, 3rem); }
@media (min-width: 760px) { .shipfoot { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3rem; } }
.shipfoot .prose { max-width: 48ch; }


/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.formgrid { display: grid; gap: 1.25rem; }
@media (min-width: 640px) { .formgrid--2 { grid-template-columns: repeat(2, 1fr); } }
.formgrid__full { grid-column: 1 / -1; }

/* --------------------------------------------------------------------------
   Quote
   -------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------
   Cart drawer
   -------------------------------------------------------------------------- */

.scrim {
  position: fixed;
  inset: 0;
  z-index: 96;
  background: rgba(4, 3, 3, 0.72);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s var(--ease), visibility 0.35s;
}
.scrim.is-on { opacity: 1; visibility: visible; }

.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 97;
  width: min(27rem, 100vw);
  background: var(--ink-2);
  border-left: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  transform: translateX(101%);
  /* visibility keeps the closed drawer out of the tab order, which matters
     because it is aria-hidden while off-screen */
  visibility: hidden;
  transition: transform 0.4s var(--ease), visibility 0.4s;
}
.drawer.is-open { transform: translateX(0); visibility: visible; }

.drawer__hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.35rem var(--gut);
  border-bottom: 1px solid var(--line);
  flex: none;
}
.drawer__t { font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; }
.drawer__body { flex: 1; overflow-y: auto; padding: var(--gut); }
.drawer__ft { flex: none; padding: var(--gut); border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 1rem; }

.citem { display: grid; grid-template-columns: 68px 1fr; gap: 1rem; padding-bottom: 1.25rem; margin-bottom: 1.25rem; border-bottom: 1px solid var(--line-soft); }
.citem:last-child { border-bottom: 0; margin-bottom: 0; }
.citem__fig { aspect-ratio: 1 / 1; overflow: hidden; background: var(--ink-3); }
.citem__fig img { width: 100%; height: 100%; object-fit: cover; }
.citem__n { font-family: var(--f-disp); font-weight: 500; font-variation-settings: "opsz" 24; font-size: 1.0625rem; line-height: 1.25; }
.citem__v { font-size: var(--t-xs); color: var(--bone-3); margin-top: 0.35rem; line-height: 1.5; }
.citem__r { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 0.7rem; }
.citem__p { font-family: var(--f-mono); font-size: var(--t-sm); color: var(--bronze); font-variant-numeric: tabular-nums; }

.qty { display: flex; align-items: center; border: 1px solid var(--line); }
.qty button {
  width: 28px; height: 28px;
  display: grid;
  place-items: center;
  color: var(--bone-2);
  font-size: 0.875rem;
  line-height: 1;
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
.qty button:hover { color: var(--ink); background: var(--bronze); }
.qty__n { min-width: 28px; text-align: center; font-family: var(--f-mono); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }

.total { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.total__l { font-family: var(--f-mono); font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--bone-3); }
.total__v { font-family: var(--f-mono); font-size: 1.25rem; color: var(--bronze); font-variant-numeric: tabular-nums; }

.cartempty { display: flex; flex-direction: column; align-items: flex-start; gap: 1.25rem; padding-top: 2rem; color: var(--bone-2); font-size: var(--t-sm); }

/* Toast */
.toast {
  position: fixed;
  left: 50%; bottom: 2rem;
  transform: translate(-50%, 200%);
  z-index: 98;
  background: var(--bronze);
  color: var(--ink);
  padding: 0.9rem 1.5rem;
  font-size: var(--t-sm);
  font-weight: 600;
  /* An empty toast still has padding, so translate alone leaves a sliver
     of bronze above the fold. Hide it outright until it has something to say. */
  opacity: 0;
  visibility: hidden;
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease), visibility 0.4s;
  max-width: calc(100vw - 2rem);
  text-align: center;
}
.toast.is-on { transform: translate(-50%, 0); opacity: 1; visibility: visible; }

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

.ftr { border-top: 1px solid var(--line); background: var(--ink-2); }
.ftr__grid {
  display: grid;
  gap: 2.5rem 3rem;
  padding-block: clamp(3rem, 6vw, 5rem);
}
@media (min-width: 700px)  { .ftr__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1050px) { .ftr__grid { grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.9fr) minmax(0, 0.9fr) minmax(0, 1.3fr); gap: 4rem; } }

.ftr__h {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bronze);
  margin-bottom: 1.25rem;
}
.ftr__list { display: flex; flex-direction: column; gap: 0.75rem; }
.ftr__list a { font-size: var(--t-sm); color: var(--bone-2); transition: color 0.25s var(--ease); width: fit-content; }
.ftr__list a:hover { color: var(--bronze-lit); }
.ftr__addr { font-size: var(--t-sm); color: var(--bone-2); line-height: 1.8; font-style: normal; }
.ftr__addr a { transition: color 0.25s var(--ease); }
.ftr__addr a:hover { color: var(--bronze-lit); }

.social { display: flex; gap: 0.5rem; margin-top: 1.5rem; }
.social a {
  width: 38px; height: 38px;
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  color: var(--bone-2);
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.social a:hover { color: var(--bronze); border-color: var(--bronze); }
.social svg { width: 16px; height: 16px; }

.signup { display: flex; flex-direction: column; gap: 0.7rem; }
.signup__row { display: flex; }
.signup__row .inp { border-right: 0; }
.signup__row .btn { flex: none; }
.signup__note { font-size: var(--t-xs); color: var(--bone-3); line-height: 1.6; }

.ftr__base {
  border-top: 1px solid var(--line);
  padding-block: 1.4rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 2rem;
  align-items: center;
  justify-content: space-between;
  font-size: var(--t-xs);
  color: var(--bone-3);
}
.ftr__base a { transition: color 0.25s var(--ease); }
.ftr__base a:hover { color: var(--bronze); }
.ftr__legal { display: flex; flex-wrap: wrap; gap: 1.5rem; }

/* --------------------------------------------------------------------------
   Stage: the opening viewport. One object in the dark and nothing else:
   no specification, no price, no proof. Everything the visitor needs to
   decide arrives in the fold beneath. The withholding is the composition.
   -------------------------------------------------------------------------- */

.stage {
  position: relative;
  min-height: 88vh; /* fallback for browsers without svh */
  min-height: min(94svh, 940px);
  display: flex;
  align-items: center;
  padding-top: 76px;
  overflow: hidden;
}

.stage__media { position: absolute; inset: 0; z-index: 0; }
/* <picture> is inline by default, so the img's height:100% would resolve
   against nothing and the stage would go blank. */
.stage__media picture { display: block; width: 100%; height: 100%; }
.stage__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Holds the board right of centre so the dark field stays clear for type */
  object-position: 68% 56%;
}
/* Below 760px the stage is taller than it is wide, the type sits over the image
   instead of beside it, and the scrim therefore shifts to a vertical one.

   No object-position could rescue the 16:9 source here. Measured at a true
   390px: ng-hero.jpg is 1376x768, cover into 390x793 scales it to 1422 wide, so
   the viewport shows 27% of the image width while the board spans about 65% of
   it. The whole object simply does not fit. The markup now swaps in a 9:16
   source at this breakpoint instead, which is composed for the crop, so the
   position goes back to centred. */
/* Scrims are built from the ground colour at varying alpha, never from black:
   a neutral scrim over warm photography goes visibly cold at the midpoints.
   Two axes, because the type column crosses a lit stretch of table.

   Order matters here and it bit us once. This base rule used to sit AFTER the
   max-width block below, and since the two have equal specificity the later
   one won at every width: the narrow-viewport scrim was dead code and the
   phone was quietly being served the desktop left-to-right gradient. The
   override has to come second. */
.stage__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right,
      var(--ink) 0%,
      rgba(11, 9, 8, 0.93) 24%,
      rgba(11, 9, 8, 0.6) 46%,
      rgba(11, 9, 8, 0.16) 74%,
      rgba(11, 9, 8, 0) 100%),
    linear-gradient(to bottom,
      rgba(11, 9, 8, 0.72) 0%,
      rgba(11, 9, 8, 0) 24%,
      rgba(11, 9, 8, 0) 60%,
      var(--ink) 100%);
}

@media (max-width: 759px) {
  .stage__media img { object-position: 50% 50%; }
  /* One axis, not two: the type sits over the image rather than beside it, so
     a left-to-right gradient darkens the wrong half. Tuned to the 9:16 source,
     which stands the board in the bottom of the frame. The type column runs
     from roughly 30% to 78% of the viewport, so its lower half crosses the lit
     face of the board: the stops between 52% and 88% carry that contrast,
     while 24% stays light so the empty upper field keeps some warmth. */
  .stage__media::after {
    background:
      linear-gradient(to bottom,
        rgba(11, 9, 8, 0.84) 0%,
        rgba(11, 9, 8, 0.40) 26%,
        rgba(11, 9, 8, 0.50) 56%,
        rgba(11, 9, 8, 0.68) 76%,
        rgba(11, 9, 8, 0.88) 92%,
        var(--ink) 100%);
  }
}

.stage__in { position: relative; z-index: 1; width: 100%; }
.stage__body { max-width: 34rem; }
.stage__body .d1 { max-width: 15ch; }
.stage__sub {
  margin-top: 1.5rem;
  max-width: 42ch;
  font-size: var(--t-md);
  line-height: 1.65;
  color: var(--bone-2);
}
.stage__body .btn { margin-top: 2.25rem; }

/* A quiet pointer to the argument below. It exists because the opening
   deliberately answers nothing, so the way down has to be visible. */
.stage__more {
  position: absolute;
  left: 50%;
  bottom: clamp(1.5rem, 3vh, 2.75rem);
  transform: translateX(-50%);
  z-index: 1;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  color: var(--bone-3);
  transition: color 0.25s var(--ease);
}
@media (min-width: 900px) { .stage__more { display: flex; } }
.stage__more:hover { color: var(--bronze-lit); }
.stage__more-l {
  font-family: var(--f-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.stage__more svg { width: 14px; height: 23px; }

/* Header floats over the stage with no rule and no scrim of its own: the
   stage already carries a top-down gradient, and doubling them muddies it. */
.hdr--float::before { opacity: 0; }

/* --------------------------------------------------------------------------
   The argument: the fold directly beneath the stage
   -------------------------------------------------------------------------- */

.argue { display: flex; flex-direction: column; gap: clamp(3rem, 6vw, 5rem); }
.argue__lede { max-width: 54ch; }
.argue__lede .d2 { max-width: 18ch; }

/* --------------------------------------------------------------------------
   Close
   -------------------------------------------------------------------------- */

.close__in {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.35rem;
  max-width: 46rem;
}
.close__in .d2 { max-width: 20ch; }
.close__cta { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 0.75rem; }

/* --------------------------------------------------------------------------
   Scroll reveal: one gesture, small, once
   -------------------------------------------------------------------------- */

/* Only hide the reveal target when there is something around to un-hide it.
   `is-in` is added by site.js; without the guard, a page loaded with scripting
   off keeps the enquiry form, the spec tables and the grain diagram at zero
   opacity forever. Browsers that do not know the media feature simply skip
   the animation and show the content, which is the right way to fail. */
@media (scripting: enabled) {
  .rv {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
  }
}
.rv.is-in { opacity: 1; transform: none; }
.rv-d1 { transition-delay: 0.08s; }
.rv-d2 { transition-delay: 0.16s; }

/* Hero load sequence */
.hero .rise { opacity: 0; transform: translateY(18px); animation: rise 0.8s var(--ease) forwards; }
.hero .rise-1 { animation-delay: 0.1s; }
.hero .rise-2 { animation-delay: 0.2s; }
.hero .rise-3 { animation-delay: 0.3s; }
.hero .rise-4 { animation-delay: 0.4s; }
@keyframes rise { to { opacity: 1; transform: none; } }

/* --------------------------------------------------------------------------
   Utilities
   -------------------------------------------------------------------------- */

.stack  { display: flex; flex-direction: column; }
.gap-md { gap: 1.5rem; }
.gap-lg { gap: 2.5rem; }
.mt-lg  { margin-top: clamp(2rem, 4vw, 3rem); }
.mt-md  { margin-top: 1.5rem; }
.mt-sm  { margin-top: 0.85rem; }
.sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: absolute;
  top: -100px; left: var(--pad);
  z-index: 100;
  background: var(--bronze);
  color: var(--ink);
  padding: 0.75rem 1.25rem;
  font-size: var(--t-sm);
  font-weight: 600;
  transition: top 0.25s var(--ease);
}
.skip:focus { top: 1rem; }

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .rv { opacity: 1; transform: none; }
  .hero .rise { opacity: 1; transform: none; }
}
