@import url("fonts.css");

/* ============================================================================
   UNIDOLLY — Loyalty deserves the best
   Palette sampled directly from the client comps; type is Newsreader (display)
   + Jost (labels/UI), both self-hosted so nothing depends on a CDN at runtime.
   ========================================================================== */

:root {
  /* surfaces */
  --espresso: #261d15;
  --espresso-deep: #1c1510;
  --paper: #efedea;   /* product photography is multiply-tinted to exactly this */
  /* Ground of the illustrated collection band, and the knockout inside the chamfered button
     that sits on it. Measured off the rendered page: this plate's own ground is neutral, so
     it ships untinted and lands on #fefefe. (An earlier plate had a warm ground and was
     multiplied to correct it; carrying that multiply over to this one pushed the white cool
     and left a faint panel showing behind the button's outline.) */
  --plate: #fefefe;
  /* Ground of the product tiles. A second white, and deliberately not --plate: each white
     here is pinned to the asset that sits on it, and these two go through different
     pipelines. The illustrated plate is multiplied down and lands on #fafafa; the product
     frames keep their untouched sweep and stay pure white. Matching them to each other
     rather than to their own images is what puts a visible panel behind the product.
     Measured off the rendered page, not off the file — sampling the asset downscales it
     first and blends the edges in, which reads 2 units low. */
  --tile: #fff;
  --sand: #ebe4dd;
  --dune: #ddd6ce;
  /* Neutral ash for the merchandising tiles. The rest of the palette is warm, which is the
     point: a tan hide sitting on a neutral ground reads warmer than the same hide on a warm
     one. The reference site bakes its own #f5f5f5 into the photography rather than setting a
     background, and at 245 that grey is fainter against white than this page's --paper
     already was — so the value here matches --paper's lightness and only drops the warmth. */
  --ash: #eeeeee;
  /* A second, deeper neutral for tiles that sit on --paper rather than on white. --ash was
     pitched at --paper's own lightness so that switching a white section to grey changed only
     the warmth; put the paper ground back underneath it and that becomes a change of nothing —
     measured 1.007 : 1, which is invisible. --stone drops nine steps and reads. */
  --stone: #e6e6e4;
  --white: #f7f6f4;

  /* ink */
  --ink: #1a1512;
  --body: #6b6259;
  --muted: #948b81;
  --cream: #f2efe9;
  --cream-dim: #b8ada1;

  /* leather, sampled off the product shots */
  --saddle: #8c4b31;
  --obsidian: #2a2724;
  --orange: #c9512f;
  --taupe: #6c4b3a;

  --line: rgba(26, 21, 18, .13);
  --line-strong: rgba(26, 21, 18, .26);
  --line-dark: rgba(242, 239, 233, .18);

  /* Roboto Slab echoes the slab serifs of the UNIDOLLY wordmark itself, so the display face
     and the logo read as one voice. Jost stays for labels, nav and UI. */
  --serif: "Roboto Slab", Rockwell, Georgia, "Times New Roman", serif;
  --sans: "Jost", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --gut: clamp(1.25rem, 4.2vw, 4rem);
  --maxw: 1560px;
  --sec: clamp(4.5rem, 8.5vw, 9rem);
  --hdr-h: 74px;
  --util-h: 34px;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);
}

/* ---------------------------------------------------------------- reset -- */
*, *::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(--sans); font-size: 1rem; line-height: 1.65;
  font-weight: 300; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--saddle); outline-offset: 3px; }
::selection { background: var(--saddle); color: #fff; }

/* ------------------------------------------------------------ typography -- */
/* A bold slab occupies far more of its em box than a light didone, so the scale steps down
   and the tracking tightens — otherwise the same nominal size reads a whole grade larger. */
.d1, .d2, .d3, .d4 { font-family: var(--serif); color: var(--ink); }
.d1 { font-size: clamp(2.35rem, 5.1vw, 4.4rem);  line-height: 1.07; letter-spacing: -.032em; font-weight: 800; }
.d2 { font-size: clamp(1.7rem, 3vw, 2.6rem);     line-height: 1.13; letter-spacing: -.026em; font-weight: 700; }
.d3 { font-size: clamp(1.3rem, 1.95vw, 1.8rem);  line-height: 1.21; letter-spacing: -.02em;  font-weight: 700; }
.d4 { font-size: clamp(1.02rem, 1.2vw, 1.22rem); line-height: 1.34; letter-spacing: -.014em; font-weight: 700; }
/* Roboto Slab has no true italic — emphasis is carried by weight instead of a synthesised slant */
.d1 em, .d2 em, .d3 em { font-style: normal; font-weight: 300; }

.eyebrow {
  font-family: var(--sans); font-size: .6875rem; font-weight: 400;
  letter-spacing: .2em; text-transform: uppercase; color: var(--muted);
}
.lede { font-size: clamp(1rem, 1.15vw, 1.0625rem); line-height: 1.72; color: var(--body); }
.copy { font-size: .9375rem; line-height: 1.78; color: var(--body); }
.copy + .copy { margin-top: 1.1em; }
.meta { font-family: var(--sans); font-size: .6875rem; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }

.on-dark { color: var(--cream); }
.on-dark .d1, .on-dark .d2, .on-dark .d3, .on-dark .d4 { color: var(--cream); }
.on-dark .eyebrow, .on-dark .meta { color: var(--cream-dim); }
.on-dark .copy, .on-dark .lede { color: #cfc5b9; }

/* ---------------------------------------------------------------- layout -- */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gut); }
.wrap--wide { max-width: 1780px; }
.sec { padding-block: var(--sec); }
/* for sections whose own content already carries a lot of vertical air */
.sec--tight { padding-block: clamp(3.25rem, 6vw, 5.5rem); }
.bg-paper { background: var(--paper); }
.bg-plate { background: var(--plate); }
.bg-sand { background: var(--sand); }
.bg-pure { background: #fff; }
.bg-dune { background: var(--dune); }
.bg-espresso { background: var(--espresso); }
.rule { height: 1px; background: var(--line); border: 0; margin: 0; }

/* ------------------------------------------------------------- controls -- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .7rem;
  font-family: var(--sans); font-size: .6875rem; font-weight: 400;
  letter-spacing: .19em; text-transform: uppercase;
  padding: 1.05rem 2.4rem; background: var(--espresso); color: var(--cream);
  border: 1px solid var(--espresso); transition: background .4s var(--ease), color .4s var(--ease);
}
.btn:hover { background: transparent; color: var(--espresso); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-strong); }
.btn--ghost:hover { background: var(--espresso); color: var(--cream); border-color: var(--espresso); }
.btn--light { background: var(--cream); color: var(--espresso); border-color: var(--cream); }
.btn--light:hover { background: transparent; color: var(--cream); }
.btn--block { width: 100%; }
.btn[disabled] { opacity: .45; pointer-events: none; }

/* underlined CTA with a rule that redraws from the left on hover */
.cta {
  display: inline-flex; align-items: center; gap: .85rem; position: relative;
  font-family: var(--sans); font-size: .6875rem; letter-spacing: .19em;
  text-transform: uppercase; padding-bottom: .7rem; color: inherit;
}
.cta::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: currentColor; opacity: .35; transform-origin: right;
  transition: transform .5s var(--ease), opacity .5s var(--ease);
}
.cta:hover::after { opacity: 1; transform: scaleX(1.06); transform-origin: left; }
.cta .arw { transition: transform .5s var(--ease); }
.cta:hover .arw { transform: translateX(5px); }

.arw { width: 18px; height: 8px; flex: none; }
.arw path { stroke: currentColor; stroke-width: 1; fill: none; }

/* ------------------------------------------------------------ utility bar -- */
/* lives inside the fixed header and collapses away once the page starts moving */
.util {
  position: relative; z-index: 60; height: var(--util-h);
  background: var(--espresso-deep); color: var(--cream-dim);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  transition: height .45s var(--ease);
}
.hdr.is-solid .util { height: 0; }
.util__track { position: relative; height: 100%; width: 100%; }
.util__msg {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: .625rem; letter-spacing: .2em; text-transform: uppercase;
  opacity: 0; transform: translateY(6px); transition: opacity .6s var(--ease), transform .6s var(--ease);
  padding-inline: 1rem; text-align: center;
}
.util__msg.is-on { opacity: 1; transform: none; }

/* ---------------------------------------------------------------- header -- */
.hdr {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  transition: transform .5s var(--ease), background .45s var(--ease), color .45s var(--ease);
}
.hdr__in {
  height: var(--hdr-h); display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  padding-inline: var(--gut); position: relative;
}
.hdr__in::after {
  content: ""; position: absolute; left: var(--gut); right: var(--gut); bottom: 0; height: 1px;
  background: var(--line); opacity: 0; transition: opacity .45s var(--ease);
}
.hdr__nav, .hdr__tools { display: flex; align-items: center; gap: clamp(1.1rem, 2.2vw, 2.3rem); }
.hdr__tools { justify-content: flex-end; }
.hdr a, .hdr button { color: inherit; }

/* Nav and tools share the wordmark's family. At 11px a slab's serifs crowd, so they run one
   step lighter than the wordmark's 700 and a little tighter than the sans they replace —
   Roboto Slab sets wider than Jost, and the old .17em tracking pushed the row too long. */
.navlink {
  font-family: var(--serif); font-weight: 500;
  font-size: .7rem; letter-spacing: .13em; text-transform: uppercase;
  position: relative; padding-block: .45rem; white-space: nowrap;
}
.navlink::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: .1rem; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform .45s var(--ease);
}
.navlink:hover::after, .navlink[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }

.wordmark {
  font-family: var(--serif); font-weight: 700; font-size: clamp(.94rem, 1.35vw, 1.16rem);
  letter-spacing: .24em; text-indent: .24em; text-transform: uppercase; white-space: nowrap;
}
.hdr__bag { position: relative; }
.hdr__count { font-variant-numeric: tabular-nums; }

/* transparent over a hero, opaque everywhere else */
/* No rule over a hero — the header floats on the film with nothing drawn under it. The
   hairline only appears once the header goes solid, where it has a job to do. */
.hdr--over { color: #fff; }
/* Reaching for the nav commits the header to its solid state. A transparent bar with an
   opaque panel hanging off it reads as two disconnected things; solid, the header and the
   menu it drops are one surface. focus-within gives keyboard users the same behaviour.
   The solid ground is espresso, not paper, so the type never leaves white — going
   transparent-to-solid is a background change only, with nothing shifting on the letters.
   It sets one step lighter than the utility strip above it, so the two darks read as a
   stack rather than one slab. No hairline: a dark bar separates from the page on its own,
   and a light rule drawn under it shows as a bright seam against the film. */
.hdr.is-solid,
.hdr--over:hover,
.hdr--over:focus-within,
body.mega-open .hdr--over { background: var(--espresso); color: #fff; }
.hdr.is-solid .hdr__in::after { opacity: 0; }
.hdr.is-hidden { transform: translateY(-100%); }
body.no-hero .hdr { background: var(--espresso); color: #fff; }
body.no-hero .util { display: none; }
body.no-hero #main { padding-top: var(--hdr-h); }

.icon-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--serif); font-weight: 500;
  font-size: .7rem; letter-spacing: .13em; text-transform: uppercase;
}
.icon-btn svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 1.1; }
.burger { display: none; }
.burger svg { width: 20px; height: 12px; stroke: currentColor; stroke-width: 1.1; }

/* ------------------------------------------------------------ mega menu -- */
.mega {
  position: absolute; left: 0; right: 0; top: 100%; background: var(--paper); color: var(--ink);
  border-top: 1px solid var(--line); padding: 2.6rem var(--gut) 3rem;
  display: grid; grid-template-columns: repeat(4, 1fr) 1.15fr; gap: 2.5rem;
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity .35s var(--ease), transform .35s var(--ease), visibility .35s;
}
.mega.is-open { opacity: 1; visibility: visible; transform: none; }
/* while the menu is down, the page behind it recedes — the same move the drawers make */
#main::before {
  content: ""; position: fixed; inset: 0; z-index: 30; pointer-events: none;
  background: rgba(20, 15, 11, .34); opacity: 0; visibility: hidden;
  transition: opacity .4s var(--ease), visibility .4s;
}
body.mega-open #main::before { opacity: 1; visibility: visible; }
/* Column heads follow the nav they hang from — same family, same lighter weight. */
.mega__h {
  font-family: var(--serif); font-weight: 500;
  font-size: .64rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 1.15rem;
}
.mega__list li + li { margin-top: .72rem; }
.mega__list a { font-size: .875rem; color: var(--body); transition: color .3s; }
.mega__list a:hover { color: var(--ink); }
.mega__promo img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }
.mega__promo p { margin-top: .8rem; }

/* --------------------------------------------------------------- overlays -- */
.scrim {
  position: fixed; inset: 0; background: rgba(26, 21, 18, .42); z-index: 70;
  opacity: 0; visibility: hidden; transition: opacity .45s var(--ease), visibility .45s;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.scrim.is-open { opacity: 1; visibility: visible; }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(430px, 100%); z-index: 80;
  background: var(--paper); display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform .5s var(--ease); visibility: hidden;
}
.drawer.is-open { transform: none; visibility: visible; }
.drawer__hd { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem 1.75rem; border-bottom: 1px solid var(--line); }
/* The panel title echoes the tool button that opened it. */
.drawer__ttl { font-family: var(--serif); font-weight: 500; font-size: .7rem; letter-spacing: .16em; text-transform: uppercase; }
.drawer__body { flex: 1; overflow-y: auto; padding: 1.5rem 1.75rem; }
.drawer__ft { padding: 1.5rem 1.75rem; border-top: 1px solid var(--line); }
.x { width: 26px; height: 26px; display: grid; place-items: center; }
.x svg { width: 13px; height: 13px; stroke: currentColor; stroke-width: 1.2; }

.line-item { display: grid; grid-template-columns: 74px 1fr auto; gap: 1rem; padding-block: 1.15rem; border-bottom: 1px solid var(--line); }
.line-item img { width: 74px; aspect-ratio: 1; object-fit: cover; background: var(--white); }
.line-item__n { font-family: var(--serif); font-weight: 700; font-size: .95rem; letter-spacing: -.015em; }
.line-item__m { font-size: .75rem; color: var(--muted); margin-top: .2rem; }
.line-item__x { font-size: .6875rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin-top: .5rem; }
.line-item__x:hover { color: var(--ink); }
.empty { text-align: center; padding-block: 3.5rem; color: var(--muted); }
.tot { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 1.15rem; }
.tot span:first-child { font-size: .6875rem; letter-spacing: .18em; text-transform: uppercase; }
.tot span:last-child { font-family: var(--serif); font-weight: 700; font-size: 1.25rem; letter-spacing: -.02em; }

/* search overlay */
.search {
  position: fixed; top: 0; left: 0; right: 0; z-index: 85; background: var(--paper);
  padding: 2.2rem var(--gut) 2.6rem; transform: translateY(-100%);
  transition: transform .5s var(--ease); visibility: hidden;
}
.search.is-open { transform: none; visibility: visible; }
.search__row { display: flex; align-items: center; gap: 1.2rem; border-bottom: 1px solid var(--line-strong); padding-bottom: 1rem; }
.search__row input {
  flex: 1; border: 0; background: none; font-family: var(--serif); font-weight: 300;
  font-size: clamp(1.3rem, 2.6vw, 2rem); letter-spacing: -.02em; padding: 0;
}
.search__row input::placeholder { color: var(--muted); }
.search__row input:focus { outline: none; }
.search__hint { margin-top: 1.2rem; display: flex; gap: 1.4rem; flex-wrap: wrap; }
.search__hint a { font-size: .75rem; color: var(--muted); border-bottom: 1px solid transparent; }
.search__hint a:hover { color: var(--ink); border-color: var(--line-strong); }
.search__res { margin-top: 1.8rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 1.6rem; }
.search__res:empty { display: none; }

/* mobile nav */
.mnav {
  position: fixed; inset: 0 auto 0 0; width: min(400px, 88%); z-index: 80; background: var(--paper);
  transform: translateX(-100%); transition: transform .5s var(--ease); visibility: hidden;
  display: flex; flex-direction: column; padding: 1.5rem 1.75rem 2.5rem;
}
.mnav.is-open { transform: none; visibility: visible; }
.mnav__list { margin-top: 2rem; }
.mnav__list a { display: block; font-family: var(--serif); font-weight: 700; font-size: 1.4rem; letter-spacing: -.02em; padding-block: .75rem; border-bottom: 1px solid var(--line); }
.mnav__sub { margin-top: 1.75rem; }
.mnav__sub a { display: block; font-size: .8125rem; color: var(--body); padding-block: .45rem; }

/* --------------------------------------------------------------- the hero -- */
.hero { position: relative; min-height: 100svh; display: flex; align-items: flex-end; overflow: hidden; }
.hero__bg { position: absolute; inset: 0; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }

/* The brand film sits over its own first frame, so there is no jump when it starts and
   no second image to download. It fades in only once it can actually play; if autoplay is
   refused, or motion is reduced, the poster underneath simply stays. */
.hero__vid {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 1.1s var(--ease);
}
.hero__vid.is-ready { opacity: 1; }
html.nofx .hero__vid { display: none; }
@media (prefers-reduced-motion: reduce) { .hero__vid { display: none; } }
/* Centred type needs a symmetric scrim: the old left-to-right wash was there to protect
   left-aligned text and would now read as an off-centre shadow. */
.hero__bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to top, rgba(18, 13, 10, .78) 0%, rgba(18, 13, 10, .5) 18%, rgba(18, 13, 10, .12) 42%, rgba(18, 13, 10, 0) 62%),
    linear-gradient(to bottom, rgba(18, 13, 10, .46) 0%, rgba(18, 13, 10, 0) 20%),
    radial-gradient(110% 58% at 50% 92%, rgba(18, 13, 10, .42) 0%, rgba(18, 13, 10, 0) 64%);
}
/* The film's subject walks through the lower-middle of frame, so the caption is pushed down
   into the bottom band rather than sitting across the dog. With the line standing alone the
   block is roughly 150px shorter than it was, so the bottom padding grows to take up the
   slack — the headline holds the same low station in the frame instead of floating back up
   into the middle of it. Measured in vh, not rem, so the station holds its proportion of the
   frame rather than creeping upward on a short viewport. */
.hero__in { position: relative; width: 100%; max-width: var(--maxw); margin-inline: auto; padding: 0 var(--gut) clamp(3.5rem, 8.5vh, 6rem); }
.hero__c { max-width: 46rem; margin-inline: auto; text-align: center; color: #fff; }
.hero .d1 { color: #fff; text-shadow: 0 2px 46px rgba(0, 0, 0, .3); }

.hero__sub {
  margin: 1.75rem auto 0; max-width: 33rem;
  font-size: clamp(.9375rem, 1.1vw, 1.0625rem); line-height: 1.66; letter-spacing: .012em;
  color: rgba(255, 255, 255, .86);
}
.hero__cta { margin-top: 2.2rem; display: flex; flex-wrap: wrap; gap: 1.3rem 2.6rem; align-items: center; justify-content: center; }
.hero .eyebrow { color: rgba(255, 255, 255, .74); margin-bottom: 1.35rem; }

/* The film ends on a centred UNIDOLLY card. Rather than let the caption sit across the
   brand mark — a collision that shifts with every viewport ratio — the caption clears out
   just before the card fades in, and returns when the loop restarts. The cue sits outside
   .hero__c and so rides through the card, which is right: it is a property of the page, not
   of the caption. */
.hero__c { transition: opacity .6s var(--ease), transform .6s var(--ease); }
.hero__c.is-away { opacity: 0; transform: translateY(14px); pointer-events: none; }

/* short hero for inner pages */
.phero { position: relative; min-height: clamp(360px, 52vh, 560px); display: flex; align-items: center; overflow: hidden; }
.phero__bg { position: absolute; inset: 0; }
.phero__bg img { width: 100%; height: 100%; object-fit: cover; }
.phero__bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to right, rgba(20, 15, 11, .66) 0%, rgba(20, 15, 11, .2) 62%, rgba(20, 15, 11, .05) 100%),
              linear-gradient(to bottom, rgba(20, 15, 11, .4) 0%, rgba(20, 15, 11, 0) 30%);
}
.phero__in { position: relative; width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gut); padding-top: var(--hdr-h); }
.phero__c { max-width: 38rem; color: #fff; }
.phero .d1, .phero .d2 { color: #fff; }
.phero .eyebrow { color: rgba(255, 255, 255, .72); margin-bottom: 1.1rem; }
.phero__sub { margin-top: 1.2rem; color: rgba(255, 255, 255, .82); font-size: clamp(.9375rem, 1.1vw, 1.0625rem); line-height: 1.68; max-width: 26rem; }

/* ------------------------------------------------------- collection band -- */
/* An illustrated ivory band that breaks the run of photography between the film and the
   product row. The plate carries line-drawn straps at its left and right edges, so the
   type sits in the clear middle at every width — object-fit:cover pushes the drawings
   further out as the viewport widens rather than crowding the words. */
/* The artwork is edge decoration — a D-ring at the top-left corner and a long strap down
   the right third. Stretched across the whole chapter with object-fit:cover it would be the
   first thing cropped away, so it ships as two pieces pinned to the left and right edges,
   each scaling to the chapter's height. The middle stays clear for the content, and the
   pieces' white ground is multiplied to the same #fafafa as the section and the product
   tiles, so there is no visible join. */
.band { position: relative; background: var(--plate); overflow: hidden; }
/* The plate is 3:1 and the band is about 2.9:1 at desktop, so filling it costs a few per
   cent of stretch and keeps the whole drawing. Below 1024 the band turns nearly square and
   the same fill would stretch the strap 2x into a smear — the artwork is dropped there and
   the band reads as clean white, which suits a phone better anyway. */
.band__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: fill; }
@media (max-width: 1023px) { .band__bg { display: none; } }
.band__in {
  position: relative; z-index: 1; max-width: 48rem; margin-inline: auto;
  padding: clamp(3.5rem, 8.5vw, 6.5rem) var(--gut); text-align: center;
}
.band__eyebrow { display: flex; align-items: center; justify-content: center; gap: clamp(.9rem, 2vw, 1.5rem); }
.band__eyebrow::before, .band__eyebrow::after {
  content: ""; height: 1px; flex: 0 1 clamp(1.5rem, 6vw, 4.5rem); background: currentColor; opacity: .45;
}
.band__t {
  font-family: var(--serif); font-weight: 700; text-transform: uppercase;
  font-size: clamp(1.7rem, 4vw, 3.15rem); line-height: 1.08; letter-spacing: .012em;
  color: var(--ink); margin-top: 1.35rem;
}
.band__s { font-family: var(--serif); font-weight: 300; font-size: clamp(.95rem, 1.15vw, 1.1rem); color: var(--body); margin-top: 1.1rem; }
.band .btn-cut { margin-top: 2.2rem; }

/* chamfered outline button — drawn as a clipped fill with a clipped inner knocked out of it,
   which keeps the 45° corners crisp at any width without an SVG */
.btn-cut {
  --cut: 9px;
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  padding: 1.05rem 2.5rem; background: var(--ink); color: var(--ink);
  clip-path: polygon(var(--cut) 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% calc(100% - var(--cut)),
                     calc(100% - var(--cut)) 100%, var(--cut) 100%, 0 calc(100% - var(--cut)), 0 var(--cut));
  transition: color .4s var(--ease);
}
.btn-cut::before {
  content: ""; position: absolute; inset: 1px; background: var(--plate);
  clip-path: polygon(var(--cut) 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% calc(100% - var(--cut)),
                     calc(100% - var(--cut)) 100%, var(--cut) 100%, 0 calc(100% - var(--cut)), 0 var(--cut));
  transition: background .4s var(--ease);
}
.btn-cut span {
  position: relative; display: inline-flex; align-items: center; gap: .85rem;
  font-family: var(--sans); font-size: .6875rem; font-weight: 400;
  letter-spacing: .19em; text-transform: uppercase; white-space: nowrap;
}
.btn-cut:hover { color: var(--plate); }
.btn-cut:hover::before { background: var(--ink); }
.btn-cut .arw { transition: transform .45s var(--ease); }
.btn-cut:hover .arw { transform: translateX(5px); }

/* --------------------------------------------------------- section header -- */
/* the aside runs a shade wider than before: a bold slab sets wider than a light serif, and
   the two-line section headings were breaking to three */
.sechd { display: grid; grid-template-columns: minmax(0, 25rem) minmax(0, 1fr); gap: clamp(2rem, 4.5vw, 5rem); align-items: start; }
.sechd__aside .eyebrow { display: block; margin-bottom: 1.5rem; }
.sechd__aside .copy { margin-top: 1.4rem; max-width: 24rem; }
.sechd__aside .cta { margin-top: 2rem; }

/* ------------------------------------------------------------- the system -- */
.sys { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1rem, 2.2vw, 2.2rem); }
.sysitem { text-align: center; }
/* transparent, not --paper: the row takes whatever ground its section is on */
.sysitem__ph { position: relative; overflow: hidden; }
.sysitem__ph img { width: 100%; aspect-ratio: 1; object-fit: contain; transition: transform .8s var(--ease); }
.sysitem:hover .sysitem__ph img { transform: scale(1.055); }
.sysitem__n { font-family: var(--serif); font-weight: 700; font-size: 1.12rem; letter-spacing: -.02em; margin-top: .6rem; }
.sysitem__s { font-size: .8125rem; color: var(--muted); margin-top: .1rem; }
.sysitem__p { font-size: .8125rem; margin-top: .45rem; font-variant-numeric: tabular-nums; }
.sysitem__i { font-family: var(--sans); font-size: .625rem; letter-spacing: .18em; color: var(--muted); }

/* 2x2 bordered cards, to the client's reference build. Sampled from it: the card is a
   hairline box with NO fill — the section's ground reads straight through, which is exactly
   why the tiles must stay multiply-tinted to that same ground. Name and swatches sit below
   the box; no price, no sub-label. */
/* Section ornament: a hand-drawn dog mark with a rule either side.
   Three things keep the rules from reading as machine parts bolted to a drawing —
   they fade out at their outer ends instead of stopping dead, they sit close enough to the
   mark to read as one gesture (the artwork's own gap is about 1% of its width), and they
   are dropped to the height of the ground the dogs stand on rather than the mark's centre.
   Ink #8c6e57 is sampled from the artwork's own strokes. */
.orn {
  display: flex; align-items: center; justify-content: center;
  /* no CSS gap: the mark's own transparent margin already leaves about the same breathing
     space the artwork has between its line and the dogs, and it scales with the mark */
  gap: 0;
  max-width: clamp(20rem, 58vw, 48rem);
  margin: clamp(-2.75rem, -4vw, -1rem) auto clamp(2.5rem, 4.6vw, 4rem);
}
.orn__rule {
  flex: 1; height: 1px; position: relative; top: clamp(2px, .35vw, 5px);
  transform: scaleX(0); transition: transform 1.25s var(--ease) .1s;
}
.orn__rule--l {
  background: linear-gradient(to right, rgba(140, 110, 87, 0), rgba(140, 110, 87, .72) 52%, rgba(140, 110, 87, .82));
  transform-origin: right;
}
.orn__rule--r {
  background: linear-gradient(to left, rgba(140, 110, 87, 0), rgba(140, 110, 87, .72) 52%, rgba(140, 110, 87, .82));
  transform-origin: left;
}
.orn.is-in .orn__rule { transform: scaleX(1); }
.orn__mark { flex: none; width: clamp(100px, 10vw, 144px); height: auto; }
html.nofx .orn__rule { transform: scaleX(1) !important; transition: none !important; }
@media (prefers-reduced-motion: reduce) { .orn__rule { transform: scaleX(1) !important; } }

/* Section masthead for a full-width row: eyebrow, then the heading with its CTA set against
   it on the same baseline, then the supporting line. Left-aligned on purpose — the band
   directly above is centred, and two centred blocks running together read as a stutter. */
.rowhd { margin-bottom: clamp(1.6rem, 3.2vw, 2.6rem); text-align: center; }

/* Four across at full width gives ~310px cards — the same size the client's reference build
   uses. Squeezed into the old two-column section they would have been ~195px, too small for
   a bordered box to hold a product with any air around it. */


/* Campaign plate. The pair runs at the 1600 x 850 the client asked for, matted on white
   rather than bled to the window: the source frames are 1642px wide, so 1600 is all but
   native. The matte is uniform on all four sides until the plate caps out, at which point the
   page gives it more room left and right — a centred plate, not a band with a gap in it, and
   wider at the sides than top and bottom to echo the plate's own landscape proportion. The
   white runs straight on into the statement below, so `.showband + .stmt` pays the gap once. */
.showband {
  background: #fff;
  padding: clamp(2rem, 4vw, 4rem) clamp(2rem, 6.5vw, 7rem);
}
/* 16:9, which is what the two films are shot at (1920x1080 on the client masters). A still
   survives a crop and a film does not, so the panel takes the footage's shape at every width,
   phones included. */
.showcase { max-width: 1600px; margin-inline: auto; aspect-ratio: 16 / 9; background: #fff; }

/* Each frame is a poster with its film over it. The poster is the film's own first frame, so
   there is nothing to jump from, and a visitor who never gets the video is left looking at the
   right picture rather than a hole. */
.filmpair { position: relative; overflow: hidden; isolation: isolate; }
.filmpair__f { position: absolute; inset: 0; opacity: 0; transition: opacity 1.1s var(--ease); }
.filmpair__f.is-on { opacity: 1; }
.filmpair__f img, .filmpair__v { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.filmpair__v { opacity: 0; transition: opacity .6s var(--ease); }
.filmpair__v.is-ready { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .filmpair__f { transition: none; }
  .filmpair__v { display: none; }
}
.fig-slides__ticks {
  position: absolute; z-index: 2; display: flex; gap: .5rem;
  right: clamp(1rem, 2vw, 1.9rem); bottom: clamp(1rem, 2vw, 1.9rem);
}
.fig-slides__ticks span { width: 34px; height: 2px; background: rgba(255, 255, 255, .3); overflow: hidden; }
.fig-slides__ticks i { display: block; height: 100%; width: 0; background: rgba(255, 255, 255, .92); }
html.nofx .fig-slides__ticks span.is-on i { width: 100%; }
@media (prefers-reduced-motion: reduce) { .fig-slides__ticks span.is-on i { width: 100%; } }

/* House statement. Pure white ground, both lines in the wordmark's slab — heading at 700, the
   line under it at 300, so the pair reads as one voice at two weights rather than two faces. */
.stmt { background: #fff; color: var(--ink); padding: clamp(4rem, 8vw, 7.5rem) var(--gut); }
/* Straight after the plate the two whites are one field, so the plate's bottom matte already
   supplies half the gap — pay the top padding once, not twice. */
.showband + .stmt { padding-top: clamp(2.5rem, 5vw, 4.5rem); }
/* The three lines stack in a single grid cell, so the block stands as tall as the longest and
   nothing below it moves as they change. */
.stmt__in { max-width: 46rem; margin-inline: auto; text-align: center; display: grid; }

/* ---- the words rise when the block is scrolled to -------------------------- */
/* The block itself no longer fades — .rv is neutralised here and the entrance is carried by
   the type instead. Two entrances on one element (a block fading up while its words rise
   inside it) read as a stutter, not as emphasis. */
.stmt__in.rv, .stmt__in.rv.is-in { opacity: 1; transform: none; }
/* The mask needs room for descenders — "companionship" has a p — so it is padded below and
   pulled back by the same amount, which keeps the baseline where the layout put it. */
.stmt .rise {
  display: inline-block; overflow: hidden; vertical-align: bottom;
  padding-bottom: .16em; margin-bottom: -.16em;
}
.stmt .rise > i {
  display: inline-block; font-style: normal;
  transform: translateY(115%);
  transition: transform .85s var(--ease);
  transition-delay: calc(var(--i, 0) * .065s);
}
.stmt__in.is-in .rise > i { transform: none; }
/* The sub follows the last word rather than arriving with the first. */
.stmt__in .stmt__s { opacity: 0; transform: translateY(12px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.stmt__in.is-in .stmt__s { opacity: 1; transform: none; transition-delay: .52s; }

@media (prefers-reduced-motion: reduce) {
  .stmt .rise > i { transform: none; transition: none; }
  .stmt__in .stmt__s, .stmt__in.is-in .stmt__s { opacity: 1; transform: none; transition: none; }
}
html.nofx .stmt__in .stmt__s { opacity: 1 !important; transform: none !important; }
.stmt__slide {
  grid-area: 1 / 1; align-self: center; pointer-events: none;
  opacity: 0; transform: translateY(9px);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
/* The incoming line waits until the outgoing one is nearly gone: two sets of letterforms at
   half opacity ghost where two photographs would have blended. */
.stmt__slide.is-on {
  opacity: 1; transform: none; pointer-events: auto;
  transition: opacity .65s var(--ease) .42s, transform .8s var(--ease) .42s;
}
.stmt__s {
  font-family: var(--serif); font-weight: 300; color: var(--ink);
  font-size: clamp(1rem, 1.3vw, 1.15rem); line-height: 1.68;
  margin-top: clamp(1.1rem, 2vw, 1.6rem);
}

/* ------------------------------------------------------------ split bands -- */
.split { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; }
.split--l3 { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.split--r3 { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.split__fig { position: relative; overflow: hidden; min-height: clamp(320px, 46vw, 640px); }
.split__fig img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.split__pad { display: flex; flex-direction: column; justify-content: center; padding: clamp(2.75rem, 6vw, 6rem) clamp(1.5rem, 5vw, 5.5rem); }
.split__pad .eyebrow { margin-bottom: 1.5rem; }
.split__pad .copy { margin-top: 1.5rem; max-width: 30rem; }
.split__pad .cta, .split__pad .btn { margin-top: 2.2rem; align-self: flex-start; }

/* --------------------------------------------------------- numbered strip -- */
/* walk.html's system strip: an intro cell followed by the four pieces, divided by hairlines.
   RECONSTRUCTED — see the note in README under "Deleted and restored". The column count is
   read back off the markup (intro + four items) and the rule side off the breakpoint override
   that resets `border-left` and swaps in `border-top`. */
.strip { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); border-block: 1px solid var(--line); }
.strip > * { border-left: 1px solid var(--line); padding: clamp(1.4rem, 2.4vw, 2.2rem) clamp(.9rem, 1.7vw, 1.5rem); }
.strip > *:first-child { border-left: 0; }
.strip__intro { display: flex; flex-direction: column; justify-content: center; }
.strip__intro .cta { margin-top: 1.5rem; align-self: flex-start; }

/* --------------------------------------------------------------- editorial -- */
.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.25rem, 2.6vw, 2.4rem); }
.card__ph { overflow: hidden; background: var(--dune); }
.card__ph img { width: 100%; aspect-ratio: 4/3; object-fit: cover; transition: transform 1s var(--ease); }
.card:hover .card__ph img { transform: scale(1.045); }
.card__hd { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin-top: 1.1rem; }
.card__t { font-family: var(--serif); font-weight: 700; font-size: clamp(1.08rem, 1.32vw, 1.28rem); line-height: 1.26; letter-spacing: -.022em; margin-top: .55rem; }
.card__x { font-size: .875rem; color: var(--body); margin-top: .55rem; max-width: 27rem; }
.card .cta { margin-top: 1.15rem; }
.card--tall .card__ph img { aspect-ratio: 3/4; }

/* ------------------------------------------------------------ product row -- */
.pgrid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1rem, 1.8vw, 1.6rem); }
.pgcard { position: relative; display: block; text-align: center; padding-bottom: 1.3rem; }
/* --ash on white, the same pairing the merchandising bands use, and no border: a tile that
   already reads against the ground does not need a rule drawn round it, and four framed
   rectangles in a row is exactly the look this page keeps being pulled away from.
   The frames were re-rendered for the grey from the card masters (all sixteen measured pure
   #ffffff) through the site's multiply pipeline, at their own pixel size — those masters top
   out at 404px and upscaling would only bake in the softness. */
.pgcard__ph { position: relative; background: var(--stone); overflow: hidden; }
/* Square. 10:9 was chosen to stop a square banking dead space above and below pieces that are
   mostly wider than tall — true of the frame, but it left the row reading as four slightly
   squashed boxes rather than a set. A square is the formal proportion, it matches the
   merchandising cards further down, and the padding below is cut back so the pieces come out
   no smaller than they were in the shorter frame. */
.pgcard__ph::before { content: ""; display: block; padding-top: 100%; }
/* the four colourways are stacked and cross-faded, so switching is instant with no reflow */
.pgcard__ph img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
  padding: clamp(.5rem, 1.15vw, .95rem);
  opacity: 0; transition: opacity .5s var(--ease), transform .85s var(--ease);
}
.pgcard__ph img.is-on { opacity: 1; }
.pgcard:hover .pgcard__ph img.is-on { transform: scale(1.045); }
.pgcard__n {
  font-family: var(--serif); font-weight: 400; font-size: clamp(1.2rem, 1.65vw, 1.55rem);
  letter-spacing: -.012em; color: var(--ink); margin-top: .9rem;
}
/* The unconfirmed-price note. Deliberately quiet and deliberately present: it is a status,
   not a promotion, so it sits under the figure in the muted label size rather than shouting —
   but it has to be visible enough that nobody signs off a number by accident. Driven by
   `provisionalPrice` in the PRODUCTS data, so it disappears the moment a price is confirmed. */
.prov {
  display: block; margin-top: .28rem;
  font-family: var(--sans); font-size: .625rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}

.pgcard__p { font-family: var(--sans); font-size: .8125rem; letter-spacing: .04em; color: var(--body); margin-top: .3rem; }

/* ------------------------------------------------------- system header -- */
/* Heading left, tone picker right, on one line — a section header bar rather than a heading
   centred over a grid with nothing beside it. */
.syshd__t { max-width: none; }
.syshd { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1.5rem clamp(2rem, 4vw, 4rem); margin-bottom: clamp(2rem, 3.6vw, 3.2rem); }
/* Swatches only, with the tone named once beside them rather than four times across the row.
   Four dot-and-label pairs ran nearly 500px and read as a set of radio buttons; the swatches
   alone come to about a third of that, and the name still gets said — which matters here more
   than most places, because two of the four are tans that a red-green deficiency collapses
   into each other. The square and the ring are the same marks the merchandising cards use, so
   the page has one vocabulary for colour rather than two. */
.tonepick__row { display: flex; align-items: center; gap: clamp(.35rem, .8vw, .6rem); }
.tonepick__b { display: block; padding: 7px; line-height: 0; }
.tonepick__b i {
  display: block; width: 18px; height: 18px; background: var(--sw);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18);
  outline: 1px solid transparent; outline-offset: 3px;
  transition: outline-color .35s var(--ease);
}
.tonepick__b:hover i { outline-color: var(--line-strong); }
.tonepick__b.is-on i { outline-color: var(--ink); }
/* Fixed measure so the swatches never shift as the name changes length — "Heritage Orange" is
   two and a half times "Taupe". */
.tonepick__n {
  min-width: 9.5rem; margin-left: clamp(.6rem, 1.2vw, 1rem);
  font-family: var(--serif); font-weight: 700; font-size: 1.02rem;
  letter-spacing: -.012em; color: var(--ink); white-space: nowrap;
}

/* --------------------------------------------------------------- journal -- */
/* Four stories as one band of panels. Hovering a panel opens it and compresses the rest; only
   the open one carries a title, a standfirst and a link, which is what keeps the row from
   closing on four identical READ stubs.

   Entirely CSS. `flex-grow` carries the width, `:hover` on the row cancels the resting panel,
   and `:focus-within` does the same for the keyboard — no script, so there is nothing to jank
   and nothing to fail.

   Ground is white, matching the two merchandising bands above it, so the lower half of the
   page reads as one continuous field with the photography doing all of the work. */
.jr { background: #fff; text-align: center; }
.jr__hd {
  margin: 0 0 clamp(2rem, 3.4vw, 3rem);
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(1.2rem, 1.85vw, 1.65rem); line-height: 1.2;
  letter-spacing: .2em; text-indent: .1em;      /* half the tracking — see .merch__hd */
  text-transform: uppercase; color: var(--ink); text-align: center;
}

.jr__panels { display: flex; gap: 6px; height: clamp(26rem, 43vw, 37rem); text-align: left; }
.jr__p {
  position: relative; flex: 1 1 0; min-width: 0; overflow: hidden;
  background: var(--dune); color: #fff;
  transition: flex-grow .75s var(--ease);
}
.jr__p img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* A bottom wash, not a flat scrim: the panels run over a bright pavement in one frame and
   black leather in another, and only a gradient holds white type on both without dulling the
   picture it sits on. Same construction as the hero's. */
.jr__p::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
    rgba(18, 13, 10, .84) 0%, rgba(18, 13, 10, .56) 20%,
    rgba(18, 13, 10, .28) 40%, rgba(18, 13, 10, 0) 66%);
}
.jr__c {
  position: absolute; z-index: 1; left: 0; right: 0; bottom: 0;
  display: block; padding: clamp(1.1rem, 1.9vw, 1.75rem);
}
/* Full white, not 80%, and one step up in size. At .6875rem in 80% white this washed out
   entirely on the tan frame, which is the one mid-tone picture in the row — a gradient can
   hold type over black leather and over a bright pavement, but not over a colour sitting at
   the same value as the type. The shadow is the cheap insurance the hero caption already uses. */
.jr__k {
  display: block; font-size: .75rem; letter-spacing: .16em; color: #fff;
  text-shadow: 0 1px 12px rgba(18, 13, 10, .55);
}
.jr__t {
  display: block; margin-top: .4rem; font-family: var(--serif); font-weight: 700;
  font-size: clamp(1.22rem, 1.62vw, 1.58rem); line-height: 1.18; letter-spacing: -.022em;
  text-shadow: 0 1px 16px rgba(18, 13, 10, .6);
}
/* Title, standfirst and link belong to the open panel only, and on a closed panel they must
   take up no room at all. Hiding them on opacity alone left them occupying their full height
   behind the category — and since the four titles and standfirsts are different lengths, each
   category was pushed up by a different amount and the row of labels sat at four different
   heights. `grid-template-rows: 0fr -> 1fr` collapses them properly, so the labels line up and
   the block unfolds upward off the bottom edge as a panel opens. */
.jr__rev { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .62s var(--ease); }
.jr__revin { overflow: hidden; min-height: 0; }
.jr__t, .jr__x, .jr__go { opacity: 0; transition: opacity .42s var(--ease); }
/* 15px in full white, not 13px at 84%. Over a photograph the standfirst has none of the help
   it gets on paper — no fixed ground behind it, and the brightest part of this frame is the
   orange leather sitting directly under the last third of the line. */
.jr__x {
  display: block; margin-top: .55rem; max-width: 28rem;
  font-size: .9375rem; line-height: 1.62; color: #fff;
  text-shadow: 0 1px 14px rgba(18, 13, 10, .6);
}
.jr__go {
  display: inline-block; position: relative; margin-top: .85rem; padding-bottom: .28rem;
  font-family: var(--sans); font-size: .75rem; letter-spacing: .19em; text-transform: uppercase;
  color: #fff; text-shadow: 0 1px 14px rgba(18, 13, 10, .6);
}
.jr__go::after { content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%; background: currentColor; opacity: .9; }

/* open at rest, cancelled the moment the row is touched or tabbed into */
.jr__p.is-on { flex-grow: 2.6; }
.jr__p.is-on .jr__rev { grid-template-rows: 1fr; }
.jr__p.is-on .jr__t, .jr__p.is-on .jr__x, .jr__p.is-on .jr__go { opacity: 1; transition-delay: .14s; }
.jr__panels:hover .jr__p.is-on,
.jr__panels:focus-within .jr__p.is-on { flex-grow: 1; }
.jr__panels:hover .jr__p.is-on:not(:hover) .jr__rev { grid-template-rows: 0fr; }
.jr__panels:hover .jr__p.is-on:not(:hover) .jr__t,
.jr__panels:hover .jr__p.is-on:not(:hover) .jr__x,
.jr__panels:hover .jr__p.is-on:not(:hover) .jr__go { opacity: 0; transition-delay: 0s; }
.jr__panels .jr__p:hover,
.jr__panels .jr__p:focus-visible { flex-grow: 2.6; }
.jr__p:hover .jr__rev, .jr__p:focus-visible .jr__rev { grid-template-rows: 1fr; }
.jr__p:hover .jr__t, .jr__p:hover .jr__x, .jr__p:hover .jr__go,
.jr__p:focus-visible .jr__t, .jr__p:focus-visible .jr__x, .jr__p:focus-visible .jr__go { opacity: 1; transition-delay: .14s; }

/* The section closes on a fill, not on a rule. No border at rest, and on hover a wash of
   --espresso runs left to right across it — --espresso is the footer's ground, so the last
   thing on the page resolves into the first thing under it.
   The fill and the label are clipped on the same curve and the same duration, which is why the
   label is set twice: sweeping a background under a line that recolours all at once reads as
   two unrelated events; clipped together, each letter turns as the edge reaches it.
   inline-grid, not grid: a block-level grid container fills the row and `min-width` cannot pull
   it back, which stretched the fill across the whole wrap. */
.jr__all {
  display: inline-grid; place-items: center; position: relative; overflow: hidden;
  min-width: min(22rem, 84vw); padding: 1.15rem 2.6rem;
  margin: clamp(2.6rem, 4.4vw, 3.6rem) 0 0;
  font-family: var(--serif); font-weight: 700;
  font-size: .8125rem; letter-spacing: .2em; text-indent: .1em; text-transform: uppercase;
  color: var(--ink);
}
.jr__all::before {
  content: ""; position: absolute; inset: 0; background: var(--espresso);
  clip-path: inset(0 100% 0 0);
  transition: clip-path .62s var(--ease);
}
.jr__lbl { grid-area: 1 / 1; position: relative; white-space: nowrap; }
.jr__lbl--on { color: var(--cream); clip-path: inset(0 100% 0 0); transition: clip-path .62s var(--ease); }
.jr__all:hover::before, .jr__all:hover .jr__lbl--on,
.jr__all:focus-visible::before, .jr__all:focus-visible .jr__lbl--on { clip-path: inset(0 0 0 0); }

/* Nothing to hover: four equal panels with every title standing, which is the honest form of
   this on a phone or a tablet. */
@media (hover: none) {
  .jr__p, .jr__p.is-on { flex-grow: 1; }
  .jr__rev, .jr__p.is-on .jr__rev { grid-template-rows: 1fr; }
  .jr__t, .jr__x, .jr__go { opacity: 1; }
}
@media (max-width: 1023px) {
  .jr__panels { flex-direction: column; height: auto; gap: 10px; }
  .jr__p { flex: none; aspect-ratio: 16 / 10; }
  .jr__p, .jr__p.is-on { flex-grow: 0; }
  .jr__rev, .jr__p.is-on .jr__rev { grid-template-rows: 1fr; }
  .jr__t, .jr__x, .jr__go { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .jr__p, .jr__rev, .jr__t, .jr__x, .jr__go { transition: none; }
  .jr__all::before, .jr__lbl--on { transition: none; }
}

/* ------------------------------------------------------------ merch bands -- */
/* A 2x2 of pieces against one large photograph, mirrored between the two bands so the page
   alternates instead of repeating.

   Three rows of geometry matter here, and the first build got all three wrong:
   - The label heads the section. It sits in its own grid row above both columns, which is
     where the reference puts it — not centred inside the pad, where it lands below the top of
     the photograph and stops reading as the section's title at all.
   - The photograph starts level with the first tile, not at the section's top edge. That
     shared top line is the thing that was "not aligned": a picture bleeding to the top while
     the goods beside it began 200px lower.
   - The row height is driven by the grid, and the figure stretches to match. Giving the figure
     its own min-height made it the taller of the two, and the pad then centred its contents
     inside the leftover — which is where the band of dead white above "Marks & Accessories"
     came from.

   White ground with --paper tiles, the inverse of the reference's grey-on-white. It has to be
   this way round here: every product frame on this site is multiplied to --paper so that white
   maps to the tile exactly, so --paper is the only tile colour that leaves no panel edge. */
.merch {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  column-gap: clamp(1.5rem, 4vw, 4rem);
  align-items: stretch;
  background: #fff;
  padding-block: clamp(3rem, 5.5vw, 5.5rem);
}
/* the goods column carries the outer gutter; the photograph runs to the window edge */
.merch__hd  { grid-row: 1; grid-column: 1; padding-left: clamp(1.5rem, 4.5vw, 5rem); }
.merch__pad { grid-row: 2; grid-column: 1; padding-left: clamp(1.5rem, 4.5vw, 5rem); }
.merch__fig { grid-row: 2; grid-column: 2; position: relative; overflow: hidden; margin: 0; min-height: 0; }
.merch--flip .merch__hd,
.merch--flip .merch__pad { grid-column: 2; padding-left: 0; padding-right: clamp(1.5rem, 4.5vw, 5rem); }
.merch--flip .merch__fig { grid-column: 1; }
.merch__fig img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ---- the band assembles as it is scrolled into place -------------------------- */
/* Entering the viewport the photograph is full-bleed across the whole section and the goods
   sit centred on top of it; scrolling resolves both back to the side-by-side layout above.
   Everything here is additive and only applied once site.js has measured the resting
   geometry and added .is-live — with no script, and under reduced motion, the band renders
   in its finished state and never moves. --p defaults to 1 for exactly that reason.

   The figure is taken out of flow and clipped rather than resized: the row's height is
   already driven by the grid beside it, so removing the figure from the flow costs nothing,
   and interpolating a clip is the only way to grow a photograph to full-bleed without
   scaling it and losing the framing.

   The veil is what makes the overlap legible. Names, swatches and SHOP are --ink on a
   photograph that is bright in one band and a dark interior in the other; a white wash that
   lifts as the picture retreats lets the type hold in both, and reads as the photograph
   coming into focus rather than as a scrim someone had to add. */
.merch.is-live { position: relative; }
/* The photograph is the top layer and the goods sit under it, so the band is not "grid over
   picture" but a picture drawing back off the goods. That ordering pays for itself twice: the
   reveal is a stronger move than an overlap, and nothing is ever read through the photograph,
   which retires the white veil this needed when the layering ran the other way — names,
   swatches and SHOP are --ink, and one band's picture is bright while the other's is a dark
   interior, so no single wash suited both. */
.merch.is-live .merch__fig {
  position: absolute; inset: 0; z-index: 2; grid-area: auto;
  will-change: clip-path;
}
/* The picture slides as the clip closes, so the frame that is left at rest is the middle of
   the photograph rather than whichever edge the window happened to land on. Without it the
   band that ends on the left kept the arm, the cup and the bag, and lost the dog off the far
   side of the clip. */
.merch.is-live .merch__fig img {
  transform: translateX(calc(var(--imgx, 0px) * var(--p, 0)));
  will-change: transform;
}
.merch.is-live .merch__hd,
.merch.is-live .merch__pad {
  position: relative; z-index: 1;   /* under the photograph, uncovered as it retreats */
  transform: translateX(calc(var(--shift, 0px) * (1 - var(--p, 1))));
}


/* The band titles are set in the wordmark's own face and treatment: Roboto Slab 700,
   uppercase, tracked, with `text-indent` matching the tracking. That indent is the wordmark's
   trick and it is not optional here — tracked type carries a trailing letter-space after its
   last character, so centred text sits fractionally left of true centre until the same amount
   is added back at the front.
   Tracking eases from the wordmark's .24em to .2em because this runs at roughly half again
   its size, and letter-spacing that reads as air at 18px reads as a gap at 27px.
   A section label at 14px in the UI sans was the reference's own value, but it made these
   read as filing tabs on somebody else's shelf rather than as the house speaking. */
.merch__hd {
  margin: 0 0 clamp(1.6rem, 2.8vw, 2.4rem);
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(1.2rem, 1.85vw, 1.65rem); line-height: 1.2;
  letter-spacing: .2em; text-indent: .1em;
  text-transform: uppercase; color: var(--ink); text-align: center;
}
.merch__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 3vw, 2.75rem) clamp(1rem, 2.2vw, 2rem); }

.mcard { text-align: center; }
.mcard__link { display: block; }
.mcard__ph { position: relative; display: block; overflow: hidden; background: var(--ash); }
.mcard__ph::before { content: ""; display: block; padding-top: 100%; }
.mcard__ph img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain;
  padding: clamp(.9rem, 2.2vw, 1.9rem); transition: transform .9s var(--ease);
}
.mcard:hover .mcard__ph img { transform: scale(1.05); }
/* The name carries this layout, so it is set at display scale rather than as a caption. The
   reference runs its product titles at 30px against a 2x2; this lands in the same place. */
.mcard__n {
  display: block; margin-top: clamp(.9rem, 1.6vw, 1.25rem);
  font-family: var(--serif); font-weight: 400; color: var(--ink);
  font-size: clamp(1.38rem, 2.15vw, 2.05rem); line-height: 1.14; letter-spacing: -.022em;
}

/* The tones, as real links rather than an ornament: each one carries &c= through to the
   product page, which preselects that colourway on arrival. That is the only version worth
   shipping — a row of chips that merely looks pressable is the same mistake as the "Preview"
   button that used to sit in the personalisation panel.
   The square is 12px but its anchor is padded out to a 24px target, because a 12px hit area
   is not one. The ring marks the tone actually showing in the tile above. */
.mcard__tones { display: flex; justify-content: center; gap: .1rem; margin-top: .7rem; }
.mcard__tones a { display: block; padding: 6px; line-height: 0; }
.mcard__tones i {
  display: block; width: 12px; height: 12px; background: var(--sw);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .2);
  outline: 1px solid transparent; outline-offset: 2px;
  transition: outline-color .35s var(--ease);
}
.mcard__tones a:hover i { outline-color: var(--line-strong); }
.mcard__tones .is-on i { outline-color: var(--ink); }

.mcard__go {
  display: inline-block; position: relative; margin-top: .55rem; padding-bottom: .3rem;
  font-family: var(--sans); font-size: .6875rem; letter-spacing: .19em;
  text-transform: uppercase; color: var(--body);
}
.mcard__go::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: currentColor; opacity: .75; transform-origin: right;
  transition: transform .45s var(--ease), opacity .45s var(--ease);
}
.mcard:hover .mcard__go::after { opacity: 1; transform: scaleX(1.08); transform-origin: left; }

/* The typographic fourth cell. It takes the tile's footprint so the 2x2 stays square, and
   sets its line at the same scale as a product name so it reads as a peer of the three
   beside it rather than as a button that wandered into the grid. */
.mcard--all .mcard__allt {
  display: grid; place-items: center; text-align: center;
  aspect-ratio: 1; background: var(--ash); padding: 1rem;
  font-family: var(--serif); font-weight: 700; color: var(--ink);
  font-size: clamp(1.42rem, 2.25vw, 2.15rem); line-height: 1.12; letter-spacing: -.026em;
}
.mcard--all .mcard__go { margin-top: clamp(.9rem, 1.6vw, 1.25rem); }

@media (max-width: 1023px) {
  /* One column: label, photograph, then the goods — the photograph keeps its place between
     the title and the grid rather than being pushed above the title by an `order` flip. */
  .merch, .merch--flip { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; }
  .merch__hd, .merch--flip .merch__hd { grid-row: 1; grid-column: 1; padding-inline: clamp(1.25rem, 4vw, 3rem); }
  .merch__fig, .merch--flip .merch__fig { grid-row: 2; grid-column: 1; aspect-ratio: 4 / 3; }
  .merch__pad, .merch--flip .merch__pad { grid-row: 3; grid-column: 1; padding-inline: clamp(1.25rem, 4vw, 3rem); padding-top: clamp(1.75rem, 4vw, 2.5rem); }
}

/* ------------------------------------------------------------ four tones -- */
.tones { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(.75rem, 1.6vw, 1.5rem); }
.tone { text-align: left; width: 100%; }
.tone__ph { overflow: hidden; position: relative; }
.tone__ph img { width: 100%; aspect-ratio: 3/4; object-fit: cover; transition: transform .9s var(--ease); }
.tone:hover .tone__ph img { transform: scale(1.06); }
.tone__r { display: flex; align-items: center; gap: .6rem; margin-top: .95rem; }
.dot { width: 11px; height: 11px; border-radius: 50%; flex: none; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .18); }
.tone__n { font-size: .8125rem; letter-spacing: .04em; }

/* colour swatch row on cards */
.swatches { display: flex; gap: .4rem; margin-top: .6rem; justify-content: center; }
.swatches .dot { width: 9px; height: 9px; }

/* --------------------------------------------------------------- marks/USP -- */
.marks { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.25rem, 2.4vw, 2.2rem); margin-top: 2.6rem; }
.mark svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: .9; }
.mark h4 { font-size: .8125rem; font-weight: 400; margin-top: .8rem; }
.mark p { font-size: .8125rem; color: var(--muted); margin-top: .25rem; }

/* ---------------------------------------------------------------- product -- */
.pgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(1.25rem, 2.4vw, 2.2rem) clamp(1rem, 2vw, 1.8rem); }
.pcard { position: relative; }
.pcard__ph { position: relative; overflow: hidden; background: var(--paper); }
.pcard__ph img { width: 100%; aspect-ratio: 1; object-fit: contain; transition: transform .85s var(--ease), opacity .5s var(--ease); }
.pcard:hover .pcard__ph img { transform: scale(1.05); }
.pcard__n { font-family: var(--serif); font-weight: 700; font-size: 1.05rem; letter-spacing: -.02em; margin-top: .85rem; }
.pcard__s { font-size: .8125rem; color: var(--muted); margin-top: .1rem; }
.pcard__p { font-size: .8125rem; margin-top: .45rem; font-variant-numeric: tabular-nums; }
.pcard__tag {
  position: absolute; top: .9rem; left: .9rem; z-index: 2; background: var(--espresso); color: var(--cream);
  font-size: .5625rem; letter-spacing: .16em; text-transform: uppercase; padding: .32rem .6rem;
}
.wish {
  position: absolute; top: .7rem; right: .7rem; z-index: 3; width: 34px; height: 34px;
  display: grid; place-items: center; opacity: 0; transition: opacity .35s var(--ease);
}
.wish svg { width: 16px; height: 16px; stroke: var(--ink); fill: none; stroke-width: 1.1; transition: fill .3s, stroke .3s; }
.pcard:hover .wish, .wish:focus-visible { opacity: 1; }
.wish.is-on { opacity: 1; }
.wish.is-on svg { fill: var(--saddle); stroke: var(--saddle); }
.qadd {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  background: rgba(38, 29, 21, .93); color: var(--cream);
  font-size: .625rem; letter-spacing: .18em; text-transform: uppercase; padding: .95rem;
  transform: translateY(100%); transition: transform .4s var(--ease); text-align: center;
}
.pcard:hover .qadd { transform: none; }
@media (hover: none) {
  .wish { opacity: 1; }
  .qadd { display: none; }
}

/* toolbar: filters + sort */
.tools { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; padding-block: 1.35rem; border-bottom: 1px solid var(--line); }
.chips { display: flex; gap: clamp(.9rem, 1.8vw, 1.7rem); flex-wrap: wrap; align-items: center; }
.chip {
  font-size: .75rem; color: var(--muted); position: relative; padding-bottom: .3rem; white-space: nowrap;
  transition: color .3s;
}
.chip::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: currentColor; transform: scaleX(0); transform-origin: right; transition: transform .4s var(--ease); }
.chip:hover { color: var(--ink); }
.chip.is-on { color: var(--ink); }
.chip.is-on::after, .chip:hover::after { transform: scaleX(1); transform-origin: left; }
.sortby { position: relative; }
.sortby__btn { display: inline-flex; align-items: center; gap: .55rem; font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase; }
.sortby__btn svg { width: 9px; height: 6px; stroke: currentColor; fill: none; stroke-width: 1.2; transition: transform .35s var(--ease); }
.sortby.is-open .sortby__btn svg { transform: rotate(180deg); }
.sortby__menu {
  position: absolute; right: 0; top: calc(100% + .7rem); z-index: 20; background: var(--paper);
  border: 1px solid var(--line); min-width: 200px; padding: .5rem 0;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
}
.sortby.is-open .sortby__menu { opacity: 1; visibility: visible; transform: none; }
.sortby__menu button { display: block; width: 100%; text-align: left; padding: .6rem 1.15rem; font-size: .8125rem; color: var(--body); }
.sortby__menu button:hover, .sortby__menu button.is-on { background: var(--sand); color: var(--ink); }
.count { font-size: .75rem; color: var(--muted); }

/* -------------------------------------------------------------------- PDP -- */
.crumb { font-size: .6875rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); padding-block: 1.4rem; }
.crumb a:hover { color: var(--ink); }
.crumb span { margin-inline: .5rem; }

.pdp { display: grid; grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 5rem); align-items: start; }
.gal { display: grid; grid-template-columns: 76px 1fr; gap: 1rem; }
.gal__thumbs { display: flex; flex-direction: column; gap: .6rem; }
.gal__thumbs button { border: 1px solid transparent; transition: border-color .3s; background: var(--paper); }
.gal__thumbs button.is-on { border-color: var(--line-strong); }
.gal__thumbs img { width: 100%; aspect-ratio: 1; object-fit: contain; }
.gal__main { position: relative; overflow: hidden; background: var(--paper); }
.gal__main img { width: 100%; aspect-ratio: 1; object-fit: contain; transition: transform .5s var(--ease), opacity .35s var(--ease); }
.gal__main.is-zoom img { transform: scale(1.9); }

.buy { position: sticky; top: calc(var(--hdr-h) + 1.5rem); }
.buy__price { font-family: var(--serif); font-weight: 700; font-size: 1.45rem; letter-spacing: -.02em; margin-top: .9rem; }
.buy__x { margin-top: 1.4rem; }
.opt { margin-top: 2.2rem; }
.opt__hd { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .9rem; }
.opt__hd span:first-child { font-size: .6875rem; letter-spacing: .18em; text-transform: uppercase; }
.opt__hd span:last-child, .opt__hd button { font-size: .75rem; color: var(--muted); }
.opt__hd button:hover { color: var(--ink); }
.opt__colours { display: flex; gap: .75rem; }
.swatch { width: 34px; height: 34px; border-radius: 50%; position: relative; display: grid; place-items: center; }
.swatch i { width: 26px; height: 26px; border-radius: 50%; display: block; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .2); }
.swatch::after { content: ""; position: absolute; inset: 0; border-radius: 50%; border: 1px solid transparent; transition: border-color .3s; }
.swatch.is-on::after { border-color: var(--ink); }
.opt__sizes { display: grid; grid-template-columns: repeat(auto-fit, minmax(64px, 1fr)); gap: .5rem; }
.size { border: 1px solid var(--line-strong); padding: .8rem .4rem; font-size: .75rem; letter-spacing: .1em; text-align: center; transition: background .3s, color .3s, border-color .3s; }
.size:hover { border-color: var(--ink); }
.size.is-on { background: var(--espresso); color: var(--cream); border-color: var(--espresso); }

.engrave { margin-top: 2.2rem; }
.engrave__in { display: flex; border: 1px solid var(--line-strong); }
.engrave__in input { flex: 1; border: 0; background: none; padding: .95rem 1.1rem; font-size: .875rem; letter-spacing: .1em; text-transform: uppercase; }
.engrave__in input:focus { outline: none; }
.engrave__in span { display: grid; place-items: center; padding-inline: 1rem; font-size: .6875rem; color: var(--muted); border-left: 1px solid var(--line); }
.engrave__note { font-size: .75rem; color: var(--muted); margin-top: .6rem; }
/* live preview: the name is drawn over the real tag photograph */
.tagprev { position: relative; width: 100%; max-width: 300px; margin-inline: auto; }
.tagprev img { width: 100%; }
.tagprev__t {
  position: absolute; left: 50%; top: 58%; transform: translate(-50%, -50%);
  font-family: var(--serif); font-weight: 700; letter-spacing: .11em; text-transform: uppercase;
  color: rgba(255, 246, 232, .93); font-size: clamp(1rem, 4.6cqw, 1.6rem);
  text-shadow: 0 1px 1px rgba(60, 30, 10, .45); white-space: nowrap; pointer-events: none;
}
.tagprev { container-type: inline-size; }

.acc { margin-top: 2.6rem; border-top: 1px solid var(--line); }
.acc__i { border-bottom: 1px solid var(--line); }
.acc__b { display: flex; justify-content: space-between; align-items: center; width: 100%; padding: 1.25rem 0; font-size: .75rem; letter-spacing: .14em; text-transform: uppercase; text-align: left; }
.acc__b svg { width: 11px; height: 11px; stroke: currentColor; stroke-width: 1.1; fill: none; flex: none; transition: transform .4s var(--ease); }
.acc__i.is-open .acc__b svg { transform: rotate(45deg); }
.acc__p { max-height: 0; overflow: hidden; transition: max-height .5s var(--ease); }
.acc__i.is-open .acc__p { max-height: 52rem; }
.acc__p > div { padding-bottom: 1.4rem; }
.acc__p .meta { display: block; margin-top: 1.15rem; margin-bottom: .3rem; color: var(--ink); }
.acc__p .meta:first-child { margin-top: 0; }
.acc__p a { text-decoration: underline; text-underline-offset: 2px; }

/* quantity stepper — the client's PDP has one */
.qty { display: inline-flex; align-items: center; border: 1px solid var(--line-strong); }
.qty button { width: 44px; height: 46px; display: grid; place-items: center; font-size: 1rem; color: var(--body); transition: color .3s; }
.qty button:hover { color: var(--ink); }
.qty input { width: 48px; height: 46px; border: 0; background: none; text-align: center; font-size: .875rem; font-variant-numeric: tabular-nums; }
.qty input:focus { outline: none; }

/* colour swatches show the actual leather, as in the client's product page */
.swatch i { background-size: cover; background-position: center; }

.stickybuy {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 45; background: var(--paper);
  border-top: 1px solid var(--line); padding: .85rem var(--gut);
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  transform: translateY(100%); transition: transform .45s var(--ease);
}
.stickybuy.is-on { transform: none; }
.stickybuy__l { display: flex; align-items: center; gap: 1rem; min-width: 0; }
.stickybuy img { width: 46px; height: 46px; object-fit: contain; background: var(--white); flex: none; }
.stickybuy__n { font-family: var(--serif); font-weight: 700; font-size: .95rem; letter-spacing: -.015em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stickybuy__m { font-size: .75rem; color: var(--muted); }

/* size finder */
.finder__row { display: grid; grid-template-columns: 1fr auto auto; gap: 1rem; align-items: end; }
.field label { display: block; font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); margin-bottom: .5rem; }
.field input, .field select { width: 100%; border: 1px solid var(--line-strong); background: none; padding: .85rem 1rem; font-size: .875rem; }
.field input:focus, .field select:focus { outline: none; border-color: var(--ink); }
.finder__out { margin-top: 1.5rem; padding: 1.15rem 1.35rem; background: var(--sand); font-size: .875rem; }
.finder__out:empty { display: none; }
.finder__out strong { font-family: var(--serif); font-size: 1.08rem; font-weight: 800; letter-spacing: -.015em; }
.sizetable { width: 100%; border-collapse: collapse; margin-top: 1.5rem; font-size: .8125rem; }
.sizetable th, .sizetable td { text-align: left; padding: .7rem .5rem; border-bottom: 1px solid var(--line); }
.sizetable th { font-family: var(--sans); font-weight: 400; font-size: .6875rem; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.sizetable tr.is-on td { background: var(--sand); }

/* ---------------------------------------------------------------- article -- */
.art { max-width: 44rem; margin-inline: auto; }
/* long-form copy runs at the light end of the same family — a slab at 300 is a comfortable
   reading face, and it keeps the site to two families */
.art p { font-family: var(--serif); font-weight: 300; font-size: 1.0625rem; line-height: 1.82; letter-spacing: -.003em; color: #4a423b; }
.art p + p { margin-top: 1.5rem; }
.art h2 { font-family: var(--serif); font-weight: 700; font-size: clamp(1.3rem, 1.9vw, 1.7rem); line-height: 1.22; letter-spacing: -.024em; margin-top: 3rem; margin-bottom: 1.1rem; }
.art figure { margin-block: 3rem; }
.art figure img { width: 100%; }
.art figcaption { font-size: .75rem; color: var(--muted); margin-top: .75rem; }
.pull {
  margin-block: 3rem; padding-left: 1.75rem; border-left: 1px solid var(--saddle);
  font-family: var(--serif); font-weight: 700; font-size: clamp(1.15rem, 1.7vw, 1.5rem);
  line-height: 1.38; letter-spacing: -.024em; color: var(--ink);
}
.artmeta { display: flex; gap: 1.5rem; align-items: center; justify-content: center; margin-bottom: 2.5rem; }

/* --------------------------------------------------------- information -- */
[id] { scroll-margin-top: calc(var(--hdr-h) + var(--util-h) + 1rem); }
.info { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: clamp(2rem, 6vw, 6rem); align-items: start; }
.info__nav { position: sticky; top: calc(var(--hdr-h) + 2rem); }
.info__nav p { margin-bottom: 1.1rem; }
.info__nav a { display: block; font-size: .8125rem; color: var(--body); padding-block: .42rem; transition: color .3s; }
.info__nav a:hover { color: var(--ink); }
.info__sec + .info__sec { margin-top: clamp(2.75rem, 5vw, 4.5rem); padding-top: clamp(2.75rem, 5vw, 4.5rem); border-top: 1px solid var(--line); }
.info__sec h2 { font-family: var(--serif); font-weight: 700; font-size: clamp(1.3rem, 1.9vw, 1.7rem); line-height: 1.18; letter-spacing: -.024em; margin-bottom: 1.1rem; }
.info__sec h3 { font-size: .8125rem; font-weight: 400; letter-spacing: .06em; margin-top: 1.6rem; margin-bottom: .4rem; }
.info__sec .copy { max-width: 42rem; }
.info__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem 2.5rem; margin-top: 1.6rem; }
@media (max-width: 1023px) {
  .info { grid-template-columns: 1fr; }
  .info__nav { position: static; display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--line); }
  .info__nav p { width: 100%; margin-bottom: .4rem; }
  .info__grid { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------- footer -- */
.ft { background: var(--espresso); color: var(--cream-dim); padding-block: clamp(3rem, 6vw, 5rem) 2rem; }

/* signature strip — the client's footer opens with the mark, the house line and the sign-up */
.ft__lockup {
  display: grid; grid-template-columns: auto 1fr minmax(0, 420px); gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: center; padding-bottom: clamp(2rem, 4vw, 3rem); border-bottom: 1px solid var(--line-dark);
}
.ft__lockup img { width: 86px; }
.ft__tag { font-size: .5625rem; letter-spacing: .22em; text-transform: uppercase; color: var(--cream); }
.ft__motto { font-family: var(--serif); font-weight: 700; font-size: .95rem; letter-spacing: -.015em; color: #a99e93; margin-top: .3rem; }

/* Four columns, not three: help and legal are separate lists now, which is what pulls the
   footer level — no column runs three times the height of the ones beside it any more. */
.ft__top { display: grid; grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr)); gap: clamp(1.75rem, 3.4vw, 3.75rem); margin-top: clamp(2rem, 4vw, 3rem); }
.ft__about { font-size: .8125rem; line-height: 1.72; color: #a99e93; max-width: 26rem; }
.ft__about + .ft__about { margin-top: .9rem; }

/* House line, set large at the foot of the About column. That column still runs shorter than
   the lists beside it, so the line is pushed to the bottom of the row rather than left
   hanging under the paragraphs — it finishes the column against the end of the lists and
   gives the footer a corner to stand on.
   Light over bold is the house device, the same one the display scale uses for emphasis: it
   builds to the word that matters instead of leading with it, and needs no second face. */
.ft__top > div:first-child { display: flex; flex-direction: column; }
.ft__stmt {
  margin-top: auto; padding-top: clamp(2.25rem, 5vw, 4.5rem);
  font-family: var(--serif); font-weight: 700;
  font-size: clamp(1.85rem, 3.5vw, 3.2rem); line-height: .99; letter-spacing: -.035em;
  color: var(--cream);
}
.ft__stmt em { font-style: normal; font-weight: 300; color: #a99e93; }
/* stacked, there is no tall column to fall to and the big line needs its own air instead */
@media (max-width: 1023px) {
  .ft__stmt { padding-top: clamp(1.75rem, 4vw, 2.5rem); padding-bottom: .5rem; }
}
.ft__h { font-size: .625rem; letter-spacing: .2em; text-transform: uppercase; color: var(--cream); margin-bottom: 1.2rem; }
.ft__l li + li { margin-top: .62rem; }
.ft__l a { font-size: .8125rem; color: #a99e93; transition: color .3s; }
.ft__l a:hover { color: var(--cream); }
.ft__form { display: flex; }
.ft__form input {
  flex: 1; min-width: 0; border: 1px solid var(--line-dark); border-right: 0; background: none;
  color: var(--cream); padding: .85rem 1rem; font-size: .6875rem; letter-spacing: .14em; text-transform: uppercase;
}
.ft__form input::placeholder { color: #7d7268; }
.ft__form input:focus { outline: none; border-color: var(--cream-dim); }
.ft__form button {
  background: var(--cream); color: var(--espresso); padding-inline: 1.7rem;
  font-size: .625rem; letter-spacing: .18em; text-transform: uppercase; white-space: nowrap;
  transition: background .35s var(--ease), color .35s var(--ease);
}
.ft__form button:hover { background: transparent; color: var(--cream); box-shadow: inset 0 0 0 1px var(--cream); }
.ft__ok { font-size: .75rem; color: #9c8f6f; margin-top: .7rem; min-height: 1.1rem; }
.ft__soc { display: flex; gap: 1.15rem; margin-top: 1.75rem; }
.ft__soc a { font-size: .6875rem; letter-spacing: .14em; text-transform: uppercase; color: #a99e93; }
.ft__soc a:hover { color: var(--cream); }
/* Everything in the bottom bar runs off the left rail. Pushed apart, the badges sat alone
   against the right gutter with most of a screen of nothing between them and the email. */
/* Legal left, payment right. Packed to the left the two sat against each other with the whole
   right half of the bar empty, which read as a row that had failed to fill rather than as a
   composed footer line. */
.ft__bot { display: flex; justify-content: space-between; align-items: center; gap: 1.1rem clamp(1.75rem, 4vw, 3.5rem); flex-wrap: wrap; margin-top: clamp(2.5rem, 5vw, 4rem); padding-top: 1.6rem; border-top: 1px solid var(--line-dark); }
.ft__bot, .ft__bot a { font-size: .6875rem; color: #7d7268; }
.ft__bot a:hover { color: var(--cream); }
.ft__meta { display: flex; gap: .5rem 1.5rem; flex-wrap: wrap; align-items: baseline; }

/* Accepted payment methods. Drawn in-house rather than pasted in as artwork: the marks are
   set in the site's own sans on a light chip, with real geometry only where the geometry is
   the brand (Mastercard's two discs, Apple's silhouette). One chip size and one colour pair
   throughout, so the row reads as a house treatment rather than nine mismatched logos.
   NOTE: these are stand-ins. Before launch, drop in each network's official SVG — Visa,
   Mastercard, Amex and PayPal all publish brand kits, and Apple Pay / Google Pay mandate
   their own artwork. Swapping them is contained to this block and the <ul class="pay">. */
.pay { display: flex; flex-wrap: wrap; gap: .34rem; margin: 0; padding: 0; list-style: none; }
.pay__c {
  display: inline-flex; align-items: center; justify-content: center; gap: .13rem;
  width: 42px; height: 27px; border-radius: 3px;
  background: rgba(242, 239, 233, .88); color: #241c15;
}
.pay__t { font-family: var(--sans); font-weight: 700; font-size: 9px; line-height: 1; letter-spacing: .03em; }
/* Visa's mark leans; the others sit upright. The skew is the one cue that survives at 9px. */
.pay__t--visa { font-size: 10.5px; letter-spacing: .01em; transform: skewX(-9deg); }
.pay__t--amex { font-size: 8.5px; letter-spacing: 0; }
.pay__t--pp   { font-size: 9px;   letter-spacing: -.015em; }
.pay__t--gg   { font-size: 11px;  letter-spacing: 0; }
.pay__t--pay  { font-weight: 500; }
/* The two drawn marks run larger than the wordmarks: a disc pair and a silhouette need more
   of the chip than letterforms do, or they shrink to specks against their neighbours. */
.pay__g { display: block; width: auto; fill: #241c15; }
.pay__g--mc { height: 16px; }
/* second disc lighter, so the overlap reads as the third tone the real pair has in mono */
.pay__g--mc circle + circle { opacity: .5; }
.pay__g--ap { height: 13px; margin-right: 1.5px; }


/* back to top */
.totop {
  position: fixed; right: var(--gut); bottom: 2rem; z-index: 40; width: 42px; height: 42px;
  border: 1px solid var(--line-strong); background: var(--paper); display: grid; place-items: center;
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .4s var(--ease), transform .4s var(--ease), visibility .4s, background .3s, color .3s;
}
.totop.is-on { opacity: 1; visibility: visible; transform: none; }
/* Stood down once the footer is on screen. It is `position: fixed`, so at the bottom of the
   page it lands exactly on the payment row now that the row has moved right — and a button
   that covers the thing under it is worse than no button. The footer carries its own way back
   up in the nav anyway. */
.totop.is-off { opacity: 0; visibility: hidden; transform: translateY(8px); pointer-events: none; }
.totop:hover { background: var(--espresso); color: var(--cream); border-color: var(--espresso); }
.totop svg { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 1.2; }

/* toast */
.toast {
  position: fixed; left: 50%; bottom: 2.2rem; z-index: 90; transform: translate(-50%, 20px);
  background: var(--espresso); color: var(--cream); padding: .9rem 1.6rem;
  font-size: .6875rem; letter-spacing: .16em; text-transform: uppercase;
  opacity: 0; visibility: hidden; transition: opacity .4s var(--ease), transform .4s var(--ease), visibility .4s;
}
.toast.is-on { opacity: 1; visibility: visible; transform: translate(-50%, 0); }

/* --------------------------------------------------------------- reveals -- */
/* Only ever applied to content that starts below the fold. A failsafe in site.js
   force-reveals anything still hidden after 2.5s, so a missed IntersectionObserver
   can never leave a section permanently invisible. */
.rv { opacity: 0; transform: translateY(16px); }
.js .rv { transition: opacity .9s var(--ease), transform .9s var(--ease); }
.rv.is-in { opacity: 1; transform: none; }
.rv-d1 { transition-delay: .08s; }
.rv-d2 { transition-delay: .16s; }
.rv-d3 { transition-delay: .24s; }
.rv-d4 { transition-delay: .32s; }
html.nofx .rv, html.nofx .rv.is-in { opacity: 1 !important; transform: none !important; transition: none !important; }
html.nofx * { animation: none !important; }
/* ?shot — pins viewport-relative heights so a full-page capture in a very tall
   window still shows the hero at a realistic size. Self-check only. */
html.shot .hero { min-height: 820px; }
/* the plate is sized by its own aspect ratio now, so it needs no pinning here */
html.shot .phero { min-height: 460px; }
html.shot .hdr { position: absolute; }   /* still overlays the hero, but does not follow the capture */
html.shot .buy { position: static; }     /* sticky -> static, NOT absolute: absolute drops it out of the grid */
html.shot .totop, html.shot .stickybuy { display: none; }

@media (prefers-reduced-motion: reduce) {
  .rv, .rv.is-in { opacity: 1 !important; transform: none !important; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
}

.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.skip { position: fixed; top: 0; left: 0; z-index: 200; background: var(--espresso); color: var(--cream); padding: .8rem 1.4rem; font-size: .75rem; transform: translateY(-120%); }
.skip:focus { transform: none; }

/* ==========================================================================
   breakpoints
   ========================================================================== */
@media (max-width: 1180px) {
  .mega { grid-template-columns: repeat(3, 1fr); }
  .mega__promo { display: none; }
  .strip { grid-template-columns: repeat(2, 1fr); }
  .strip > * { border-left: 0 !important; border-top: 1px solid var(--line); }
  .pgrid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 1023px) {
  :root { --hdr-h: 62px; }
  .hdr__in { grid-template-columns: 1fr auto 1fr; }
  .hdr__nav .navlink, .hdr__tools .icon-btn span { display: none; }
  .burger { display: inline-flex; }
  .mega { display: none !important; }
  .sechd { grid-template-columns: 1fr; gap: 2.2rem; }
  .split, .split--l3, .split--r3 { grid-template-columns: 1fr; }
  .split__fig { min-height: 58vw; }
  .split--flip .split__fig { order: -1; }
  .cards { grid-template-columns: 1fr 1fr; }
  .pgrid4 { grid-template-columns: 1fr 1fr; gap: clamp(1.6rem, 3.2vw, 2.5rem) 1.1rem; }
  .sys { grid-template-columns: repeat(2, 1fr); gap: 2rem 1.25rem; }
  .tones { grid-template-columns: repeat(2, 1fr); }
  .pdp { grid-template-columns: 1fr; }
  .buy { position: static; }
  .gal { grid-template-columns: 1fr; }
  .gal__thumbs { flex-direction: row; order: 2; overflow-x: auto; }
  .gal__thumbs button { flex: 0 0 68px; }
  .nlband { grid-template-columns: 1fr; text-align: center; justify-items: center; }
  .nlband__f { max-width: 100%; }
  .ft__top { grid-template-columns: 1fr 1fr; }
  .ft__top > *:first-child { grid-column: 1 / -1; }
  .ft__lockup { grid-template-columns: auto 1fr; }
  .ft__lockup .ft__form { grid-column: 1 / -1; }
  .marks { grid-template-columns: 1fr; gap: 1.4rem; }
}

@media (max-width: 719px) {
  .hero { min-height: 92svh; }
  .hero__c { max-width: none; }
  .cards { grid-template-columns: 1fr; }
  .pgrid { grid-template-columns: 1fr 1fr; gap: 2rem 1rem; }
  .sys { grid-template-columns: 1fr 1fr; }
  .strip { grid-template-columns: 1fr; }
  .tones { grid-template-columns: 1fr 1fr; }
  .ft__top { grid-template-columns: 1fr; }
  .tools { gap: .9rem; }
  .chips { gap: .9rem; }
  .finder__row { grid-template-columns: 1fr; }
  .totop { display: none; }
  .stickybuy__m { display: none; }
  .art p { font-size: 1.0625rem; }
}
