/* ==========================================================================
   b.lo.c studio
   Two paths, one entry. DIVE DEEPER is the gallery scroll; SHOP is a
   conventional storefront. Same data, same product page, same inquiry.
   SHOP is faster, not louder — type, color and restraint carry across.

   The page takes its color from the photograph in front of you: --tone and
   --ink are interpolated from the selects against scroll position (js/site.js).
   Type: Labor Union carries the labels, Gambetta the reading voice.
   ========================================================================== */

/* --- reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol { margin: 0; padding: 0; }
ul, ol { list-style: none; }
img { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

/* --- faces ---------------------------------------------------------------- */
/* Single-weight files are declared across a range so the browser serves the
   real file at every weight the site asks for, rather than faking a bold. */
@font-face {
  font-family: "Labor Union";
  src: url("../fonts/woff2/LaborUnion-Small.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* Gambetta carries the reading voice: Light for running text, Regular for the
   display lines, Medium for the interview questions. */
@font-face {
  font-family: "Gambetta";
  src: url("../fonts/woff2/Gambetta-Light.woff2") format("woff2");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Gambetta";
  src: url("../fonts/woff2/Gambetta-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Gambetta";
  src: url("../fonts/woff2/Gambetta-LightItalic.woff2") format("woff2");
  font-weight: 300; font-style: italic; font-display: swap;
}
@font-face {
  font-family: "Gambetta";
  src: url("../fonts/woff2/Gambetta-Medium.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}

/* --- tokens --------------------------------------------------------------- */
:root {
  --tone: #E5EFDD;
  --ink: #383F33;
  --ink-soft: #585F52;
  --ink-rgb: 56, 63, 51;

  --ui: "Labor Union", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --sans: "Gambetta", "Iowan Old Style", Palatino, Georgia, serif;
  --serif: "Gambetta", "Iowan Old Style", Palatino, Georgia, serif;

  --masthead-h: 5.5rem;   /* until the script measures the real one */
  --vh-frame: calc(100svh - var(--masthead-h));

  --gutter: clamp(1.25rem, 4.5vw, 5rem);
  --measure: 33rem;
  --rule: rgba(var(--ink-rgb), .16);
  --rule-faint: rgba(var(--ink-rgb), .09);

  --fs-collection: clamp(2.4rem, 7vw, 6rem);
  --fs-display: clamp(1.6rem, 3.2vw, 2.7rem);
  --fs-lede: clamp(1.1rem, 1.7vw, 1.45rem);
  --fs-body: clamp(.95rem, 1vw, 1.05rem);
  --fs-micro: clamp(.62rem, .72vw, .72rem);

  --ease: cubic-bezier(.22, .61, .36, 1);
  --slow: cubic-bezier(.16, .84, .28, 1);
}

/* --- base ----------------------------------------------------------------- */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  background: var(--tone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  font-weight: 300;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  padding-top: var(--masthead-h);
  transition: background-color .5s linear, color .5s linear;
}
body.is-locked { overflow: hidden; }

::selection { background: rgba(var(--ink-rgb), .16); }
:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* --- type roles ----------------------------------------------------------- */
.collection-name {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--fs-collection);
  line-height: .98;
  letter-spacing: -.025em;
}
.display {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--fs-display);
  line-height: 1.16;
  letter-spacing: -.012em;
}
.label {
  font-family: var(--ui);
  font-weight: 500;
  font-size: var(--fs-micro);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color .5s linear;
}
.lede { font-size: var(--fs-lede); font-weight: 300; line-height: 1.5; max-width: 30ch; }
.prose { max-width: var(--measure); font-weight: 300; }
.prose p + p { margin-top: 1.3em; }
.serial {
  font-family: var(--ui);
  font-weight: 400;
  font-size: var(--fs-micro);
  letter-spacing: .16em;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  transition: color .5s linear;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; top: .5rem; left: .5rem; z-index: 300;
  padding: .6rem 1rem; background: var(--ink); color: var(--tone);
  font-size: var(--fs-micro); letter-spacing: .2em; text-transform: uppercase;
  transform: translateY(-250%);
}
.skip-link:focus { transform: none; }

/* --- masthead ------------------------------------------------------------- */
.masthead {
  position: fixed; inset: 0 0 auto 0; z-index: 90;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
  padding: clamp(.9rem, 2vw, 1.5rem) var(--gutter);
  background: var(--tone);
  border-bottom: 1px solid var(--rule);
  transition: background-color .45s var(--ease), border-color .45s var(--ease);
}
.masthead--clear { background: transparent; border-bottom-color: transparent; }

/* The mark carries two colours rather than one, so it is drawn rather than
   stencilled: the letterforms take the page's ink and stay legible from the
   palest surface tone to the deepest, while the circle takes the average
   colour of the photograph the page is standing in. Custom properties reach
   through <use> into the symbol, which a class selector could not. */
.mark-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Both fills are set on the root by the scroll painter; these are what the
   mark wears before the script has had its first frame. */
:root { --mark-ink: var(--ink-soft); --mark-fill: var(--mean, var(--ink-soft)); }
/* The bar takes its height from the mark plus its padding, so sizing the mark
   up carries the bar with it and the space around it is untouched. */
.brand { display: block; width: clamp(46px, 5vw, 60px); }
.brand[data-brand="foot"] { width: clamp(56px, 7vw, 72px); }
.brand__mark {
  display: block; width: 100%; height: auto;
  aspect-ratio: 1 / 1;
  /* The ground moves under the mark as the page turns over; the fills follow
     it at the same pace rather than snapping. */
  transition: color .5s linear;
}
.brand__mark path, .brand__mark circle { transition: fill .5s linear; }

.nav { display: flex; align-items: center; gap: clamp(.9rem, 2.2vw, 2.1rem); }
.nav a {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: .25em;
  border-bottom: 1px solid transparent;
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.nav a:hover, .nav a:focus-visible { color: var(--ink); }
.nav a[aria-current="true"], .nav a[aria-current="page"] { color: var(--ink); border-bottom-color: currentColor; }

/* The crossing between the two paths sits apart from the section links. */
.nav__cross {
  margin-left: clamp(.4rem, 1.4vw, 1rem);
  padding: .7em 1.2em;
  border: 1px solid var(--rule);
  color: var(--ink);
  transition: background-color .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease);
}
.nav__cross:hover, .nav__cross:focus-visible { background: var(--ink); color: var(--tone); border-color: var(--ink); }

.nav__toggle { display: none; }

/* The cart, sitting in the bar itself rather than inside the menu. Only ever
   shown where the menu has to be opened to reach anything: on a wide screen
   the nav is already on display and carries its own cart link, and two would
   be one too many. */
.masthead__cart { display: none; }
.masthead__cart[hidden] { display: none; }

.masthead--invert .brand { background-color: #fff; }
.masthead--invert .nav a { color: rgba(255, 255, 255, .78); }
.masthead--invert .nav a:hover,
.masthead--invert .nav a:focus-visible,
.masthead--invert .nav a[aria-current="true"] { color: #fff; }
.masthead--invert .nav__cross { color: #fff; border-color: rgba(255, 255, 255, .4); }
.masthead--invert .nav__toggle { color: #fff; }

/* --- layout --------------------------------------------------------------- */
.shell { width: 100%; max-width: 90rem; margin-inline: auto; padding-inline: var(--gutter); }
.shell--narrow { max-width: 68rem; }
.section { padding-block: clamp(5rem, 15vh, 11rem); }
.section__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem; padding-bottom: 1.2rem;
  margin-bottom: clamp(2.5rem, 6vw, 4.5rem);
  border-bottom: 1px solid var(--rule);
}

/* ==========================================================================
   Dive in — the shared entry
   ========================================================================== */
.dive { position: relative; }
.dive__stage {
  position: sticky; top: 0; height: 100svh; overflow: hidden;
  /* Work dissolves as it leaves the top rather than sliding under the nav,
     which keeps the masthead readable against whatever is passing. */
  --edge: clamp(64px, 9vh, 104px);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--edge));
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--edge));
}

.drift {
  position: absolute;
  width: var(--w, 20vw);
  will-change: transform, opacity;
  cursor: pointer;
  background: rgba(var(--ink-rgb), .04);
}
.drift img {
  width: 100%; height: auto; display: block;
  box-shadow: 0 clamp(6px, 1.2vw, 20px) clamp(18px, 3.4vw, 52px) rgba(0, 0, 0, .17);
}
.drift::after {
  content: ""; position: absolute; inset: 0;
  outline: 1px solid transparent; outline-offset: 6px;
  transition: outline-color .3s var(--ease);
}
.drift:hover::after, .drift:focus-visible::after { outline-color: rgba(var(--ink-rgb), .35); }

/* The opening lines, held on landing. */
.intro-lede {
  position: absolute; z-index: 6;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(90vw, 42rem);
  text-align: center;
  pointer-events: none;
  will-change: opacity, transform;
}
.intro-lede p {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.9vw, 3rem);
  line-height: 1.3;
  letter-spacing: -.018em;
  text-shadow: var(--copy-halo);
}

/* A halo in the page's own tone: invisible against the background, but it
   holds the copy off whatever image happens to drift beneath it. */
:root { --copy-halo: 0 0 22px var(--tone), 0 0 8px var(--tone); }

/* The rest of the sentence, revealed a fragment at a time within the
   assortment. Positioned by JS from each fragment's data attributes. */
.intro-frags { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
.frag {
  position: absolute;
  transform: translate(-50%, -50%);
  max-width: min(78vw, 24rem);
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.15rem, 2.7vw, 2.15rem);
  line-height: 1.28;
  letter-spacing: -.014em;
  text-wrap: balance;
  opacity: 0;
  will-change: opacity, transform;
  text-shadow: var(--copy-halo);
}

.dive__cue {
  position: fixed; left: 50%; bottom: clamp(1.5rem, 4vh, 2.6rem);
  transform: translateX(-50%); z-index: 20;
  display: flex; flex-direction: column; align-items: center; gap: .7em;
  transition: opacity .6s var(--ease);
}
.dive__cue::after {
  content: ""; width: 1px; height: 2.4em;
  background: linear-gradient(to bottom, currentColor, transparent);
  animation: cue 2.8s var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: scaleY(0); transform-origin: top; opacity: 0; }
  35%  { transform: scaleY(1); transform-origin: top; opacity: 1; }
  70%  { transform: scaleY(1); transform-origin: bottom; opacity: 1; }
  100% { transform: scaleY(0); transform-origin: bottom; opacity: 0; }
}

/* ==========================================================================
   The fork — a hard stop. The page holds until a choice is made (v3 §3).
   ========================================================================== */
.fork { min-height: 100svh; display: grid; place-items: center; text-align: center; }
.fork__inner { width: 100%; }
.fork__question {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.7rem, 4vw, 3rem);
  line-height: 1.1; letter-spacing: -.02em;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}
.fork__options {
  margin-top: clamp(2.5rem, 6vw, 4rem);
  display: grid; gap: 1px;
  grid-template-columns: 1fr;
  background: var(--rule);
  border-block: 1px solid var(--rule);
}
@media (min-width: 48rem) { .fork__options { grid-template-columns: 1fr 1fr; } }

.fork__option {
  display: block;
  background: var(--tone);
  padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.5rem, 4vw, 3rem);
  transition: background-color .5s linear, color .45s var(--ease);
}
.fork__option:hover, .fork__option:focus-visible { background: var(--ink); color: var(--tone); }
.fork__option:hover .fork__note, .fork__option:focus-visible .fork__note { color: var(--tone); opacity: .75; }
.fork__name {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.9rem, 4vw, 3.1rem); line-height: 1; letter-spacing: -.02em;
}
.fork__note {
  margin-top: 1rem; font-weight: 300; color: var(--ink-soft);
  max-width: 26ch; margin-inline: auto;
  transition: color .45s var(--ease), opacity .45s var(--ease);
}

/* ==========================================================================
   Collections — the DIVE DEEPER scroll
   ========================================================================== */
.opener {
  position: relative; height: 100svh;
  display: grid; place-items: center; overflow: hidden;
}
.opener__bg { position: absolute; inset: 0; }
.opener__bg img { width: 100%; height: 100%; object-fit: cover; }
.opener__bg::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.14) 0%, rgba(0,0,0,.32) 100%);
}
.opener__inner { position: relative; z-index: 2; text-align: center; padding-inline: var(--gutter); }
.opener__title { color: #fff; }

/* The editorial layer: water and light, then the process. */
.depths { padding-block: clamp(5rem, 14vh, 10rem); }
.depths__grid {
  display: grid; gap: clamp(2.5rem, 6vw, 5rem);
  grid-template-columns: 1fr;
}
@media (min-width: 56rem) { .depths__grid { grid-template-columns: 1fr 1fr; } }
.depths__block h3 { margin-bottom: .9rem; }
.depths__block p {
  font-weight: 300; font-size: clamp(1rem, 1.3vw, 1.18rem);
  line-height: 1.62; max-width: 38ch;
}

.piece {
  min-height: 100svh;
  display: grid; place-items: center;
  padding-block: clamp(3.5rem, 10vh, 8rem);
}
.piece__inner { width: 100%; display: grid; justify-items: center; gap: clamp(1.4rem, 3vw, 2.2rem); }
.piece__plate {
  width: min(62vw, 64vh * 1.509, 940px);
  aspect-ratio: 1565 / 1037;
  cursor: pointer; position: relative;
  box-shadow: 0 clamp(8px, 1.6vw, 26px) clamp(22px, 4vw, 64px) rgba(0, 0, 0, .18);
}
.piece__plate img { width: 100%; height: 100%; object-fit: cover; }
/* Two elements only in the scroll: the collection, and acquire (v2 §4.1). */
.piece__meta {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(1.2rem, 3vw, 2.4rem); flex-wrap: wrap;
}
.piece__collection { font-family: var(--serif); font-weight: 400; font-size: clamp(1.4rem, 2.4vw, 2rem); line-height: 1; }

/* ==========================================================================
   SHOP
   ========================================================================== */
.shop-head { padding-top: clamp(6rem, 16vh, 9rem); }

.shop-collections { display: grid; gap: clamp(1rem, 2vw, 1.6rem); grid-template-columns: 1fr; }
@media (min-width: 44rem) { .shop-collections { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 72rem) { .shop-collections { grid-template-columns: repeat(3, 1fr); } }

.shop-card { display: block; position: relative; overflow: hidden; }
.shop-card__plate { position: relative; aspect-ratio: 4 / 5; overflow: hidden; background: var(--rule-faint); }
.shop-card__plate img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.3s var(--slow); }
.shop-card:hover .shop-card__plate img, .shop-card:focus-visible .shop-card__plate img { transform: scale(1.04); }
.shop-card__plate::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.42) 0%, rgba(0,0,0,0) 52%);
}
.shop-card__body { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: clamp(1.1rem, 2.4vw, 1.8rem); color: #fff; }
.shop-card__name { font-family: var(--serif); font-weight: 400; font-size: clamp(1.6rem, 2.6vw, 2.2rem); line-height: 1; }
.shop-card__short { margin-top: .45rem; font-weight: 300; color: rgba(255,255,255,.84); font-size: .95rem; }

/* Product grid — the storefront convention, in the studio's palette. */
.product-grid {
  display: grid; gap: clamp(1.6rem, 3vw, 2.6rem) clamp(1rem, 2vw, 1.8rem);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 60rem) { .product-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 86rem) { .product-grid { grid-template-columns: repeat(4, 1fr); } }

.product-card { display: block; text-align: center; }
.product-card__plate {
  aspect-ratio: 1565 / 1037; overflow: hidden;
  background: var(--rule-faint);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .10);
}
.product-card__plate img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--slow); }
.product-card:hover .product-card__plate img, .product-card:focus-visible .product-card__plate img { transform: scale(1.035); }
.product-card__meta { margin-top: .9rem; display: grid; gap: .25rem; }
.product-card__collection { font-family: var(--serif); font-weight: 400; font-size: 1.15rem; line-height: 1.1; }
.product-card__price { font-weight: 400; font-size: .88rem; color: var(--ink-soft); transition: color .5s linear; }

/* ==========================================================================
   Product detail page — shared by both paths
   ========================================================================== */
.pdp { display: grid; gap: clamp(2rem, 4vw, 3.5rem); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 64rem) {
  .pdp { grid-template-columns: minmax(0, 1.55fr) minmax(20rem, .85fr); gap: clamp(2.5rem, 5vw, 4.5rem); }
  .pdp__buy { position: sticky; top: clamp(6rem, 14vh, 8.5rem); }
}

/* Horizontal scroll: artwork first, then in-room and framed examples as they
   arrive. Built for more frames than it currently has. */
.carousel { position: relative; }
.carousel__track {
  display: grid; grid-auto-flow: column; grid-auto-columns: 100%;
  gap: clamp(.6rem, 1.4vw, 1rem);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__frame { scroll-snap-align: center; }
.carousel__frame img {
  width: 100%; height: auto;
  box-shadow: 0 clamp(10px, 2vw, 30px) clamp(26px, 5vw, 72px) rgba(0, 0, 0, .20);
}
.carousel__bar { display: flex; gap: .4rem; margin-top: 1rem; }
.carousel__seg {
  flex: 1; height: 2px; background: var(--rule);
  transition: background-color .35s var(--ease);
}
.carousel__seg[aria-current="true"] { background: var(--ink); }
.carousel__count { margin-top: .6rem; }
.carousel--single .carousel__bar { display: none; }

.pdp__collection { font-family: var(--serif); font-weight: 400; font-size: clamp(2.2rem, 4.6vw, 3.4rem); line-height: 1; letter-spacing: -.02em; }
.pdp__price { margin-top: 1.1rem; font-size: 1.05rem; font-weight: 400; }
.pdp__facts { margin-top: 1.6rem; display: grid; gap: .55rem; }
.pdp__fact { display: flex; gap: .7rem; align-items: baseline; font-weight: 300; color: var(--ink-soft); transition: color .5s linear; }
.pdp__fact::before { content: "—"; opacity: .5; }
.pdp__cta { margin-top: 1.9rem; width: 100%; justify-content: center; }

.spec { border-top: 1px solid var(--rule-faint); margin-top: 1.8rem; }
.spec div { display: flex; justify-content: space-between; gap: 1rem; padding: .65rem 0; border-bottom: 1px solid var(--rule-faint); }
.spec dt { color: var(--ink-soft); font-weight: 300; transition: color .5s linear; }
.spec dd { text-align: right; font-weight: 400; }

.accordion { margin-top: 1.8rem; border-top: 1px solid var(--rule-faint); }
.accordion details { border-bottom: 1px solid var(--rule-faint); }
.accordion summary {
  list-style: none; cursor: pointer;
  padding: .95rem 0; display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: .2em; text-transform: uppercase;
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::after { content: "+"; font-size: 1rem; letter-spacing: 0; }
.accordion details[open] summary::after { content: "–"; }
.accordion p { padding-bottom: 1.1rem; font-weight: 300; color: var(--ink-soft); max-width: 42ch; transition: color .5s linear; }

.pager { display: flex; justify-content: space-between; gap: 1rem; margin-top: clamp(3rem, 7vw, 5rem); padding-top: 1.2rem; border-top: 1px solid var(--rule); }

/* ==========================================================================
   About / trade / contact
   ========================================================================== */
.about__lead { display: grid; gap: clamp(2rem, 5vw, 4rem); }
@media (min-width: 62rem) { .about__lead { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: end; } }

.studio-run { display: grid; gap: clamp(2.5rem, 6vw, 5rem); margin-top: clamp(3rem, 8vw, 6rem); }
.studio-row { display: grid; gap: clamp(1rem, 2.5vw, 2rem); align-items: center; }
.studio-row--2, .studio-row--offset { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); }
.studio-row--wide { grid-template-columns: 1fr; }
.studio-row--offset > *:nth-child(2) { margin-top: clamp(2rem, 6vw, 5rem); }
.studio-fig img { width: 100%; }

/* The quarter-turn from v2 §4.3 is baked into the asset by
   tools/process-extra.swift, so this only has to keep a portrait frame from
   towering over a full-width row. */
.studio-fig--portrait {
  width: 100%;
  max-width: min(28rem, 62vw);
  margin-inline: auto;
}

.trade__blocks { display: grid; gap: clamp(1.8rem, 4vw, 3rem); grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); margin-top: clamp(2.5rem, 6vw, 4rem); }
.trade__block { border-top: 1px solid var(--rule); padding-top: 1.1rem; }
.trade__block h3 { font-family: var(--serif); font-weight: 400; font-size: clamp(1.4rem, 2.2vw, 1.85rem); line-height: 1.1; margin-top: .4rem; }
.trade__block p { margin-top: .7rem; color: var(--ink-soft); font-weight: 300; transition: color .5s linear; }

/* --- buttons / forms ------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; gap: .8em;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  padding: 1.05em 2em;
  border: 1px solid var(--ink); color: var(--ink);
  transition: background-color .4s var(--ease), color .4s var(--ease);
}
.btn:hover, .btn:focus-visible { background: var(--ink); color: var(--tone); }
.btn--solid { background: var(--ink); color: var(--tone); }
.btn--solid:hover, .btn--solid:focus-visible { background: transparent; color: var(--ink); }
.btn--quiet { border-color: var(--rule); }

.link-underline { border-bottom: 1px solid var(--rule); padding-bottom: .12em; transition: border-color .3s var(--ease); }
.link-underline:hover, .link-underline:focus-visible { border-bottom-color: var(--ink); }

.form { display: grid; gap: 1.5rem; max-width: 34rem; }
.field { display: grid; gap: .45rem; }
.field label { font-size: var(--fs-micro); font-weight: 500; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-soft); }
.field input, .field select, .field textarea {
  font-family: var(--sans); font-size: 1rem; font-weight: 300;
  color: var(--ink); background: transparent;
  border: 0; border-bottom: 1px solid var(--rule); border-radius: 0;
  padding: .55rem 0; transition: border-color .3s var(--ease);
}
.field textarea { resize: vertical; min-height: 5.5rem; }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-bottom-color: var(--ink); }
.field option { color: #1a1a1a; }
.form__status { font-size: var(--fs-micro); font-weight: 500; letter-spacing: .2em; text-transform: uppercase; min-height: 1.2em; }

/* --- footer --------------------------------------------------------------- */
.foot { border-top: 1px solid var(--rule); padding-block: clamp(3rem, 7vh, 4.5rem) clamp(1.5rem, 4vh, 2.5rem); }
.foot__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 2.5rem; align-items: start; }
.foot__grid ul { display: grid; gap: .55rem; }
.foot__grid a { color: var(--ink-soft); font-weight: 300; transition: color .3s var(--ease); }
.foot__grid a:hover, .foot__grid a:focus-visible { color: var(--ink); }
.foot__base {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem;
  margin-top: clamp(2.5rem, 6vh, 4rem); padding-top: 1.1rem;
  border-top: 1px solid var(--rule-faint);
  color: var(--ink-soft); font-size: .82rem; font-weight: 300;
}

/* --- reveal / anchors ----------------------------------------------------- */
[data-reveal] { opacity: 0; transform: translateY(1.5rem); transition: opacity 1s var(--ease), transform 1s var(--ease); }
[data-reveal].is-in { opacity: 1; transform: none; }
.tone-anchor { position: absolute; width: 1px; height: 1px; pointer-events: none; opacity: 0; }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 62rem) {
  .piece__plate { width: min(88vw, 52vh * 1.509); }
}

@media (max-width: 46rem) {
  .nav {
    position: fixed; inset: 0;
    flex-direction: column; align-items: flex-start; justify-content: center;
    gap: 1.5rem; padding: var(--gutter);
    background: var(--tone);
    transform: translateY(-100%);
    transition: transform .55s var(--slow);
  }
  .nav[data-open="true"] { transform: none; }
  .nav a { font-size: .8rem; letter-spacing: .18em; }
  .nav__cross { margin-left: 0; }
  .nav__toggle {
    display: block; position: relative; z-index: 2;
    font-size: var(--fs-micro); font-weight: 500;
    letter-spacing: .2em; text-transform: uppercase; color: var(--ink);
    /* The bar is space-between with the mark at one end; this collects the
       free space here so Menu and the cart travel together at the other. */
    margin-left: auto;
  }
  /* To the right of Menu, closer to it than the bar's own gap would put it. */
  .masthead__cart[hidden] { display: none; }
  .masthead__cart {
    display: inline-flex; align-items: center; gap: .4em;
    position: relative; z-index: 2;
    margin-left: -.65rem;
    font-size: var(--fs-micro); font-weight: 500;
    letter-spacing: .1em; color: var(--ink);
    font-variant-numeric: tabular-nums;
  }
  .masthead__cart svg {
    width: 1.05rem; height: 1.05rem;
    fill: none; stroke: currentColor;
    stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
  }
  .masthead--invert .masthead__cart { color: #fff; }
  .product-grid { grid-template-columns: repeat(2, 1fr); }
  .studio-row--offset > *:nth-child(2) { margin-top: 0; }
  .intro-lede { width: 88vw; }
  .intro-lede p { font-size: clamp(1.25rem, 6.4vw, 1.9rem); }
  .frag { font-size: clamp(1.05rem, 5vw, 1.5rem); max-width: 80vw; }
}

/* ==========================================================================
   Reduced motion — the field becomes an ordinary run of images
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  [data-reveal] { opacity: 1; transform: none; }

  .dive { height: auto !important; }
  .dive__stage { position: static; height: auto; overflow: visible; padding-block: 3rem; }
  .drift {
    position: relative; inset: auto;
    width: min(78vw, 44rem) !important;
    transform: none !important; opacity: 1 !important;
    margin: 0 auto clamp(2rem, 6vw, 4rem);
  }
  .intro-lede, .frag {
    position: static; transform: none; opacity: 1 !important;
    margin: clamp(1.5rem, 5vw, 3rem) auto;
    text-align: center;
    max-width: min(90vw, 36rem);
  }
  .intro-frags { position: static; }
  .dive__cue { display: none; }
  .piece { min-height: 0; }
  .opener { height: auto; padding-block: clamp(4rem, 12vh, 8rem); }
  .fork { min-height: 0; padding-block: clamp(3rem, 8vh, 5rem); }
}

/* ==========================================================================
   v3 — DIVE DEEPER: depth rows, expanded depth, horizontal journey
   ========================================================================== */

/* A short reintroduction of the work itself before the depths are indexed. */
.deepdive { position: relative; }
.deepdive__stage { position: sticky; top: 0; height: 100svh; overflow: hidden; }

/* The table of contents. Each row is one depth, light to dark. */
.depths-index { position: relative; }

.depth { position: relative; }
.depth + .depth { border-top: 1px solid rgba(255, 255, 255, .18); }

.depth__row {
  position: relative;
  display: block;
  width: 100%;
  height: clamp(160px, 24vh, 280px);
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  transition: height .55s var(--slow);
}
.depth__row img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.02);
  transition: transform 1.4s var(--slow);
}
.depth__row:hover img { transform: scale(1.05); }
.depth__row::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to right, rgba(0,0,0,.46) 0%, rgba(0,0,0,.18) 60%, rgba(0,0,0,.3) 100%);
}
.depth__rowinner {
  position: relative; z-index: 2;
  height: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem;
  padding-inline: var(--gutter);
  color: #fff;
}
.depth__name {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.9rem, 5vw, 4rem); line-height: 1;
  letter-spacing: -.025em;
}
.depth__cue {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: rgba(255, 255, 255, .8);
  display: flex; align-items: center; gap: .6em;
}
.depth__cue::after { content: "+"; font-size: 1.1rem; letter-spacing: 0; }

/* Open: the row shrinks and pins as the header for the depth below it,
   sitting under the masthead rather than behind it. */
.depth.is-open .depth__row {
  position: sticky; top: var(--masthead-h, 76px); z-index: 30;
  height: clamp(72px, 11vh, 104px);
}
.depth.is-open .depth__cue::after { content: "–"; }

.depth__panel { display: none; }
.depth.is-open .depth__panel {
  display: block;
  min-height: 100svh;
  padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(3.5rem, 8vw, 6rem);
}

.depth__blurb { max-width: 42ch; margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.depth__blurb p { font-weight: 300; font-size: var(--fs-lede); line-height: 1.5; }
.depth__blurb p + p { margin-top: 1em; }

.depth__grid {
  display: grid; gap: clamp(.8rem, 1.6vw, 1.4rem);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 52rem) { .depth__grid { grid-template-columns: repeat(3, 1fr); } }

.depth__tile { display: block; cursor: pointer; }
.depth__tile-plate { aspect-ratio: 1565 / 1037; overflow: hidden; background: var(--rule-faint); }
.depth__tile-plate img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--slow); }
.depth__tile:hover .depth__tile-plate img { transform: scale(1.04); }
.depth__tile .serial { margin-top: .5rem; display: block; }

/* The horizontal journey, scoped to one depth. */
.journey { display: none; }
.depth.is-journey .journey { display: block; }
.depth.is-journey .depth__grid,
.depth.is-journey .depth__blurb { display: none; }

.journey__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: 1.2rem;
}
.journey__track {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: min(82vw, 62rem);
  gap: clamp(1rem, 3vw, 2.5rem);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-bottom: .5rem;
}
.journey__track::-webkit-scrollbar { display: none; }
.journey__frame { scroll-snap-align: center; }
.journey__frame img {
  width: 100%; height: auto;
  box-shadow: 0 clamp(10px, 2vw, 30px) clamp(26px, 5vw, 70px) rgba(0, 0, 0, .2);
}
.journey__meta { display: flex; justify-content: space-between; gap: 1rem; margin-top: .8rem; }

/* ==========================================================================
   v3 — Editorial. The one place the layout behaves like a printed page.
   ========================================================================== */
.editorial { max-width: 58rem; margin-inline: auto; }
.editorial__kicker { text-align: center; }
.editorial__title {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(2.2rem, 5.4vw, 4.2rem); line-height: 1.04;
  letter-spacing: -.025em; text-align: center;
  margin-top: 1rem; text-wrap: balance;
}
.editorial__standfirst {
  font-size: var(--fs-lede); font-weight: 300; line-height: 1.5;
  text-align: center; max-width: 46ch; margin: clamp(1.5rem, 3vw, 2.2rem) auto 0;
  text-wrap: balance;
}
.editorial__body { max-width: 36rem; margin-inline: auto; margin-top: clamp(3rem, 7vw, 5rem); }
.editorial__body p { font-weight: 300; font-size: 1.06rem; line-height: 1.78; }
.editorial__body p + p { margin-top: 1.4em; }
.editorial__pull {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.4rem, 2.8vw, 2.1rem); line-height: 1.3;
  letter-spacing: -.015em; text-align: center;
  max-width: 26ch; margin: clamp(2.5rem, 6vw, 4rem) auto;
  text-wrap: balance;
}
.editorial__figure { margin: clamp(2.5rem, 6vw, 4.5rem) 0; }
.editorial__figure--wide { max-width: 58rem; margin-inline: auto; }
.editorial__figure--bleed { max-width: none; width: 100%; }
.editorial__figure img { width: 100%; }
.editorial__figure figcaption { margin-top: .7rem; text-align: center; }
.editorial__pair { display: grid; gap: clamp(1rem, 2.4vw, 1.8rem); grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }

/* ==========================================================================
   v3 — Instagram row
   ========================================================================== */
.ig__row {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: minmax(min(46vw, 15rem), 1fr);
  gap: clamp(.4rem, 1vw, .8rem);
  overflow-x: auto; overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.ig__row::-webkit-scrollbar { display: none; }
.ig__tile { position: relative; aspect-ratio: 1; overflow: hidden; background: var(--rule-faint); }
.ig__tile img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--slow); }
.ig__tile:hover img { transform: scale(1.05); }

/* ==========================================================================
   v3 — Product detail page: two purchase modes
   ========================================================================== */
.modes {
  display: grid; grid-template-columns: 1fr 1fr;
  border: 1px solid var(--rule);
  margin-bottom: 1.6rem;
}
.mode {
  padding: .95em 1em;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-soft);
  transition: background-color .35s var(--ease), color .35s var(--ease);
}
.mode + .mode { border-left: 1px solid var(--rule); }
.mode[aria-selected="true"] { background: var(--ink); color: var(--tone); }

.mode-panel { container-type: inline-size; }
.mode-panel[hidden] { display: none; }
.mode-panel__line { margin-bottom: 1.2rem; }
.mode-panel__material { font-weight: 300; color: var(--ink-soft); max-width: 34ch; transition: color .5s linear; }

/* Eight print sizes run two abreast so the list stays four rows and the
   choice can be taken in at a glance. The canvas tiers, being four, keep a
   single column — they carry a name as well as a size and need the width.
   Below 26rem of panel there is no room for two, so it folds back to one. */
.sizes { display: grid; gap: .45rem; margin-top: 1.4rem; }
/* Filled down the first column and then the second, so the small sizes are
   read together on the left and the large ones on the right — rather than
   zig-zagging across the rows, which is what a grid does by default. The row
   count comes from the renderer, since it is half the number of sizes. */
.sizes[data-columns="2"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(var(--size-rows, 4), auto);
  grid-auto-flow: column;
}
/* The widest pairing, "40 x 60 in" beside "$1,600", needs about 137px of
   cell once padding is counted — so two fit above roughly 18rem of panel,
   and the piece page's 320px column holds them with room over. Below that
   it folds back rather than clipping a price. */
@container (max-width: 18rem) {
  .sizes[data-columns="2"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-auto-flow: row;
  }
}
.sizes[data-columns="2"] .size {
  gap: .5rem; padding-inline: .9em;
  font-size: .92rem;
}
.sizes[data-columns="2"] .size__price { white-space: nowrap; }
.size {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding: .85em 1.1em;
  border: 1px solid var(--rule);
  font-weight: 300;
  cursor: pointer;
  transition: border-color .3s var(--ease), background-color .3s var(--ease);
}
.size:hover { border-color: rgba(var(--ink-rgb), .42); }
.size[aria-checked="true"] { border-color: var(--ink); background: rgba(var(--ink-rgb), .05); }
.size__price { font-weight: 400; }
.size__note { font-size: var(--fs-micro); letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft); }


/* Above the buttons now, so the wait is read before the decision rather than
   after it. The air moves to the foot for the same reason. */
.buy__note:not(:empty) { margin-top: 1.4rem; }
/* The wait belongs to the button under it rather than to the sizes above, so
   where it is present it pulls the button up close. The buttons set their own
   generous top margin for the case where there is no note at all. */
.buy__note:not(:empty) + .pdp__cta,
.buy__note:not(:empty) + .quickshop__cta,
.buy__note:not(:empty) + .work__inquire { margin-top: .75rem; }
.buy__note { font-size: .86rem; font-weight: 300; line-height: 1.6; color: var(--ink-soft); transition: color .5s linear; }

@media (prefers-reduced-motion: reduce) {
  .deepdive { height: auto !important; }
  .deepdive__stage { position: static; height: auto; overflow: visible; padding-block: 3rem; }
  .depth.is-open .depth__row { position: static; }
  .depth__row { height: auto; min-height: 120px; }
}

/* ==========================================================================
   v4 — scroll-driven journey (GSAP ScrollTrigger + Lenis)
   Sections pin and their timelines are scrubbed against scroll, in the manner
   of the reference: the page is one ruler and each act claims a range of it.
   ========================================================================== */

/* Every act is a tall rail with a pinned stage inside it. */
.act { position: relative; }
.act__stage {
  position: sticky; top: 0;
  height: 100svh;
  overflow: hidden;
  display: grid;
  place-items: center;
}

/* --- the featured image, centre stage ------------------------------------- */
.featured {
  position: relative; z-index: 3;
  width: min(46vw, 52vh * 1.5, 720px);
  aspect-ratio: 3 / 2;
  will-change: transform, opacity;
}
.featured__frame {
  position: absolute; inset: 0;
  opacity: 0;
  overflow: hidden;
}
.featured__frame img { width: 100%; height: 100%; object-fit: cover; }
.featured__frame.is-live { opacity: 1; }

/* --- copy that reads in place -------------------------------------------- */
.script {
  position: absolute; inset: 0; z-index: 6;
  display: grid; place-items: center;
  pointer-events: none;
  padding-inline: var(--gutter);
}
.script__line {
  grid-area: 1 / 1;
  max-width: min(90vw, 40rem);
  text-align: center;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.4rem, 3.4vw, 2.8rem);
  line-height: 1.24;
  letter-spacing: -.018em;
  text-wrap: balance;
  opacity: 0;
  text-shadow: var(--copy-halo);
  will-change: opacity, transform;
}
.script--lower { align-items: end; padding-bottom: 12vh; }

/* Landing mark, set as type (v4 §2 beat 1). */
.landing__mark {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.9rem, 5.4vw, 4.2rem);
  line-height: 1.1; letter-spacing: -.02em;
  text-align: center;
}
.landing__bleed {
  position: absolute; inset: 0; z-index: 2;
  opacity: 0;
  will-change: transform, opacity;
}
.landing__bleed img { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   v4 — depths
   ========================================================================== */
.depth-act { position: relative; }
.depth-act .act__stage { display: grid; place-items: center; }

.depth-head {
  position: absolute; z-index: 7;
  top: calc(var(--masthead-h, 84px) + 1.4rem);
  left: var(--gutter);
  pointer-events: none;
}
.depth-head__numeral {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.1rem, 1.6vw, 1.4rem); line-height: 1;
  color: var(--ink-soft); transition: color .5s linear;
}
.depth-head__name {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(2rem, 4.6vw, 3.6rem); line-height: 1;
  letter-spacing: -.025em; margin-top: .3rem;
}
.depth-head__palette { margin-top: .7rem; max-width: 22ch; }

/* Images surround the copy rather than sitting behind it. */
.depth-field { position: absolute; inset: 0; }
.depth-field__item {
  position: absolute;
  width: var(--w, 15vw);
  aspect-ratio: 1565 / 1037;
  overflow: hidden;
  cursor: pointer;
  opacity: 0;
  will-change: transform, opacity;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .16);
}
.depth-field__item img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.1s var(--slow); }
.depth-field__item:hover img { transform: scale(1.05); }

/* --- sub nav (v4 §5.2) ---------------------------------------------------- */
.subnav {
  position: fixed; z-index: 80;
  right: var(--gutter); top: 50%;
  transform: translateY(-50%);
  display: grid; gap: .85rem;
  opacity: 0; pointer-events: none;
  transition: opacity .5s var(--ease);
}
.subnav.is-live { opacity: 1; pointer-events: auto; }
.subnav__item {
  display: flex; align-items: center; justify-content: flex-end; gap: .7rem;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-soft);
  transition: color .35s var(--ease);
}
.subnav__item::after {
  content: ""; width: 26px; height: 1px;
  background: currentColor; opacity: .45;
  transition: width .35s var(--ease), opacity .35s var(--ease);
}
.subnav__item:hover { color: var(--ink); }
.subnav__item[aria-current="true"] { color: var(--ink); }
.subnav__item[aria-current="true"]::after { width: 46px; opacity: 1; }

/* ==========================================================================
   v4 — image viewer
   ========================================================================== */
.viewer { position: fixed; inset: 0; z-index: 200; display: grid; }
.viewer[hidden] { display: none; }
.viewer__scrim { position: absolute; inset: 0; background: var(--tone); opacity: 0; transition: opacity .4s var(--ease); }
.viewer.is-open .viewer__scrim { opacity: .985; }
.viewer__panel {
  position: relative; z-index: 2;
  width: 100%; height: 100%;
  display: grid; grid-template-rows: auto 1fr auto;
  padding: clamp(1rem, 2.4vw, 1.8rem) var(--gutter) clamp(1.5rem, 3vw, 2.4rem);
  opacity: 0; transform: translateY(1rem);
  transition: opacity .4s var(--ease), transform .5s var(--slow);
}
.viewer.is-open .viewer__panel { opacity: 1; transform: none; }
.viewer__bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.viewer__stage { display: grid; place-items: center; min-height: 0; padding-block: clamp(1rem, 3vh, 2rem); }
.viewer__stage img {
  max-width: min(100%, 76vw); max-height: 64vh;
  width: auto; height: auto; object-fit: contain;
  box-shadow: 0 clamp(10px, 2vw, 30px) clamp(26px, 5vw, 72px) rgba(0, 0, 0, .22);
}
.viewer__foot { display: flex; align-items: end; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.viewer__steps { display: flex; gap: .5rem; align-items: center; }
.viewer__step {
  width: 2.5rem; height: 2.5rem; display: grid; place-items: center;
  border: 1px solid var(--rule);
  transition: background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.viewer__step:hover:not(:disabled) { background: var(--ink); color: var(--tone); border-color: var(--ink); }
.viewer__step:disabled { opacity: .3; cursor: default; }

/* ==========================================================================
   v4 — trade web + contact
   ========================================================================== */
.web { position: absolute; inset: 0; }
.web__tile {
  position: absolute;
  width: var(--w, 9vw);
  aspect-ratio: 1565 / 1037;
  overflow: hidden;
  opacity: 0;
  will-change: transform, opacity;
}
.web__tile img { width: 100%; height: 100%; object-fit: cover; }

.trade-card { grid-area: 1 / 1; max-width: min(90vw, 34rem); text-align: center; opacity: 0; will-change: opacity, transform; }
.trade-card h3 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.7rem, 3.6vw, 2.8rem); line-height: 1.08; letter-spacing: -.02em;
}
.trade-card p { margin-top: 1rem; font-weight: 300; font-size: var(--fs-lede); line-height: 1.5; text-shadow: var(--copy-halo); }

.rotator { display: inline-grid; vertical-align: baseline; }
.rotator__word { grid-area: 1 / 1; opacity: 0; transition: opacity .5s var(--ease), transform .5s var(--ease); transform: translateY(.25em); white-space: nowrap; }
.rotator__word.is-live { opacity: 1; transform: none; }

@media (max-width: 46rem) {
  .featured { width: min(84vw, 42vh * 1.5); }
  .script__line { font-size: clamp(1.15rem, 5.4vw, 1.7rem); }
  .landing__mark { font-size: clamp(1.5rem, 7.4vw, 2.2rem); }
  .depth-head { left: var(--gutter); right: var(--gutter); }
  .depth-head__name { font-size: clamp(1.6rem, 8vw, 2.2rem); }
  /* Sub nav collapses to a compact strip on narrow screens (v4 §10.7). */
  .subnav { right: auto; left: 50%; top: auto; bottom: 1rem; transform: translateX(-50%);
            grid-auto-flow: column; gap: .5rem; }
  .subnav__item { font-size: .55rem; letter-spacing: .1em; }
  .subnav__item::after { width: 12px; }
  .subnav__item[aria-current="true"]::after { width: 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .act { height: auto !important; }
  .act__stage { position: static; height: auto; overflow: visible; display: block; padding-block: 3rem; }
  .field, .web { position: static; }
  .field__item, .web__tile, .depth-field__item {
    position: relative; width: min(70vw, 30rem) !important;
    opacity: 1 !important; transform: none !important; margin: 0 auto 1.5rem;
  }
  .featured { width: min(84vw, 44rem); margin-inline: auto; }
  .featured__frame { position: relative; opacity: 1; }
  .script { position: static; display: block; }
  .script__line { opacity: 1 !important; transform: none !important; margin: 1.5rem auto; }
  .landing__bleed { position: relative; opacity: 1; height: 60svh; }
  .subnav { display: none; }
  .trade-card { opacity: 1 !important; margin: 2rem auto; }
  .rotator__word:not(:first-child) { display: none; }
  .rotator__word:first-child { opacity: 1; transform: none; }
}

/* Interview questions read as the editorial's structural device. */
.editorial__q {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.25rem, 2.2vw, 1.7rem);
  line-height: 1.25;
  letter-spacing: -.012em;
  margin-bottom: 1.2em;
}
.editorial__body + .editorial__body { margin-top: clamp(2.5rem, 6vw, 4rem); }

/* ==========================================================================
   v5 — condensed journey
   ========================================================================== */

/* Fragments placed among the scatter rather than held dead centre. */
.script__line--placed {
  position: absolute;
  grid-area: auto;
  transform: translate(-50%, -50%);
  max-width: min(78vw, 26rem);
  text-align: left;
}

/* In a depth the images lead: copy drops to a supporting size and sits low,
   out of the way of the work. */
.script--depth { align-items: end; padding-bottom: 9vh; }
.script__line--depth {
  font-size: clamp(1.05rem, 1.9vw, 1.55rem);
  font-weight: 300;
  font-family: var(--ui);
  letter-spacing: 0;
  line-height: 1.4;
  max-width: min(88vw, 34rem);
}

/* Depth plates carry the section now. */
.depth-field__item { box-shadow: 0 12px 44px rgba(0, 0, 0, .2); }

/* Trade establishing frame. */
.trade-lead { max-width: min(90vw, 34rem); text-align: center; }
.trade-lead__line {
  margin-top: 1rem;
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.4rem, 3vw, 2.3rem);
  line-height: 1.22; letter-spacing: -.018em;
  text-wrap: balance;
  text-shadow: var(--copy-halo);
}

/* The sub nav is vertical on the right at every width. */
@media (max-width: 46rem) {
  .subnav {
    right: var(--gutter); left: auto;
    top: 50%; bottom: auto;
    transform: translateY(-50%);
    grid-auto-flow: row; gap: .6rem;
  }
  .subnav__item { font-size: .5rem; letter-spacing: .12em; }
  .subnav__item::after { width: 14px; }
  .subnav__item[aria-current="true"]::after { width: 24px; }
  .script__line--placed { max-width: 72vw; }
}

@media (prefers-reduced-motion: reduce) {
  .script__line--placed { position: static; transform: none; text-align: center; }
  .trade-lead { margin: 2rem auto; }
}

/* Shop lands on the work itself — collections stacked with their pieces. */
.shop-group + .shop-group { margin-top: clamp(3rem, 7vw, 5rem); }

/* The landing carries two lines as one block, not two layers in one cell. */
.script--stack { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5rem; }
.script--stack .script__line { grid-area: auto; }

/* ==========================================================================
   v6 — the minimal landing
   Five moves: a full frame, a line, the work, a paragraph, the conversation.
   ========================================================================== */
.hero { height: var(--vh-frame); overflow: hidden; }
/* On the landing the image is full bleed, so it starts above the bar. */
[data-page="home"] .hero { margin-top: calc(var(--masthead-h) * -1); height: 100svh; }
.hero img { width: 100%; height: 100%; object-fit: cover; }

/* Copy sits on clean ground, nothing else in the frame. */
.statement {
  min-height: 78svh;
  display: grid;
  place-items: center;
  padding: clamp(5rem, 14vh, 9rem) var(--gutter);
  text-align: center;
}
.statement__line {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.6rem, 4vw, 3.2rem);
  line-height: 1.24;
  letter-spacing: -.02em;
  max-width: 22ch;
  text-wrap: balance;
}
.statement__para {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(1.2rem, 2.4vw, 2rem);
  line-height: 1.38;
  letter-spacing: -.014em;
  max-width: 40ch;
  text-wrap: balance;
}

/* The work, light to dark. No captions, no collection names. */
.work { padding: clamp(2rem, 6vh, 4rem) var(--gutter) clamp(5rem, 12vh, 8rem); }
.work__grid {
  max-width: 96rem;
  margin-inline: auto;
  display: grid;
  gap: clamp(.5rem, 1.2vw, 1.1rem);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 46rem) { .work__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 70rem) { .work__grid { grid-template-columns: repeat(4, 1fr); } }

.work__item {
  display: block;
  aspect-ratio: 1565 / 1037;
  overflow: hidden;
  background: var(--rule-faint);
}
.work__item img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--slow); }
.work__item:hover img, .work__item:focus-visible img { transform: scale(1.035); }

.editorial__head { text-align: center; margin-bottom: clamp(3rem, 8vw, 5rem); }
.editorial__head .editorial__title { margin-top: .8rem; }

/* ==========================================================================
   v7 — five pages
   The landing holds its own line; the paragraph gets a clean ground; the work
   is entered in home, then indexed as a field; the interview folds away.
   ========================================================================== */

/* --- 1 · the landing ------------------------------------------------------ */
.hero { position: relative; }

.hero__action {
  position: absolute; left: 0; right: 0; bottom: clamp(2rem, 7vh, 4.5rem); z-index: 3;
  display: flex; justify-content: center;
}
.hero__pill {
  display: inline-flex; align-items: center; gap: .9em;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .28em; text-transform: uppercase;
  color: var(--ink);
  padding: .95rem 1.8rem;
  border: 1px solid var(--rule); border-radius: 999px;
  background: var(--tone);
  transition: background-color .45s var(--ease), color .45s var(--ease), border-color .45s var(--ease);
}
.hero__pill svg {
  width: 1.05em; fill: none; stroke: currentColor;
  stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
}
.hero__pill:hover, .hero__pill:focus-visible {
  background: var(--ink); color: var(--tone); border-color: var(--ink);
}

.hero__copy {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  padding: var(--gutter); text-align: center;
}
/* The mark is set the way a pronunciation is set: bracketed and sloped. */
.hero__line em { font-style: italic; }

.hero__line {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(1.53rem, 3.96vw, 3.06rem);
  line-height: 1.22;
  letter-spacing: -.02em;
  max-width: 20ch;
  color: var(--ink);
  text-wrap: balance;
  transition: color .5s linear;
}

/* --- 3 · in home ---------------------------------------------------------- */
.inhome { position: relative; height: var(--vh-frame); overflow: hidden; background: #14171a; }
.inhome__stage { position: absolute; inset: 0; }
.inhome__slide {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--slow);
}
.inhome__slide[data-live="true"] { opacity: 1; }
.inhome__slide img { width: 100%; height: 100%; object-fit: cover; }

/* Just enough ground at the foot for the two white labels. */
.inhome::before {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(0deg, rgba(8, 12, 10, .46), rgba(8, 12, 10, 0) 28%);
}

.inhome__arrow {
  position: absolute; top: 50%; z-index: 3;
  transform: translateY(-50%);
  width: clamp(3.4rem, 6vw, 5.6rem); aspect-ratio: 1;
  display: grid; place-items: center;
  color: #fff;
  transition: opacity .45s var(--ease), transform .45s var(--ease);
  opacity: .8;
}
.inhome__arrow svg {
  width: 100%; fill: none; stroke: currentColor;
  stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 12px rgba(6, 14, 16, .45));
}
.inhome__arrow--prev { left: clamp(.8rem, 2.6vw, 2.4rem); }
.inhome__arrow--next { right: clamp(.8rem, 2.6vw, 2.4rem); }
.inhome__arrow:hover, .inhome__arrow:focus-visible { opacity: 1; }
.inhome__arrow--prev:hover { transform: translateY(-50%) translateX(-3px); }
.inhome__arrow--next:hover { transform: translateY(-50%) translateX(3px); }
.inhome__arrow:focus-visible { outline-color: #fff; }

.inhome__caption, .inhome__count {
  position: absolute; z-index: 3;
  bottom: clamp(1.25rem, 4vh, 2.5rem);
  color: rgba(255, 255, 255, .88);
}
.inhome__caption { left: clamp(1.25rem, 4.5vw, 3.4rem); }
.inhome__count { right: clamp(1.25rem, 4.5vw, 3.4rem); font-variant-numeric: tabular-nums; }

/* --- 4 · the portfolio ---------------------------------------------------- */
/* A rail long enough to travel, with the field pinned inside it. */
.gallery { position: relative; }
/* Five and a bit frames of travel, less a fifth: the field read as long
   before the way out arrived. The tone anchors along it are placed in
   percentages, so they keep their spacing as it shortens. */
.gallery__rail { position: relative; height: calc(var(--vh-frame) * 4.08); }

.gallery__stage {
  /* Up 30% from clamp(210px, 30.4vw, 478px). The cell carries both the frame
     and the air around it — the image is .71 of it across, the gutters the
     rest — so lifting the cell lifts the work and the spacing between it by
     the same amount, and the proportions of the field are untouched. */
  --cell: clamp(273px, 39.5vw, 621px);
  --cols: 7; --rows: 5;
  position: sticky; top: var(--masthead-h);
  height: var(--vh-frame);
  overflow: clip;
  cursor: grab;
  /* The vertical axis stays the page's, so a touch can always scroll past. */
  touch-action: pan-y;
}
.gallery__stage.is-dragging { cursor: grabbing; }
@media (max-width: 46rem) { .gallery__stage { --cols: 4; --rows: 7; } }
@media (min-width: 100rem) { .gallery__stage { --cols: 9; --rows: 6; } }

.gallery__plane { position: absolute; top: 0; left: 0; will-change: transform; }
.gallery__tile {
  position: absolute; top: 0; left: 0;
  display: grid;
  grid-template-columns: repeat(var(--cols), var(--cell));
  /* The vertical air is unchanged, so the row is now shorter than the cell is
     wide: a wide gutter across, a generous one down. */
  grid-auto-rows: calc(var(--cell) * .924);
}

/* Square cells holding landscape frames: the air around each piece is the
   cell, not a gap. */
.gallery__item {
  display: grid; align-content: center;
  padding-inline: calc(var(--cell) * .145);
  -webkit-user-select: none; user-select: none;
}
.gallery__frame {
  display: block;
  width: 100%; aspect-ratio: 1565 / 1037;
  overflow: hidden;
  background: rgba(var(--ink-rgb), .07);
}
.gallery__frame img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.4s var(--slow);
  -webkit-user-drag: none;
}
.gallery__item:hover .gallery__frame img,
.gallery__item:focus-visible .gallery__frame img { transform: scale(1.045); }

/* Over the field the pointer is replaced by the word for what a click does. */
@media (hover: hover) and (pointer: fine) {
  .gallery__stage, .gallery__item { cursor: none; }
  .gallery__stage.is-dragging { cursor: grabbing; }
  .deeper, .deeper__link { cursor: pointer; }
}
.cursor {
  position: fixed; top: 0; left: 0; z-index: 80;
  pointer-events: none;
  display: grid; place-items: center;
  width: 5.2rem; height: 2.1rem;
  background: var(--tone); color: var(--ink);
  border: 1px solid var(--ink);
  opacity: 0; scale: .7;
  transition: opacity .3s var(--ease), scale .4s var(--slow),
              background-color .5s linear, color .5s linear, border-color .5s linear;
  will-change: transform;
}
.cursor.is-live { opacity: 1; scale: 1; }
.cursor span {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .24em; text-transform: uppercase;
}


/* The way on, held at the foot of the field. */
.deeper {
  position: absolute; z-index: 4;
  left: 0; right: 0; bottom: clamp(1.25rem, 4vh, 2.5rem);
  display: flex; justify-content: center;
}
/* The way out is held back until the field is mostly behind you — offered at
   the top it reads as a way past the work rather than a way on from it. The
   gate is added by the script, so without one the pill is simply there. */
.deeper.is-gated { opacity: 0; pointer-events: none; transition: opacity .7s var(--ease); }
.deeper.is-gated.is-ready { opacity: 1; pointer-events: auto; }
.deeper__link {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .28em; text-transform: uppercase;
  padding: .85rem 1.7rem;
  background: var(--tone);
  border: 1px solid var(--rule); border-radius: 999px;
  transition: background-color .45s var(--ease), color .45s var(--ease), border-color .45s var(--ease);
}
.deeper__link::after { content: "\2193"; margin-left: .8em; letter-spacing: 0; }
.deeper__link:hover, .deeper__link:focus-visible {
  background: var(--ink); color: var(--tone); border-color: var(--ink);
}

/* --- 5 · in conversation --------------------------------------------------
   Set as an editorial: an opening frame that holds while the article wipes up
   over it, a bar that fills as you read, and a ground the reader chooses.
   -------------------------------------------------------------------------- */
.convo { position: relative; }

/* The bar along the top, while the piece is being read. */
.convo__progress {
  position: fixed; top: var(--masthead-h); left: 0; right: 0; z-index: 70;
  height: 4px;
  opacity: 0; pointer-events: none;
  transition: opacity .5s var(--ease);
}
.convo__progress.is-live { opacity: 1; }
.convo__progress-bar {
  display: block; height: 100%; width: 100%;
  background: var(--ink);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: background-color .5s linear;
}

/* --- the opening frame ---------------------------------------------------- */
/* Twice the frame tall, so the sticky image holds for one screen while the
   article, pulled back up by the same amount, wipes over it. */
.convo__hero { position: relative; height: calc(var(--vh-frame) * 2); }
.convo__hero-frame {
  position: sticky; top: var(--masthead-h);
  height: var(--vh-frame); overflow: clip;
}
.convo__hero-frame > img { width: 100%; height: 100%; object-fit: cover; }
.convo__hero-shade {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(6, 12, 10, .52), rgba(6, 12, 10, .18) 46%, rgba(6, 12, 10, .5));
}
/* The title sits low, clear of the subject, the way a cover carries it. */
.convo__hero-copy {
  position: absolute; inset: 0; z-index: 2;
  display: grid; align-content: start; justify-items: center;
  padding: var(--gutter);
  padding-top: clamp(3.5rem, 15svh, 11rem);
  text-align: center;
}
.convo__kicker {
  font-family: var(--ui); font-weight: 500;
  font-size: var(--fs-micro); letter-spacing: .3em; text-transform: uppercase;
  color: rgba(255, 255, 255, .8);
  margin-bottom: clamp(.5rem, 1.25vw, .9rem);
}
.convo__title {
  font-family: var(--serif);
  font-weight: 300;
  /* Sized off the viewport so the name holds a single line at every width. */
  font-size: clamp(1.5rem, 6.1vw, 6rem);
  line-height: 1.04;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
}

/* --- the article panel ---------------------------------------------------- */
/* Its own ground, chosen by the reader, so it overrides the page's tone for
   everything inside it. */
.convo__panel {
  --tone: #E7E8DD;
  --ink: #3A3B32;
  --ink-soft: #63645A;
  --ink-rgb: 58, 59, 50;

  position: relative; z-index: 2;
  margin-top: calc(var(--vh-frame) * -1);
  background: var(--tone); color: var(--ink);
  padding-block: clamp(3rem, 9vh, 6rem) clamp(5rem, 15vh, 11rem);
  transition: background-color .6s var(--ease), color .6s var(--ease);
}
.convo__panel[data-mode="dark"] {
  --tone: #2A3125;
  --ink: #CDD6C8;
  --ink-soft: #969F91;
  --ink-rgb: 205, 214, 200;
}
.convo .shell { max-width: 68rem; }

.convo__meta {
  display: flex; flex-wrap: wrap; gap: 1rem;
  align-items: center; justify-content: space-between;
  max-width: 60rem; margin: 0 auto clamp(2.5rem, 7vw, 4.5rem);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--rule);
}
.convo__theme { display: flex; }
.convo__theme button, .convo__share {
  font-family: var(--ui); font-weight: 500;
  font-size: var(--fs-micro); letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-soft);
  padding: .5rem .9rem;
  border: 1px solid transparent;
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.convo__theme button[aria-pressed="true"] { color: var(--ink); border-color: var(--rule); }
.convo__theme button:hover, .convo__share:hover { color: var(--ink); }
.convo__share { padding-inline: 0; }
.convo__share-note { margin-left: .8em; opacity: 0; transition: opacity .3s var(--ease); }
.convo__share-note.is-live { opacity: 1; }

.convo__lead, .convo__block { max-width: 60rem; margin-inline: auto; }
.convo__lead::after, .convo__block::after { content: ""; display: block; clear: both; }

/* The answers are set in the same voice as the questions; the questions carry
   the weight. */
.convo__lead p, .convo__block p {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(1.25rem, 2.2vw, 1.7rem);
  line-height: 1.5;
  letter-spacing: -.012em;
}
.convo .editorial__q { font-weight: 500; }
/* A figure sits between paragraphs, so the rhythm is set on the flow, not on
   adjacent paragraphs. */
.convo__lead > * + p, .convo__block > * + p { margin-top: 1.1em; }

/* --- the frames, in assorted breaks --------------------------------------- */
.convo__fig { margin: clamp(1.6rem, 4vw, 2.4rem) 0; }
.convo__fig img { width: 100%; }
.convo__fig--feature { clear: both; width: 100%; margin: clamp(2.6rem, 7vw, 4.5rem) 0; }

/* A short run of frames across the measure, top-aligned so the differing
   heights read as the break they are. */
.convo__row {
  clear: both;
  display: grid; align-items: start;
  gap: clamp(.8rem, 2.2vw, 1.6rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
  margin: clamp(2.6rem, 7vw, 4.5rem) 0;
}
.convo__row .convo__fig { margin: 0; }

@media (min-width: 52rem) {
  .convo__fig--right, .convo__fig--left { width: 38%; shape-outside: margin-box; }
  /* Each frame clears the last, so the column is never squeezed between two. */
  .convo__fig--right { float: right; clear: both; margin: .45rem 0 1.7rem clamp(1.7rem, 3.6vw, 3rem); }
  .convo__fig--left  { float: left;  clear: both; margin: .45rem clamp(1.7rem, 3.6vw, 3rem) 1.7rem 0; }
}

/* Folded, the next question is still showing — enough of it to be worth
   opening — and the way in sits over the point where it fades out. */
.convo__rest {
  --peek: clamp(9rem, 24vh, 15rem);
  display: grid; grid-template-rows: var(--peek);
  margin-top: clamp(2.8rem, 7vw, 4.5rem);
  transition: grid-template-rows .9s var(--slow);
}
.convo__rest[data-open="true"] { grid-template-rows: 1fr; }
.convo__rest-inner { overflow: hidden; min-height: 0; }
.convo__rest[data-open="false"] .convo__rest-inner {
  -webkit-mask-image: linear-gradient(180deg, #000 22%, rgba(0, 0, 0, 0) 96%);
  mask-image: linear-gradient(180deg, #000 22%, rgba(0, 0, 0, 0) 96%);
}
.convo__block { margin-top: clamp(2.8rem, 7vw, 4.5rem); }
.convo__rest-inner > .convo__block:first-child { margin-top: 0; }
.convo__rest .editorial__pull { max-width: 60rem; margin-inline: auto; }

.convo__action { position: relative; z-index: 2; margin-top: clamp(2.4rem, 6vw, 3.6rem); text-align: center; }
/* Closed, the button rides up over the fade. */
.convo__rest[data-open="false"] + .convo__action { margin-top: calc(var(--peek) * -.34); }
.convo__action .btn { background: var(--tone); }

@media (prefers-reduced-motion: reduce) {
  .inhome__slide, .convo__rest, .cursor, .convo__panel { transition: none; }
}

/* ==========================================================================
   The library — the collections
   A way in, then one collection per frame. Each frame is pinned and the next
   slides up over it, so the ground changes as you travel down through the work.
   ========================================================================== */

/* The way in. */
.gate { position: relative; height: var(--vh-frame); overflow: clip; }
/* Mirrored, so the room turns the same way as the one in the drawer. */
.gate__img { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }
.gate__shade {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(8, 12, 10, .18), rgba(8, 12, 10, 0) 38%, rgba(8, 12, 10, .42));
}
.gate__action {
  position: absolute; left: 0; right: 0; bottom: 17%; z-index: 2;
  display: flex; justify-content: center;
}
.gate__pill {
  display: inline-flex; align-items: center; gap: .9em;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .28em; text-transform: uppercase;
  color: #fff;
  padding: .95rem 1.8rem;
  border: 1px solid rgba(255, 255, 255, .6); border-radius: 999px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  background: rgba(10, 16, 14, .2);
  transition: background-color .45s var(--ease), color .45s var(--ease), border-color .45s var(--ease);
}
.gate__pill svg {
  width: 1.05em; fill: none; stroke: currentColor;
  stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
}
.gate__pill:hover, .gate__pill:focus-visible { background: #fff; color: #14171a; border-color: #fff; }

/* --- the collections ------------------------------------------------------ */
.library { position: relative; }

/* Half a frame taller than it shows, so each collection holds longer before
   the next covers it. The stack still works: the panels are siblings, so each
   one paints over the one before. */
.library__panel {
  position: sticky; top: var(--masthead-h);
  height: calc(var(--vh-frame) * 1.5);
  background: var(--tone); color: var(--ink);
  display: grid; grid-template-rows: 1fr auto;
  gap: clamp(2.2rem, 6vh, 4.5rem);
  padding: clamp(1.6rem, 4.5vh, 3rem)
           clamp(1rem, 3vw, 3.2rem)
           calc(var(--vh-frame) * .5 + clamp(2rem, 6vh, 4rem));
}

.library__grid {
  min-height: 0;
  display: grid;
  gap: clamp(2rem, 4.6vw, 4.2rem);
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1fr;
}
@media (max-width: 60rem) { .library__grid { grid-template-columns: repeat(2, 1fr); } }

/* The work keeps its own proportions — the row gives it a box, the art sits
   in the middle of it, and what is left over is air. */
.library__card { display: block; min-height: 0; }
/* The plate is the box the row gives; the art is absolutely centred inside it
   so its cap always resolves against a definite height and it can never grow
   past its cell, however the columns rewrap. */
.library__plate { position: relative; display: block; width: 100%; height: 100%; min-height: 0; }
.library__plate { --card-edge: clamp(5px, .75vw, 12px); }
.library__flat {
  position: absolute; inset: 0; margin: auto;
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  /* The margin a print carries. */
  border: var(--card-edge) solid #fff;
  box-shadow: 0 1.2rem 3rem rgba(8, 12, 10, .16);
  transition: transform 1.2s var(--slow), opacity .45s var(--ease);
}

/* --- the work on a wall, on hover --------------------------------------------
   Not a picture built to resemble the one behind the click: the same room, the
   same hanging, mounted by the same call the drawer uses, at the size and in
   the finish the drawer opens on. Hover and click therefore cannot show two
   different pictures.

   The room is kept at its own shape and sized to cover the card, because the
   cards are not all one shape — they run from about 1.96 to 2.07 wide — and a
   piece sized as a share of the card would come out differently on each. Then
   the whole thing is pushed in from its centre, so the card holds a closer
   view of the same photograph.
   ---------------------------------------------------------------------------- */
.library__plate { container-type: size; }

/* Built only where it can be used.

   A phone cannot hover, so this layer can never be shown on one, and the
   collection grid there is the print and its margin until the card is tapped —
   which opens the piece, where the work on a wall lives anyway.

   Hidden with display rather than left transparent, because the saving is the
   point: an image inside a display: none subtree gets no layout box, so a lazy
   one never fetches. The room photograph is 466 KB at 2560 wide, and it was
   being downloaded to every phone for something they could not see.

   Hiding it also means the states below have to be hidden with it. A phone can
   still reach a card by keyboard, and :focus-visible fading the thumbnail out
   with nothing behind it would leave the card blank. So the whole mechanism
   sits inside the one query — the layer, its geometry, and both the states
   that reveal it. */
.library__situ { display: none; }

@media (hover: hover) and (pointer: fine) {

/* The room takes the thumbnail's own box, not the cell's. The thumbnail is
   letterboxed inside the cell — 311 x 211 of a 311 x 276 plate on a card this
   size — so a layer filling the cell would swell into that spare height on
   hover. Sized from the content outwards, with the same white margin, so the
   two occupy the same rectangle and only the picture inside it changes. */
.library__situ {
  display: block;
  position: absolute; inset: 0; margin: auto;
  box-sizing: content-box;
  width: auto; height: auto;
  max-width: calc(100% - 2 * var(--card-edge));
  max-height: calc(100% - 2 * var(--card-edge));
  aspect-ratio: 420 / 278;
  /* The same rectangle the thumbnail occupies, but the margin is padding here
     rather than a white border, and that is the whole difference: overflow
     clips at the padding box, so the room paints out to the outer edge where a
     border would have held a white band in front of it. A print carries a
     margin and a photograph of a room does not. */
  padding: var(--card-edge);
  box-shadow: 0 1.2rem 3rem rgba(8, 12, 10, .16);
  overflow: hidden;
  opacity: 0;
  transition: opacity .5s var(--ease);
}
.library__scene {
  position: absolute; top: 50%; left: 50%;
  translate: -50% -50%;
  /* Covers however the card is shaped: wide enough for its width, and wide
     enough that its own height reaches the card's. */
  width: max(100%, calc(100cqh * 1.4997));
  aspect-ratio: 2560 / 1707;
  transition: transform 1.1s var(--slow);
}
.library__scene .scale__room { width: 100%; }
/* A thumbnail is the one place the floater will not draw itself.

   The frame there is about 130px for a 75in canvas, which leaves the quarter
   inch of shadow under a device pixel. So in a card, and only in a card, each
   band is given a floor of half a pixel — one device pixel at rest, 1.3 at the
   scale the hover runs at, and the hover is the only state a card is seen in.
   At this size the trim only has to say that there is a gap, and then a white
   frame.

   The white face is already above that floor at 0.852px, so it is drawn at its
   true half inch and the floor never reaches it. Only the shadow is held up.

   The ring the drawer and the piece page use is explicitly off here. This is
   settled at a size that took several passes to find, and a ring would widen
   the shadow again. */
.library__scene .scale__gap {
  inset: max(var(--gap-y, 0px), .5px) max(var(--gap-x, 0px), .5px);
}
.library__scene .scale__mat {
  inset: max(var(--art-y, 0px), calc(max(var(--gap-y, 0px), .5px) + .5px))
         max(var(--art-x, 0px), calc(max(var(--gap-x, 0px), .5px) + .5px));
}
/* Written to outrank the framed ring rather than merely to follow it: that one
   carries an attribute selector, so a plainer one here would lose however late
   it came in the file. */
.library__scene .scale__hang[data-framed="true"] .scale__mat { box-shadow: none; }
/* Nothing in a card is turned, so the hang keeps the room's own light. */
.library__scene .scale__hang { transition: none; }

.library__card:hover .library__flat { opacity: 0; transform: translateY(-.35rem); }
.library__card:hover .library__situ { opacity: 1; }
.library__card:hover .library__scene { transform: scale(1.3); }

.library__card:focus-visible .library__flat { opacity: 0; }
.library__card:focus-visible .library__situ { opacity: 1; }
.library__card:focus-visible .library__scene { transform: scale(1.3); }

}  /* (hover: hover) and (pointer: fine) */

@media (prefers-reduced-motion: reduce) {
  .library__situ { transition: opacity .3s linear; }
  .library__scene { transition: none; }
}

/* Name and note on one line, the note held to the right. */
.library__foot {
  display: grid; gap: .6rem 2rem;
  grid-template-columns: 1fr auto 1fr;
  align-items: baseline;
}
.library__name { grid-column: 1; }
.library__scroll { grid-column: 2; justify-self: center; }
.library__short { grid-column: 3; justify-self: end; }
.library__name {
  font-family: var(--serif); font-weight: 300;
  font-size: clamp(1.6rem, 4.4vw, 3.4rem); line-height: 1;
  letter-spacing: -.02em;
}
.library__short {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--ink-soft); text-align: right;
}

/* Over the work the pointer says what a click does. */
@media (hover: hover) and (pointer: fine) {
  .library__card { cursor: none; }
}

/* One way down, on the first collection only. */
.library__scroll {
  display: inline-flex; align-items: center; gap: .55em;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .26em; text-transform: uppercase;
  color: var(--ink-soft);
}
.library__scroll svg {
  width: 1em; fill: none; stroke: currentColor;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  animation: nudge 2.4s var(--ease) infinite;
}
@keyframes nudge {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(.22em); }
}
@media (prefers-reduced-motion: reduce) { .library__scroll svg { animation: none; } }

/* Stacked, they read in turn: the collection, its note, then the way down.
   The cue is last in the column though it sits between them in the source. */
@media (max-width: 46rem) {
  .library__foot { grid-template-columns: 1fr; }
  .library__name, .library__short { grid-column: 1; justify-self: start; text-align: left; }
  .library__scroll { grid-column: 1; }
  .library__name { order: 1; }
  .library__short { order: 2; }
  .library__scroll { order: 3; }
}

/* --- the small print -------------------------------------------------------
   Long-form reading rather than the site's display voice: a measure that
   stops where the eye wants it to, and headings that separate without
   shouting.
   -------------------------------------------------------------------------- */
.foot__legal { display: flex; flex-wrap: wrap; gap: 1.1rem; }
.foot__legal a { color: var(--ink-soft); transition: color .3s var(--ease); }
.foot__legal a:hover, .foot__legal a:focus-visible,
.foot__legal a[aria-current="page"] { color: var(--ink); }

.legal__inner { max-width: 38rem; margin-inline: auto; }
.legal__title {
  margin-top: .8rem;
  font-family: var(--serif); font-weight: 300;
  font-size: clamp(1.9rem, 5vw, 3.1rem); line-height: 1.1;
}
.legal__stamp {
  margin-top: .7rem;
  font-family: var(--ui); font-weight: 500;
  font-size: var(--fs-micro); letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-soft);
}
.legal__h {
  margin-top: clamp(2.2rem, 6vh, 3.4rem);
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.1rem, 2.2vw, 1.35rem); line-height: 1.3;
}
.legal p, .legal__list {
  margin-top: 1rem;
  font-weight: 300; line-height: 1.7; color: var(--ink-soft);
}
.legal__h + p { margin-top: .7rem; }
.legal__list { padding-left: 1.1rem; }
.legal__list li { list-style: disc; margin-top: .5rem; }
.legal strong { font-weight: 500; color: var(--ink); }

/* --- the cart -------------------------------------------------------------
   Open editions only. It keeps the drawer's shape, so what is in the cart is
   read the same way as what is being chosen.
   -------------------------------------------------------------------------- */
.nav__cart[hidden] { display: none; }
.nav__cart [data-cart-count] { font-variant-numeric: tabular-nums; }
.nav__cart [data-cart-count]::before { content: "("; }
.nav__cart [data-cart-count]::after { content: ")"; }

.cart__empty { font-weight: 300; color: var(--ink-soft); margin-top: clamp(1.4rem, 4vh, 2.2rem); }

.cart__list { margin-top: clamp(1.4rem, 4vh, 2.2rem); text-align: left; }
.cart__line {
  padding: clamp(.9rem, 2.6vh, 1.2rem) 0;
  border-top: 1px solid var(--rule);
}
.cart__line:last-child { border-bottom: 1px solid var(--rule); }
/* The detail sits under the picture rather than beside it, because the
   picture now runs the full width of the rule above it. */
.cart__foot {
  display: grid; grid-template-columns: 1fr auto;
  gap: clamp(.8rem, 3vw, 1.2rem); align-items: start;
  margin-top: clamp(.7rem, 2vh, 1rem);
}
.cart__thumb { display: block; width: clamp(3.4rem, 14vw, 4.4rem); }
.cart__thumb img { display: block; width: 100%; height: auto; }

/* --- the two views ---------------------------------------------------------
   The work as it is mounted, and the work on a wall. Used by a cart line and
   by the quick-shop drawer, which is why it is named for neither. One box for
   both pictures, at the room's own 3:2, so a chevron changes the picture and
   never the layout — nothing below it moves when the view flips.
   -------------------------------------------------------------------------- */
.shots { position: relative; width: 100%; aspect-ratio: 3 / 2; }
.shots__shot {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  opacity: 0; visibility: hidden;
  transition: opacity .45s var(--ease), visibility 0s linear .45s;
}
.shots__shot[data-live="true"] {
  opacity: 1; visibility: visible;
  transition: opacity .45s var(--ease), visibility 0s;
}
.shots__shot--room .scale__room { width: 100%; }

/* The mounted work on its own: the same object the room hangs, lifted out of
   it. Static rather than pinned to a wall, and sized off the box's height so
   that a square 8 x 8 and a 2:3 40 x 60 come out the same weight. */
/* Doubled up on purpose. The hung-on-a-wall rules live further down the
   sheet, so a single class here would lose on source order and the work would
   be drawn at its wall size — a few percent of the box, a sliver.

   Used in two places: the cart line, and the viewer's first frame. It still
   turns about its own middle, so the quarter-turn works off the wall as well
   as on it; the width and aspect transitions go, because nothing here is
   resizing between one size and the next. */
.scale__hang.scale__hang--plain {
  position: relative; left: auto; top: auto;
  transform: rotate(var(--rot-deg, 0deg));
  width: auto; height: auto;
  box-shadow: 0 .7rem 1.8rem rgba(8, 12, 10, .18);
  transition: transform .6s var(--slow);
}
/* Sized by its long side, not its height: 80% of the stage's short side,
   whatever shape the piece is. Two things fall out of that. A quarter turn
   stays inside the box — at a flat 74% height a 3:2 piece turned a quarter
   stood 11% taller than the stage and ran into the type below it. And every
   piece reads at one scale, so a square 16 x 16 and a 40 x 60 are shown with
   the same authority instead of the wide one dominating the list. */
.shots__shot .scale__hang--plain { height: calc(80% / max(var(--ar, 1), 1)); max-width: 88%; }
/* In the viewer it is cut to the frame by JS, and wears the same lift the
   room plate does beside it. Placed by transform rather than by the grid,
   which would shunt an overflowing turn to the start. */
.zoom__frame--art .scale__hang--plain {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%) rotate(var(--rot-deg, 0deg));
  box-shadow: 0 1.4rem 3.4rem rgba(8, 12, 10, .22);
}
/* The floater's shadow line is drawn twice in the room, where the leftover
   between two rounded boxes can vanish on an edge. Here the work is drawn
   several times larger and the rectangle is comfortably over a pixel on all
   four sides, so the ring has nothing left to rescue and would only thicken
   what is already true. */
.scale__hang.scale__hang--plain[data-framed="true"] .scale__mat { box-shadow: none; }

/* The chevrons sit at the edges, on the drawer's own ground, so they can be
   drawn in ink. Above the zoom button, which covers the whole picture — a
   chevron under it would open the viewer instead of turning the page. */
.shots__chev {
  position: absolute; z-index: 5;
  display: grid; place-items: center;
  top: 50%; transform: translateY(-50%);
  width: 2.2rem; height: 2.2rem;
  color: var(--ink-soft); opacity: .55;
  transition: opacity .3s var(--ease), color .3s var(--ease);
}
.shots__chev:hover, .shots__chev:focus-visible { opacity: 1; color: var(--ink); }
.shots__chev--prev { left: -.35rem; }
.shots__chev--next { right: -.35rem; }
.shots__chev svg { width: 1.05rem; height: 1.05rem; fill: none; stroke: currentColor; stroke-width: 1.4; }

@media (prefers-reduced-motion: reduce) {
  .shots__shot { transition: none; }
}
.cart__piece { font-family: var(--serif); font-weight: 400; font-size: 1.05rem; line-height: 1.25; }
.cart__spec {
  margin-top: .2rem;
  font-family: var(--ui); font-weight: 500; font-size: var(--fs-micro);
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft);
}
.cart__cost { font-weight: 400; white-space: nowrap; }

.cart__qty { display: flex; align-items: center; gap: .55rem; margin-top: .6rem; }
.cart__qty button {
  display: grid; place-items: center;
  width: 1.7rem; height: 1.7rem;
  border: 1px solid var(--rule); color: var(--ink-soft);
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.cart__qty button:hover, .cart__qty button:focus-visible { border-color: var(--ink); color: var(--ink); }
.cart__qty > span { min-width: 1.4em; text-align: center; font-variant-numeric: tabular-nums; }
/* Scoped past .cart__qty button, which would otherwise hold it to the width
   of a stepper and clip the word. */
.cart__qty .cart__drop {
  margin-left: auto; border: 0; width: auto; height: auto;
  font-size: .82rem; color: var(--ink-soft);
}
.cart__qty .cart__drop:hover, .cart__qty .cart__drop:focus-visible { color: var(--ink); }

.cart__sum {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: clamp(1.2rem, 3.4vh, 1.8rem);
  font-family: var(--serif); font-size: 1.1rem;
}
.cart__note { margin-top: .5rem; font-size: .86rem; font-weight: 300; color: var(--ink-soft); }
/* The wait, on the line it belongs to rather than as a note about the order. */
.cart__scan {
  margin-top: .2rem;
  font-family: var(--ui); font-weight: 500;
  font-size: .54rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}
.cart [data-cart-status]:empty { display: none; }
.cart [data-cart-status] { margin-top: 1rem; }

/* --- a link to a frame that has gone ---------------------------------------
   Said plainly and centred, rather than quietly showing a different
   photograph under the link someone followed.
   -------------------------------------------------------------------------- */
.gone { display: grid; place-items: center; min-height: 60svh; }
.gone__inner { max-width: 34rem; margin-inline: auto; text-align: center; }
.gone__title {
  font-family: var(--serif); font-weight: 300;
  font-size: clamp(1.9rem, 5vw, 3.1rem); line-height: 1.1;
}
/* Side by side where there is room, stacked where there is not. */
.gone__links {
  margin-top: clamp(1.4rem, 4vh, 2.2rem);
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: .6rem clamp(1.4rem, 4vw, 2.4rem);
}

/* --- after the payment ----------------------------------------------------- */
.order__inner { max-width: 34rem; margin-inline: auto; text-align: center; }
.order__title {
  margin-top: .8rem;
  font-family: var(--serif); font-weight: 300;
  font-size: clamp(1.9rem, 5vw, 3.1rem); line-height: 1.1;
}
.order__wait { margin-top: clamp(1.4rem, 4vh, 2.2rem); font-weight: 300; color: var(--ink-soft); }
.order__list { margin-top: clamp(1.8rem, 5vh, 2.8rem); text-align: left; }
.order__line {
  display: grid; grid-template-columns: auto 1fr auto;
  gap: clamp(.8rem, 3vw, 1.2rem); align-items: center;
  padding: clamp(.9rem, 2.6vh, 1.2rem) 0;
  border-top: 1px solid var(--rule);
}
.order__line:last-child { border-bottom: 1px solid var(--rule); }
.order__note {
  margin-top: clamp(1rem, 3vh, 1.6rem);
  font-weight: 300; color: var(--ink-soft); text-align: left;
}

/* The confirmation's own word about the wait, set apart from the receipt
   above it so it reads as the studio speaking rather than another line of
   the order. */
.order__scan {
  margin-top: clamp(1.2rem, 3vh, 1.8rem);
  padding-top: clamp(1.2rem, 3vh, 1.8rem);
  border-top: 1px solid var(--rule-faint);
}
.order__scan-h { font-size: 1.05rem; font-weight: 300; }
.order__scan-b {
  margin-top: .55rem;
  font-weight: 300; line-height: 1.7; color: var(--ink-soft);
  font-size: .95rem;
}
.order .cart__sum { text-align: left; }

/* --- quick shop ----------------------------------------------------------- */
/* A narrow drawer that scrolls: the piece, centred, with the choices and the
   cart beneath it. */
.sheet--wide .sheet__panel {
  width: min(100%, 32rem);
  overflow-y: auto;
  padding: clamp(3rem, 8vh, 4.9rem) clamp(1.25rem, 4vw, 2rem) clamp(2.5rem, 8vh, 4rem);
  text-align: center;
}
.quickshop { display: block; }

.quickshop__name {
  font-family: var(--ui); font-weight: 500;
  font-size: clamp(1rem, 1.6vw, 1.2rem); line-height: 1.35;
  letter-spacing: .3em; text-transform: uppercase;
}
.quickshop__serial {
  margin-top: .55rem;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .3em; text-transform: uppercase; color: var(--ink-soft);
}

/* The work, at the width of the column. In flow, so nothing can lie over the
   controls beneath it. */
.quickshop__frame { margin: clamp(1rem, 3vh, 1.5rem) 0 0; }
.quickshop__frame img {
  display: block; width: 100%; height: auto;
  border: clamp(5px, .9vw, 10px) solid #fff;
  box-shadow: 0 1rem 2.6rem rgba(8, 12, 10, .16);
}

.quickshop .modes { margin-top: clamp(2rem, 5vh, 3.2rem); }
.quickshop .sizes { margin-top: clamp(.9rem, 2.4vh, 1.3rem); }
.quickshop__cta {
  width: 100%; justify-content: center;
  display: inline-flex; align-items: center; gap: .9em;
  margin-top: clamp(1.6rem, 4vh, 2.6rem);
}
.quickshop .buy__note { margin-top: .9rem; }
.quickshop__more { margin-top: clamp(1rem, 2.6vh, 1.4rem); }
.quickshop__more a { font-size: .86rem; }

.quickshop__ask { text-align: left; }
.quickshop__ask .form { margin-top: clamp(1.2rem, 3vh, 2rem); }
.quickshop__ask .quickshop__name,
.quickshop__ask .quickshop__serial { text-align: center; }


/* ==========================================================================
   A piece
   The details are held at the left while every image of the work runs past
   them in one column. The enquiry opens over the page rather than under it.
   ========================================================================== */
.work { padding-top: clamp(.75rem, 2.5vh, 1.75rem); }

.work__layout {
  display: grid; grid-template-columns: 1fr;
  gap: clamp(2.5rem, 7vw, 5rem);
  max-width: 96rem; margin-inline: auto;
  padding-inline: var(--gutter);
}
@media (min-width: 60rem) {
  .work__layout {
    grid-template-columns: minmax(15rem, 20rem) 1fr;
    gap: clamp(3rem, 9vw, 9rem);
  }
  .work__info {
    position: sticky; align-self: start;
    top: calc(var(--masthead-h) + clamp(1.5rem, 6vh, 4rem));
  }
}

.work__eyebrow {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-soft);
}
.work__name {
  margin-top: clamp(1.6rem, 5vh, 3rem);
  font-family: var(--ui); font-weight: 500;
  font-size: clamp(1.15rem, 1.9vw, 1.6rem);
  line-height: 1.35;
  letter-spacing: .3em; text-transform: uppercase;
}
.work__serial {
  margin-top: .9rem;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-soft);
}
.work__spec {
  margin-top: 1.5rem;
  font-family: var(--serif); font-weight: 300; line-height: 1.6;
  color: var(--ink-soft);
}

.work .modes { margin-top: clamp(2rem, 6vh, 3.2rem); }
.work .mode-panel { margin-top: 1.4rem; }
.work .pdp__price { margin-top: 1.1rem; }

.work__inquire { margin-top: clamp(1.8rem, 5vh, 2.8rem); }
.work__inquire .btn { width: 100%; justify-content: center; }

/* One column, the work first and everything else under it. */
.work__images { display: grid; gap: clamp(1.5rem, 5vh, 4rem); align-content: start; }
.work__images figure { margin: 0; }
.work__images img { width: 100%; background: var(--rule-faint); }
.scale figcaption,
.work__images figcaption {
  margin-top: .7rem;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--ink-soft);
}

/* --- the enquiry, in the window ------------------------------------------- */
.sheet { position: fixed; inset: 0; z-index: 100; display: grid; }
.sheet[hidden] { display: none; }
.sheet__scrim {
  position: absolute; inset: 0;
  background: rgba(8, 12, 10, .5);
  opacity: 0; transition: opacity .45s var(--ease);
}
.sheet.is-open .sheet__scrim { opacity: 1; }
.sheet__panel {
  position: relative; z-index: 2;
  justify-self: end; width: min(100%, 32rem);
  height: 100%; overflow-y: auto;
  background: var(--tone); color: var(--ink);
  padding: clamp(2rem, 6vh, 3.5rem) clamp(1.5rem, 4vw, 3rem);
  transform: translateX(100%);
  transition: transform .55s var(--slow);
}
.sheet.is-open .sheet__panel { transform: none; }
.sheet__close {
  position: absolute; top: clamp(1rem, 3vh, 1.6rem); right: clamp(1rem, 3vw, 1.6rem);
  width: 2.4rem; height: 2.4rem; display: grid; place-items: center;
}
.sheet__close svg { width: 1rem; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; }
/* The piece comes with you into the enquiry: what you chose, at a glance. */
.sheet__card {
  display: grid; grid-template-columns: auto 1fr;
  gap: clamp(.8rem, 3vw, 1.2rem);
  align-items: center;
  margin: .9rem 0 clamp(1.6rem, 4vh, 2.4rem);
  padding: clamp(.7rem, 2.6vw, 1rem);
  background: rgba(var(--ink-rgb), .06);
}
.sheet__thumb { display: block; width: clamp(3.4rem, 14vw, 4.4rem); }
.sheet__thumb img { display: block; width: 100%; height: auto; }
.sheet__detail p {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  line-height: 1.7; color: var(--ink-soft);
}
/* The price closes the summary, so it carries the ink rather than the soft. */
.sheet__detail .sheet__price { margin-top: .35rem; color: var(--ink); }
.sheet__detail .sheet__price[hidden] { display: none; }
.sheet__detail .sheet__piece {
  margin: 0 0 .2rem;
  font-family: var(--serif); font-weight: 400;
  font-size: 1.1rem; line-height: 1.25;
  letter-spacing: normal; text-transform: none;
  color: var(--ink);
}
.sheet .form { max-width: none; }

@media (max-width: 46rem) {
  .sheet__panel { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .sheet__panel, .sheet__scrim { transition: none; }
}

/* --- the work, to scale ----------------------------------------------------
   The room is a photograph; the piece on the wall is not. It is sized from the
   real print dimensions against a measured px-per-inch, so every size is exact
   and a new size needs no new photography.
   -------------------------------------------------------------------------- */
/* The room measures its own shadow.

   The hang is positioned in percentages of this box, so the frame scales with
   the room wherever the room appears — a card, the drawer, the zoom overlay.
   The shadow under it did not: it was a rem constant, the same number of pixels
   in all three. On the card, whose room is about 1.7 times smaller than the
   drawer's, that put a blur 19.5% of the frame's width against the drawer's
   11.3%, and under a white floater it read as a dirty, thicker frame — the
   hover and the piece it opens showing two different objects.

   So the shadow is measured in the room too. Calibrated against the drawer at
   1440: 7.2 / 6.4 / 25.6px of a 731px room. */
/* display: block is load-bearing, not tidying. The drawer's room is a <div>
   and a card's is a <span>, and container-type is ignored on a non-atomic
   inline — so the card's shadow measured itself against .library__plate, the
   next container up, and came out 3.5% adrift from the drawer's. The same
   inline was quietly swallowing the width: 100% set on it further up. */
.scale__room { position: relative; display: block; container-type: inline-size; }
/* The room reads left to right: the window, and so the light, sits on the
   left. Mirroring the plate keeps one photograph doing both jobs. */
.scale__plate { display: block; width: 100%; height: auto; transform: scaleX(-1); }

.scale__hang {
  position: absolute;
  /* 48% on the unmirrored plate, so 52% once it is flipped. The small sizes
     hang in a crop of the same photograph, where the point sits elsewhere, so
     JS writes it; these are the wide plate's numbers and the fallback. */
  left: var(--hang-x, 52%); top: var(--hang-y, 51.6%);
  /* The whole object turns together, about its own centre. */
  transform: translate(-50%, -50%) rotate(var(--rot-deg, 0deg));
  width: var(--art-w, 24.36%);
  aspect-ratio: var(--art-ratio, 3 / 2);
  /* A print's white paper margin; under a canvas this is the floater. */
  background: #fff;
  /* Counter-rotated as the piece turns, so the light stays where the room put it.
     The blur carries --room-k for the same reason the offsets do: in the near
     room the wall is 1.29x nearer, so the frame and everything it throws is
     1.29x larger. */
  box-shadow: var(--sh-x, .985cqi) var(--sh-y, .875cqi)
              calc(3.501cqi * var(--room-k, 1)) rgba(8, 12, 10, .26);
  transition: width .7s var(--slow), aspect-ratio .7s var(--slow),
              transform .6s var(--slow), background-color .5s var(--ease);
}
/* The insets sit on a wrapper: an absolutely positioned <img> is a replaced
   element, so it would take its intrinsic width and ignore the right inset. */
.scale__mat {
  position: absolute;
  inset: var(--art-y, 0) var(--art-x, 0);
  overflow: hidden;
  /* Only ever seen before the work has painted. The floater's shadow is a
     filled rectangle sitting just outside this box, not a ring, so without
     something over it a canvas comes up as a solid black panel for as long as
     the image takes — nothing at room scale, a 240px block in the cart. */
  background: #fff;
}
.scale__art { display: block; width: 100%; height: 100%; object-fit: cover; }

/* The shadow gap a floater leaves between the frame and the canvas edge.
   True to the inch: half an inch of face, then a quarter inch of shadow. */
.scale__gap {
  display: none; position: absolute;
  inset: var(--gap-y, 0) var(--gap-x, 0);
  background: #14120f;
}
/* The floater, in whichever finish is selected. The fallback is the maple
   this was before there was a choice. */
.scale__hang[data-framed="true"] { background: var(--floater, #c8ab82); }
.scale__hang[data-framed="true"] .scale__gap { display: block; }
/* The shadow gap, drawn a second time as a ring on the artwork's own box.

   Framed only, with the rectangle above it — a print has a white paper margin
   and no shadow at all, so a ring on a print is a black line around a
   photograph that should not have one.

   Why twice: the rectangle gives a band that is whatever is left between two
   independently positioned boxes, and each box rounds its own four edges to
   the pixel grid on its own. At the sizes the drawer and the piece page draw
   the room at that leftover is about 1.5 device pixels, and the rounding is
   enough to take it away altogether on an edge or two — and a floater missing
   its shadow line on two sides stops reading as a floater. A ring has no such
   argument: inner edge the artwork's edge, outer edge one width out, on all
   four sides by construction. The rectangle stays behind it, where it can only
   add to the dark.

   The width is the true quarter inch, as a share of the room: 0.25in at
   0.4059% of the room's width per inch is 0.1015cqi. That is 0.742px against
   the piece page's 731px room where the rectangle measures 0.734, and 1.154
   against the zoom overlay's 1.148 — nothing thickened, only made even. The
   0.75px floor is for the drawer, whose room is 448px and whose gap would
   otherwise be 0.9 of a device pixel. */
.scale__hang[data-framed="true"] .scale__mat {
  box-shadow: 0 0 0 max(calc(.1015cqi * var(--room-k, 1)), .75px) #14120f;
}

@media (prefers-reduced-motion: reduce) {
  .scale__hang { transition: none; }
}


/* --- the edition mark ------------------------------------------------------ */
.size__name { display: inline-flex; align-items: center; gap: .65em; }
.edition {
  display: inline-grid; place-items: center;
  width: 1.85em; height: 1.85em;
  border: 1px solid currentColor; border-radius: 50%;
  font-size: .68em; font-weight: 500; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  opacity: .8;
}

/* --- a piece, on the small screens ----------------------------------------
   The two columns become one, and the first frame is set between the serial
   and the format, so what you are choosing sits right above the choice.
   -------------------------------------------------------------------------- */
@media (max-width: 59.999rem) {
  .work__info, .work__images { display: contents; }
  .work__images > :first-child { order: 1; }
  /* Half the gap, so the format sits close under what it is sizing. */
  .work__info-body { order: 2; margin-top: calc(clamp(2.5rem, 7vw, 5rem) * -.5); }
  .work__images > :not(:first-child) { order: 3; }
}

/* --- view larger ------------------------------------------------------------
   The room carries a way through to the work on its own.
   -------------------------------------------------------------------------- */
.scale__zoom {
  position: absolute; inset: 0; z-index: 3;
  display: block; width: 100%; height: 100%;
  cursor: zoom-in;
}
.scale__zoom-tag {
  position: absolute; right: .55rem; bottom: .55rem;
  padding: .5rem .85rem;
  background: rgba(8, 12, 10, .62); color: #fff;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase;
  opacity: 0; transition: opacity .3s var(--ease);
}
.scale__zoom:hover .scale__zoom-tag,
.scale__zoom:focus-visible .scale__zoom-tag { opacity: 1; }

/* The word only ever appears under a pointer, so on a touch screen there is
   nothing to tell you the picture opens. There the button wears the chip the
   rotate control wears — same size, same ground, same corner height — with a
   glass instead of an arrow. */
.scale__zoom-chip { display: none; }
@media (hover: none) {
  .scale__zoom-tag { display: none; }
  .scale__zoom-chip {
    display: grid; place-items: center;
    position: absolute; right: .55rem; bottom: .55rem;
    width: 2.1rem; height: 2.1rem;
    border-radius: 999px;
    color: #fff; background: rgba(8, 12, 10, .5);
  }
  .scale__zoom-chip svg {
    width: 1.05rem; height: 1.05rem;
    fill: none; stroke: currentColor;
    stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  }
}

.zoom {
  position: fixed; inset: 0; z-index: 120;
  /* A column that shrink-wraps the picture and then sits the controls under
     it, the pair centred together. A grid row of 1fr would centre the picture
     in the row and leave the bar stranded at the foot of the screen. */
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(.8rem, 2vh, 1.4rem);
  /* What the picture does not get: the overlay's own padding, the gap under
     it, and the bar of controls. Named so the picture can be sized against
     the screen rather than against the box it is inside — that box is sized
     by the picture, so asking it how tall it is goes in a circle. */
  --zoom-chrome: calc(2 * clamp(1rem, 5vw, 4rem) + clamp(.8rem, 2vh, 1.4rem) + 2.8rem);
  /* How wide the picture ends up: whichever of the room, the ceiling, or the
     height budget runs out first. The bar takes the same, so its two ends
     stay on the picture's corners at every size. */
  --zoom-pic: min(100%, 76rem, calc((100svh - var(--zoom-chrome)) * 1.4997));
  padding: clamp(1rem, 5vw, 4rem);
  background: rgba(8, 12, 10, .9);
  opacity: 0; transition: opacity .4s var(--ease);
}
.zoom[hidden] { display: none; }
.zoom.is-open { opacity: 1; }
.zoom__scrim { position: absolute; inset: 0; cursor: zoom-out; }
.zoom__close {
  position: absolute; z-index: 3;
  top: clamp(1rem, 3vw, 1.8rem); right: clamp(1rem, 3vw, 1.8rem);
  width: 2.6rem; height: 2.6rem;
  display: grid; place-items: center; color: #fff;
}
.zoom__close svg {
  width: 1.1rem; fill: none; stroke: currentColor;
  stroke-width: 1.2; stroke-linecap: round;
}
@media (prefers-reduced-motion: reduce) { .zoom { transition: none; } }

/* --- turning the work ------------------------------------------------------ */
.scale__controls {
  position: absolute; z-index: 4;
  left: .55rem; bottom: .55rem;
  display: flex; gap: .4rem;
}
.scale__btn {
  height: 2.1rem; min-width: 2.1rem;
  display: inline-flex; align-items: center; justify-content: center;
  padding-inline: .5rem;
  color: #fff; background: rgba(8, 12, 10, .5);
  border-radius: 999px;
  transition: background-color .3s var(--ease);
}
.scale__btn:hover, .scale__btn:focus-visible { background: rgba(8, 12, 10, .8); }
.scale__btn svg {
  width: 1.05rem; flex: none;
  fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

/* The control names itself on arrival, then folds back to the icon. */
.scale__btn-label {
  max-width: 0; opacity: 0;
  overflow: hidden; white-space: nowrap;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  transition: max-width .55s var(--ease), opacity .35s var(--ease),
              margin-left .55s var(--ease);
}
.scale__btn.is-open .scale__btn-label { max-width: 6rem; opacity: 1; margin-left: .55em; }
@media (prefers-reduced-motion: reduce) {
  .scale__btn-label { transition: none; }
}

/* Turned upright, the work is laid out across and then rotated into the
   opening, so it still fills it exactly. */
/* --- the viewer ------------------------------------------------------------ */
.zoom { background: var(--tone); transition: opacity .4s var(--ease), background-color .5s linear; }
.zoom__stage {
  position: relative; z-index: 2; display: grid;
  width: 100%; flex: 0 1 auto; min-height: 0;
}
.zoom__frame {
  grid-area: 1 / 1;
  display: grid; place-items: center;
  min-width: 0; min-height: 0;
  opacity: 0; pointer-events: none;
  transition: opacity .45s var(--ease);
}
.zoom__frame[data-live="true"] { opacity: 1; pointer-events: auto; }

.zoom__frame--art > img {
  max-width: 100%; width: auto; height: auto;
  max-height: calc(100svh - var(--zoom-chrome));
  /* The margin a print carries, so the work reads as a work. */
  border: clamp(6px, .9vw, 14px) solid #fff;
  box-shadow: 0 1.4rem 3.4rem rgba(8, 12, 10, .22);
}
/* The room is given the plate's own 2560x1707 and a ceiling, so when the
   screen is short it narrows rather than running past the stage and under the
   controls. The hang inside is positioned in percentages of this box, so the
   box has to keep the picture's shape as it shrinks. */
.zoom__frame--room .scale__room {
  /* Narrowed by whichever runs out first, the width or the height. The plate
     is 2560 x 1707, so a height budget buys 1.4997 times as much width. */
  width: var(--zoom-pic);
}
.zoom__frame--room .scale__plate { box-shadow: 0 1.4rem 3.4rem rgba(8, 12, 10, .22); }

.zoom__arrow {
  position: absolute; top: 50%; z-index: 3;
  transform: translateY(-50%);
  width: clamp(2.4rem, 4vw, 3.4rem); aspect-ratio: 1;
  display: grid; place-items: center;
  color: var(--ink); opacity: .6;
  transition: opacity .3s var(--ease);
}
.zoom__arrow:hover, .zoom__arrow:focus-visible { opacity: 1; }
.zoom__arrow svg {
  width: 90%; fill: none; stroke: currentColor;
  stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round;
}
.zoom__arrow--prev { left: clamp(.4rem, 2vw, 1.4rem); }
.zoom__arrow--next { right: clamp(.4rem, 2vw, 1.4rem); }
.zoom__close { color: var(--ink); }

/* --- the way back to everything -------------------------------------------- */
.product-card__all {
  display: grid; place-items: center;
  background: none;
  border: 1px solid var(--rule);
  text-align: center; padding: 1rem;
  transition: border-color .35s var(--ease);
}
.product-card__all span {
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--ink-soft);
  transition: color .35s var(--ease);
}
.product-card--all:hover .product-card__all { border-color: var(--ink); }
.product-card--all:hover .product-card__all span { color: var(--ink); }

/* The same quarter turn, from inside the viewer. */
/* In the viewer the control keeps its name — there is room for it here. */
.zoom__rotate {
  flex: none;
  height: 2.6rem;
  display: inline-flex; align-items: center; gap: .6em;
  padding-inline: .9rem;
  border: 1px solid var(--rule); border-radius: 999px;
  color: var(--ink); opacity: .75;
  font-family: var(--ui);
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase;
  transition: opacity .3s var(--ease), border-color .3s var(--ease);
}
.zoom__rotate:hover, .zoom__rotate:focus-visible { opacity: 1; border-color: var(--ink); }
.zoom__rotate svg {
  width: 1rem; flex: none;
  fill: none; stroke: currentColor;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
/* Placed by transform rather than by the grid, so an oversized turn still
   sits dead centre. */
.zoom__frame--art { position: relative; }
.zoom__frame--art > img {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%) rotate(var(--zoom-deg, 0deg));
  transition: transform .6s var(--slow);
  /* The chosen size decides the shape here, the same way it does on the
     wall: a square print is shown square, cropped from the middle, so the
     larger view agrees with what will arrive. */
  object-fit: cover;
}

/* A second way through sits directly under the first. */
.pdp__cta + .pdp__cta,
.quickshop__cta + .quickshop__cta { margin-top: .55rem; }
.work__inquire .pdp__cta:first-child { margin-top: 0; }

/* The description runs the width of the column before it wraps. */
.mode-panel__material { max-width: none; }

/* ==========================================================================
   A · the label voice
   Labor Union is a display face: set upright in capitals, and given room to
   breathe between lines.
   ========================================================================== */
.label, .nav a, .btn, .serial, .mode,
.field label,
.convo__kicker, .convo__theme button, .convo__share,
.quickshop__name, .quickshop__serial,
.work__name, .work__serial,
.gate__pill, .hero__pill, .deeper__link,
.library__short, .library__scroll, .library__index,
.scale__btn-label, .scale__zoom-tag, .quickshop__count,
.cursor span, .foot__base, .filter a,
.form__status, .skip-link, .accordion summary,
.product-card__all span, .sheet__detail p,
.scale figcaption, .work__images figcaption {
  font-family: var(--ui);
  text-transform: uppercase;
  line-height: 1.7;
}

/* ==========================================================================
   The choices speak in the body face
   What is being chosen between is read rather than labelled, so the rows
   stay in Gambetta while the line above them and the caption under the work
   keep the label voice.
   ========================================================================== */
.size, .size__price, .size__note {
  font-family: var(--sans);
  text-transform: none;
}
.size__note { letter-spacing: .01em; }

/* --- the standing notice -----------------------------------------------------
   A line that drops from under the bar and folds back up behind it. It sits one
   step below the bar in the stack, so folding away is a disappearance behind
   something solid rather than a slide off the top of the screen — which is also
   why it is only ever shown once the bar has a ground of its own.

   Fixed rather than in flow: taking a line of height from the page and giving
   it back twenty seconds later would move the work under the reader twice.

   It takes its colour from the live ground like everything else. --ink holds
   well clear of --tone on every frame in the series, so the line stays legible
   from Surface through to Deep.
   ---------------------------------------------------------------------------- */
.shipbar {
  position: fixed; z-index: 89;
  top: var(--masthead-h); left: 0; right: 0;
  display: flex; flex-wrap: wrap;
  align-items: baseline; justify-content: center;
  gap: .3rem clamp(.9rem, 2.2vw, 1.8rem);
  padding: .72rem calc(var(--gutter) + 1.6rem);
  background: var(--tone);
  border-bottom: 1px solid var(--rule);
  transform: translateY(-100%);
  transition: transform .6s var(--slow), opacity .45s var(--ease),
              background-color .5s linear;
  will-change: transform;
}
.shipbar.is-open { transform: translateY(0); }
/* Scrolled back up, the bar above has gone transparent again and there is
   nothing left to fold into — sliding up would just be the line crossing the
   opening frame in plain sight. So it goes where it stands: the transform is
   held at rest and only the opacity moves. */
.shipbar.is-open.is-gone { opacity: 0; }

.shipbar__line,
.shipbar__link {
  font-family: var(--ui); font-weight: 500;
  font-size: var(--fs-micro); letter-spacing: .16em; text-transform: uppercase;
  line-height: 1.5;
}
.shipbar__line { color: var(--ink); }
.shipbar__link {
  color: var(--ink);
  padding-bottom: .12em;
  border-bottom: 1px solid rgba(var(--ink-rgb), .45);
  transition: border-color .35s var(--ease);
}
.shipbar__link:hover,
.shipbar__link:focus-visible { border-bottom-color: var(--ink); }

.shipbar__close {
  position: absolute; top: 50%; right: calc(var(--gutter) - .5rem);
  transform: translateY(-50%);
  width: 2rem; height: 2rem; display: grid; place-items: center;
  font-size: 1.1rem; line-height: 1;
  color: var(--ink-soft);
  background: none; border: 0; cursor: pointer;
}
.shipbar__close:hover,
.shipbar__close:focus-visible { color: var(--ink); }

/* Two lines rather than a clipped one where the sentence will not fit beside
   the link. The bar grows; nothing is cut. */
@media (max-width: 34rem) {
  .shipbar { padding-inline: calc(var(--gutter) + 1.2rem); }
  .shipbar__close { top: .55rem; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .shipbar { transition: none; }
}



/* --- floater finishes ---------------------------------------------------------
   Four chips in a row. The chip is the colour of the frame itself, so the
   choice is made by eye and watched in the room above rather than read.
   ------------------------------------------------------------------------------ */
/* The identity labels the picture, so it sits over it and shares its
   centre line rather than heading the column of controls. */
/* Inside the figure, over the picture it names. */
.piece__ident { text-align: center; margin-bottom: .75rem; }

/* The frame finishes, one row directly over the sizes, under a heading that
   covers both. Each takes an equal share of the row, so the five divide it
   evenly however wide it is.

   The names go when the row cannot hold them. A container query rather than a
   viewport one: this row sits in a 20rem column on the piece page, a wider
   panel in the drawer and a near-full-width bar in the larger view, so what
   matters is the room this row has, not the size of the screen around it.
   -------------------------------------------------------------------------- */
.framebar { margin: .55rem 0 .5rem; container-type: inline-size; }
/* Set to the same size as the names on the chips below it, so the heading and
   the row it introduces read as one small-caps family rather than two. */
.frames__h { margin-top: 1.2rem; margin-bottom: .55rem; font-size: .56rem; }
.frames { display: flex; gap: .4rem; }
.frame {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: .55em;
  padding: .55em .5em;
  border: 1px solid var(--rule); background: none;
  cursor: pointer;
  transition: border-color .3s var(--ease), background-color .3s var(--ease);
}
.frame:hover { border-color: rgba(var(--ink-rgb), .42); }
.frame[aria-checked="true"] { border-color: var(--ink); background: rgba(var(--ink-rgb), .05); }
.frame:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.frame__chip {
  width: 1.15rem; height: 1.15rem; flex: none;
  /* The grain, cut from the partner's photograph of that moulding. The flat
     colour sits behind it so the chip still reads before the tile loads. */
  background: var(--chip) var(--tex) center / cover no-repeat;
  box-shadow: inset 0 0 0 1px rgba(var(--ink-rgb), .28);
}
/* Chips alone until there is room for words. */
.frame__name { display: none; }
@container (min-width: 32rem) {
  .frame { justify-content: flex-start; padding-inline: .8em; }
  .frame__name {
    display: block;
    font-family: var(--ui); font-weight: 500;
    font-size: .56rem; letter-spacing: .14em; text-transform: uppercase;
    color: var(--ink-soft);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .frame[aria-checked="true"] .frame__name { color: var(--ink); }
}

/* The controls below the picture rather than over it: the finishes against
   its left edge, rotate against its right. The bar takes the same width the
   room image does, so both ends land on the picture however wide the screen
   is. Styled as they are in the drawer and on the piece page — the same
   control in a darker room.
   -------------------------------------------------------------------------- */
.zoom__bar {
  position: relative; z-index: 3;
  width: var(--zoom-pic);
  display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem;
}
.zoom__frames { flex: 1 1 auto; min-width: 0; container-type: inline-size; }
/* Wide enough that the longest name — Light Walnut — is not clipped at a
   fifth of it. */
.zoom__frames .frames { max-width: 44rem; }
.zoom__bar .frame { border-color: rgba(255, 255, 255, .28); }
.zoom__bar .frame:hover { border-color: rgba(255, 255, 255, .5); }
.zoom__bar .frame[aria-checked="true"] { border-color: #fff; background: rgba(255, 255, 255, .1); }
.zoom__bar .frame__name { color: rgba(255, 255, 255, .72); }
.zoom__bar .frame[aria-checked="true"] .frame__name { color: #fff; }
.zoom__bar .frame:focus-visible { outline-color: #fff; }

/* On the piece page the identity heads the column rather than captioning a
   centred drawer, so it sits against the picture's left edge. */
body[data-page="piece"] .piece__ident { text-align: left; }

/* --- the confirmation, read against the payment screen ------------------------
   Every figure that screen showed, in the order it showed them, so the two can
   be compared without arithmetic. Left aligned: a receipt is read down a
   column, not across a centred page.
   ---------------------------------------------------------------------------- */
.order__line-detail { min-width: 0; }
.order__line-cost {
  text-align: right; white-space: nowrap;
  font-weight: 300; font-variant-numeric: tabular-nums;
}
.order__qty { display: block; font-size: .8rem; color: var(--ink-soft); }

/* The number the customer quotes if they ever write in. Above the lines
   rather than buried under the totals: it is the first thing to find again on
   a page someone has scrolled back to, and the one part of a receipt that is
   of no use unless it is easy to see. Tabular figures so the four characters
   sit evenly, and selectable the way any reference should be. */
.order__ref {
  display: flex; align-items: baseline; justify-content: center; gap: .6em;
  margin-bottom: 1.2rem;
  padding-bottom: .9rem;
  border-bottom: 1px solid var(--rule-faint);
}
/* The number in the label voice, like the word in front of it. A little
   larger than the label and on looser letterspacing than the body face would
   want, because Labor Union is a display face and these are five characters
   someone will read out a character at a time. Tabular figures so the digits
   hold a column against the letters. */
.order__ref b {
  font-family: var(--ui);
  font-weight: 500;
  font-size: .78rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.order__totals { margin-top: 1.2rem; text-align: left; }
.order__row {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .45rem 0;
  font-weight: 300; font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.order__row--paid {
  margin-top: .3rem; padding-top: .8rem;
  border-top: 1px solid var(--rule);
  color: var(--ink); font-size: 1.05rem;
}

.order__where {
  margin-top: clamp(1.6rem, 4vh, 2.4rem);
  padding-top: clamp(1.2rem, 3vh, 1.6rem);
  border-top: 1px solid var(--rule-faint);
  text-align: left;
}
.order__addr {
  margin-top: .4rem;
  font-weight: 300; line-height: 1.6; color: var(--ink-soft);
}
.order__where .label + .order__addr { margin-top: .55rem; }
