/* ==========================================================================
   Design tokens
   The chrome carries no colour. White, near-black, two greys, one rule.
   Colour comes from the work on the wall and nowhere else.
   ========================================================================== */

@font-face { font-family: Outfit; src: url(assets/fonts/outfit-400.woff2) format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: Outfit; src: url(assets/fonts/outfit-500.woff2) format('woff2'); font-weight: 500; font-display: swap; }
@font-face { font-family: Outfit; src: url(assets/fonts/outfit-700.woff2) format('woff2'); font-weight: 700; font-display: swap; }

/* Native scrolling. In-page anchors ease; the sticky masthead is kept
   clear of every scroll target. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
html { scroll-padding-top: 84px; }

:root {
  --paper:  #ffffff;
  --ink:    #0f0f10;
  --muted:  #6b6d70;
  --line:   #e7e7e4;
  --fill:   #f6f6f4;   /* ground behind a plate, never behind text */

  /* Type scale — deliberate jumps, not four sizes chosen by feel. */
  --t-micro: 0.6875rem;
  --t-small: 0.8125rem;
  --t-body:  1rem;
  --t-lead:  1.1875rem;
  --t-h3:    1.375rem;
  --t-h2:    clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem);
  --t-h1:    clamp(3rem, 1.2rem + 7.4vw, 7.5rem);

  /* Spacing — 8px base, one ladder, used everywhere */
  --s1: 0.5rem;  --s2: 1rem;   --s3: 1.5rem;  --s4: 2rem;
  --s5: 3rem;    --s6: 4rem;   --s7: 6rem;    --s8: 9rem;

  --gutter: clamp(1.25rem, 0.6rem + 3vw, 4.5rem);
  --max:    88rem;

  /* The room between sections. Deliberately large — the page is meant to
     breathe, and the reveals need distance to be felt. */
  --band:   clamp(7rem, 3rem + 14vw, 16rem);

  --head:   4.5rem;                        /* sticky masthead height */
  --ease:   cubic-bezier(0.22, 1, 0.36, 1);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: Outfit, ui-sans-serif, system-ui, sans-serif;
  font-size: var(--t-body);
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.shell { max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.rule  { border: 0; border-top: 1px solid var(--line); margin: 0; }
.sr    { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.util {
  font-size: var(--t-micro); font-weight: 500;
  letter-spacing: 0.18em; text-transform: lowercase; color: var(--muted);
}

/* --------------------------------------------------- the link, everywhere
   A rule that draws itself left to right. This is the site's only "go here"
   affordance, so it has to be unmistakable and quick. */

.link {
  position: relative; display: inline-block;
  font-size: var(--t-small); font-weight: 500;
  text-transform: lowercase; padding-bottom: 3px;
}
.link::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform 320ms var(--ease);
}
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); }

.link--lg {
  font-size: clamp(1.25rem, 0.8rem + 1.8vw, 2rem);
  font-weight: 700; letter-spacing: -0.025em; padding-bottom: 6px;
}
.link--lg::after { height: 3px; }

/* --------------------------------------------------------------- masthead */

.masthead {
  position: sticky; top: 0; z-index: 30;
  background: var(--paper); border-bottom: 1px solid var(--line);
}
.masthead__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s4); height: var(--head);
}
.wordmark { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.025em; line-height: 1; text-transform: lowercase; transition: opacity 200ms ease; }
.wordmark:hover { opacity: 0.55; }
a:active { opacity: 0.55; }
.nav { display: flex; align-items: center; gap: clamp(1rem, 0.4rem + 1.6vw, 2.25rem); }
.nav a { font-size: var(--t-small); font-weight: 500; }
.nav .bag { font-variant-numeric: tabular-nums; }
.nav .link[aria-current='page']::after { transform: scaleX(1); }

/* ------------------------------------------------------------------- hero */

.hero {
  display: grid; align-items: center; gap: var(--s6);
  padding-block: clamp(2.25rem, 1rem + 3.5vw, 4rem) clamp(4rem, 2rem + 7vw, 8rem);
}
@media (min-width: 62rem) {
  .hero { grid-template-columns: 1fr 0.78fr; gap: clamp(3rem, 1rem + 6vw, 8rem); }
}
.hero__line {
  font-size: var(--t-h1); font-weight: 700; line-height: 0.94;
  letter-spacing: -0.045em; text-transform: lowercase; margin: var(--s3) 0 0;
}
.hero__cta { margin-top: clamp(2rem, 1rem + 3vw, 3.5rem); display: flex; gap: var(--s5); flex-wrap: wrap; align-items: baseline; }

/* The three facts, set quietly under the hero text. No boxes — the only
   corners on the site belong to the work. */
.facts {
  --fact-pad-x: clamp(1rem, 0.5rem + 1.2vw, 1.5rem);
  list-style: none; padding: 0;
  /* Pulled left by its own padding so the text still lines up with the
     headline above, even though each row is now a panel. */
  margin: clamp(2.5rem, 1.4rem + 3.2vw, 4rem) 0 0 calc(-1 * var(--fact-pad-x));
  display: grid; gap: clamp(0.5rem, 0.2rem + 0.8vw, 0.875rem);
  max-width: 34rem;
}
/* The panel is white on a white page, so nothing is visible at rest — the
   shadow is the only edge, and it only exists under the cursor. */
.fact {
  display: grid; grid-template-columns: 2.75rem 1fr; gap: var(--s3);
  align-items: baseline;
  padding: clamp(0.875rem, 0.5rem + 1vw, 1.25rem) var(--fact-pad-x);
  border-radius: 16px;
  background: transparent;
  transform-origin: left center;
  will-change: transform;
  transition: transform 550ms var(--ease), box-shadow 550ms var(--ease),
              background-color 550ms var(--ease);
}
/* Scoped under .facts deliberately: at plain `.fact:hover` this ties with
   `[data-reveal].is-in { transform: none }`, which comes later and wins, so
   the raise silently never happens. */
.facts .fact:hover {
  transform: translateY(-3px) scale(1.022);
  background: var(--paper);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 20px 44px -22px rgb(0 0 0 / 0.24);
}
.fact h3 { margin: 0 0 2px; font-size: var(--t-body); font-weight: 700; letter-spacing: -0.01em; text-transform: lowercase; }
.fact p { margin: 0; color: var(--muted); font-size: var(--t-small); max-width: 40ch; }

/* Capped so the 14-degree rotation has room to swing without the near edge
   crossing the gutter. */
.hero .plate-box { max-width: 30rem; margin-inline: auto; }
.plate-box {
  background: var(--fill); aspect-ratio: 4 / 5;
  display: grid; place-items: center;
  padding: clamp(1.75rem, 0.8rem + 4vw, 4rem);
}
/* ------------------------------------------------------------- carousel */
/* The hero rotates through six featured prints. Slides crossfade in place;
   the active dot stretches into a pill whose fill slides across for the
   length of the slide, then hands over to the next dot. */
/* Slides travel: the active print exits left as the next rides in from the
   right. Only the two moving slides carry a transition — everything else
   snaps back to its waiting position offscreen with no animation, so nothing
   streaks across the stage. The clip lives on the plate box, not the
   carousel: the box's padding is where the print's shadow falls, so the
   shadow renders whole and tilts with the print, while offstage slides
   park at 130% — beyond the padding — and stay hidden. */
[data-carousel] .plate-box { overflow: hidden; }
.carousel { position: relative; height: 100%; width: 100%; }
.carousel__slide {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  transform: translateX(130%);
  pointer-events: none;
}
.carousel__slide.is-active {
  transform: translateX(0); pointer-events: auto;
  transition: transform 760ms var(--ease); z-index: 2;
}
.carousel__slide.is-prev {
  transform: translateX(-130%);
  transition: transform 760ms var(--ease); z-index: 1;
}
.carousel__dots {
  display: flex; gap: 0.55rem; justify-content: center; align-items: center;
  margin-top: 1.15rem;
}
.carousel__dot {
  appearance: none; border: 0; padding: 0; cursor: pointer;
  width: 0.4rem; height: 0.4rem; border-radius: 999px;
  background: var(--line); position: relative; overflow: hidden;
  transition: width 480ms var(--ease), background 300ms var(--ease);
}
.carousel__dot:hover { background: var(--muted); }
.carousel__dot.is-active { width: 2.1rem; background: var(--line); cursor: default; }
.carousel__fill {
  position: absolute; inset: 0; border-radius: 999px;
  background: var(--ink);
  transform: scaleX(0); transform-origin: left center;
}
.carousel__dot.is-active .carousel__fill {
  animation: carousel-fill var(--carousel-dur, 5500ms) linear forwards;
}
@keyframes carousel-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) {
  /* no fill, no clock: the carousel holds still and the dots become plain tabs */
  .carousel__dot.is-active .carousel__fill { animation: none; transform: scaleX(1); }
  .carousel__slide.is-active, .carousel__slide.is-prev { transition: none; }
}

/* The hero poster carries its shadow permanently — it is the showpiece, and a
   plate lying flat on its ground reads as an image rather than an object. */
.plate-box img {
  height: 100%; width: auto;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 18px 40px -16px rgb(0 0 0 / 0.30);
  transition: box-shadow 400ms var(--ease);
}
.plate-box:hover img {
  box-shadow: 0 2px 4px rgb(0 0 0 / 0.07), 0 34px 62px -20px rgb(0 0 0 / 0.38);
}

/* ---------------------------------------------------------------- section */

.section { padding-block: var(--band); }
.section--tight { padding-block: calc(var(--band) * 0.55); }
.section__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s4); margin-bottom: clamp(2.5rem, 1rem + 4vw, 5rem); flex-wrap: wrap;
}
.section__title {
  margin: 0; font-size: var(--t-h2); font-weight: 700; line-height: 1.05;
  letter-spacing: -0.03em; text-transform: lowercase; max-width: 18ch;
}
.section__note { margin: 0; max-width: 38ch; color: var(--muted); font-size: var(--t-small); }

/* ------------------------------------------------------------- info tiles */

.tiles { display: grid; gap: var(--s3); }
@media (min-width: 52rem) { .tiles { grid-template-columns: repeat(3, 1fr); gap: var(--s4); } }

/* No boxes here either — an index, a title, a line of text, and a gentle
   raise under the cursor. */
.tile {
  display: flex; flex-direction: column; gap: var(--s3);
  transition: transform 500ms var(--ease);
}
/* Same specificity tie as .fact:hover — see the note there. */
.tiles .tile:hover { transform: translateY(-4px); }
.tile__index { font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.18em; color: var(--muted); }
.tile h3 { margin: 0 0 var(--s2); font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; text-transform: lowercase; }
.tile p { margin: 0; color: var(--muted); font-size: var(--t-small); max-width: 30ch; }

/* ------------------------------------------------------------ plate tiles */

.grid { display: grid; gap: var(--s5) var(--s3); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 62rem) { .grid { grid-template-columns: repeat(4, 1fr); gap: var(--s6) var(--s4); } }
.grid--three { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 62rem) { .grid--three { grid-template-columns: repeat(3, 1fr); } }

.card__frame {
  background: var(--fill);
  padding: clamp(1rem, 0.4rem + 2.4vw, 2.25rem);
  display: grid; place-items: center;
  aspect-ratio: 3 / 4; overflow: hidden;
  border: 1px solid transparent;
  transition: background-color 400ms var(--ease), border-color 400ms var(--ease);
}
.card__frame img { height: 100%; width: auto; object-fit: contain; transition: box-shadow 400ms var(--ease); }
.card:hover .card__frame { border-color: var(--line); }
.card:hover .card__frame img { box-shadow: 0 1px 2px rgb(0 0 0 / 0.05), 0 16px 34px -14px rgb(0 0 0 / 0.30); }
.card__body { margin-top: var(--s2); display: flex; justify-content: space-between; gap: var(--s2); align-items: baseline; }
.card__name { font-size: var(--t-small); font-weight: 500; text-transform: lowercase; }
.card__meta { font-size: var(--t-micro); color: var(--muted); margin-top: 2px; }
.card__price { font-size: var(--t-small); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ------------------------------------------------------------------- sets */

.set { display: grid; gap: var(--s5); }
@media (min-width: 62rem) { .set { grid-template-columns: 1.3fr 1fr; align-items: center; gap: clamp(3rem, 1rem + 6vw, 7rem); } }

.wall {
  background: var(--fill); aspect-ratio: 4 / 3;
  display: grid; place-items: center;
  padding: clamp(1rem, 0.3rem + 2.4vw, 2.25rem);
}
/* Sized by column width, not height: three 2:3 plates at full height need more
   width than the ground can give, and would overflow it. */
.wall__group { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(0.75rem, 0.2rem + 2vw, 2rem); align-items: center; width: 100%; }
.wall__group img {
  width: 100%; height: auto; max-height: 100%; object-fit: contain;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 14px 30px -14px rgb(0 0 0 / 0.26);
}
.set__copy p { color: var(--muted); max-width: 40ch; }
.set__price { margin-top: var(--s3); font-size: var(--t-small); }
.set__price s { color: var(--muted); margin-left: var(--s1); }

/* ------------------------------------------------------------ closing cta */

.closing { padding-block: var(--band); text-align: center; }
.closing__line {
  margin: 0 auto var(--s5); max-width: 14ch;
  font-size: clamp(2rem, 1rem + 4.4vw, 4.5rem); font-weight: 700;
  line-height: 0.98; letter-spacing: -0.04em; text-transform: lowercase;
}

/* ------------------------------------------------------------------ email */

.signup { display: grid; gap: var(--s4); }
@media (min-width: 48rem) { .signup { grid-template-columns: 1fr 1fr; align-items: end; gap: var(--s7); } }
.field { display: flex; gap: var(--s2); border-bottom: 1px solid var(--ink); padding-bottom: var(--s1); }
.field input { flex: 1; border: 0; background: none; font: inherit; color: inherit; padding: 0; }
.field input::placeholder { color: var(--muted); }
.field input:focus { outline: none; }
.field button { font-size: var(--t-small); font-weight: 500; white-space: nowrap; }

/* ----------------------------------------------------------------- footer */

.footer { border-top: 1px solid var(--line); padding-block: var(--s5); }
.footer__row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
.footer__nav { display: flex; gap: clamp(1rem, 0.4rem + 1.6vw, 2rem); flex-wrap: wrap; }
.footer__base { margin-top: var(--s4); display: flex; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }

/* ==================================================================== shop
   Deliberately not the homepage: no hero, no full-bleed type, tighter
   rhythm, a persistent filter rail, and an index that starts immediately.
   ==================================================================== */

.shopbar { border-bottom: 1px solid var(--line); padding-block: var(--s5) var(--s4); }
.shopbar__inner { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; }
.shopbar h1 { margin: 0; font-size: var(--t-h2); font-weight: 700; line-height: 1; letter-spacing: -0.03em; text-transform: lowercase; }
.shopbar__count { font-size: var(--t-small); color: var(--muted); font-variant-numeric: tabular-nums; margin: var(--s1) 0 0; }
.shopbar__sort { display: flex; gap: var(--s3); }

.catalogue { display: grid; gap: var(--s5); padding-block: var(--s5) var(--s8); }
@media (min-width: 62rem) {
  .catalogue { grid-template-columns: 12rem 1fr; gap: var(--s7); }
  .filters { position: sticky; top: calc(var(--head) + var(--s4)); align-self: start; }
}
.filters__group { margin-bottom: var(--s5); }
.filters h2 { margin: 0 0 var(--s2); font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.18em; color: var(--muted); text-transform: lowercase; }
.filters ul { margin: 0; padding: 0; display: grid; gap: var(--s1); }
.filters li { list-style: none; }
.filters .link { font-size: var(--t-small); font-weight: 400; }
.filters .link[aria-current='true'] { font-weight: 500; }
.filters .link[aria-current='true']::after { transform: scaleX(1); }

/* --------------------------------------------------------- product detail */

.product { display: grid; gap: var(--s5); padding-block: var(--s5) 0; }
@media (min-width: 62rem) {
  .product { grid-template-columns: 1.25fr 1fr; gap: var(--s8); align-items: start; padding-block: var(--s6) 0; }
  .product__panel { position: sticky; top: calc(var(--head) + var(--s4)); }
}
.viewer__stage { background: var(--fill); display: grid; place-items: center; padding: clamp(1.5rem, 0.5rem + 4vw, 4rem); aspect-ratio: 4 / 5; }
.viewer__stage img {
  height: 100%; width: auto; object-fit: contain;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 18px 40px -16px rgb(0 0 0 / 0.30);
}
.viewer__thumbs { display: flex; gap: var(--s2); margin-top: var(--s2); }
.viewer__thumbs button { width: 3.75rem; aspect-ratio: 4/5; background: var(--fill); border: 1px solid transparent; display: grid; place-items: center; padding: 6px; }
.viewer__thumbs button[aria-current='true'] { border-color: var(--ink); }
.viewer__thumbs img { height: 100%; width: auto; }

.product__title { margin: 0; font-size: var(--t-h2); font-weight: 700; line-height: 1.05; letter-spacing: -0.03em; text-transform: lowercase; }
.product__sub { margin: var(--s1) 0 0; color: var(--muted); font-size: var(--t-small); }
.product__price { margin: var(--s3) 0 0; font-size: var(--t-lead); font-variant-numeric: tabular-nums; }

.opt { margin-top: var(--s4); }
.opt__label { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s2); margin-bottom: var(--s2); }
.opt__label span:first-child { font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.18em; color: var(--muted); }
.opt__label span:last-child { font-size: var(--t-small); }
.opt__row { display: flex; flex-wrap: wrap; gap: var(--s1); }
.chip { border: 1px solid var(--line); padding: 0.6rem 0.9rem; font-size: var(--t-small); line-height: 1; border-radius: 999px; transition: border-color 200ms ease, background-color 200ms ease; }
.chip:hover { border-color: #c9c9c4; }
.chip[aria-pressed='true'] { border-color: var(--ink); background: var(--ink); color: var(--paper); }

.add { margin-top: var(--s5); width: 100%; background: var(--ink); color: var(--paper); padding: 1.05rem; border-radius: 999px; font-size: var(--t-small); font-weight: 500; display: flex; justify-content: center; gap: var(--s2); transition: background-color 200ms ease; }
.add:hover { background: #26262a; }
.ships { margin: var(--s3) 0 0; font-size: var(--t-small); color: var(--muted); }

.about { display: grid; gap: var(--s4); }
@media (min-width: 62rem) { .about { grid-template-columns: 1fr 1fr; gap: var(--s7); } }
.about p { margin: 0 0 var(--s3); color: var(--muted); max-width: 52ch; }
.specs { display: grid; gap: 0; }
.specs div { display: flex; justify-content: space-between; gap: var(--s3); padding: 0.7rem 0; border-bottom: 1px solid var(--line); font-size: var(--t-small); }
.specs dt { color: var(--muted); margin: 0; }
.specs dd { margin: 0; font-variant-numeric: tabular-nums; }

.scale { background: var(--fill); padding: clamp(1.5rem, 0.5rem + 4vw, 4rem); }
.scale svg { width: 100%; height: auto; }

/* ==========================================================================
   Motion
   One easing curve for everything. Two tiers of hover. A masked line reveal
   reserved for the two largest lines on the site.
   ========================================================================== */

[data-tilt-scene] { perspective: 1400px; }
[data-tilt] { will-change: transform; }

/* The clip has to clear the descenders. At line-height below 1 the glyph tails
   fall outside the line box, so the padding covers the overflow and the equal
   negative margin keeps the leading unchanged. */
.mask { display: block; overflow: hidden; padding-bottom: 0.26em; margin-bottom: -0.26em; }
.mask > span {
  display: block;
  transform: translateY(106%);
  transition: transform 950ms var(--ease) var(--delay, 0ms);
}
.is-in .mask > span { transform: translateY(0); }

[data-reveal] {
  opacity: 0; transform: translateY(18px);
  transition: opacity 800ms var(--ease) var(--delay, 0ms),
              transform 800ms var(--ease) var(--delay, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* The soft entrance: less travel, more time. For the quiet elements. */
[data-reveal='soft'] { transform: translateY(12px); transition-duration: 1050ms; }

/* The hero plate arrives with more travel and settles out of a slight
   rotation, so it reads as an object being set down rather than a fade. */
[data-reveal='plate'] { opacity: 0; transform: translateY(46px) rotate(-1.4deg) scale(0.965); }
[data-reveal='plate'].is-in {
  opacity: 1; transform: none;
  transition: opacity 1200ms var(--ease) var(--delay, 0ms),
              transform 1200ms var(--ease) var(--delay, 0ms);
}

/* Masked lines are invisible until measured, so nothing flashes unstyled. */
.mask > span { will-change: transform; }

/* Crossing between pages: the leaving page dips out, the arriving one rises
   in. The classes come from interactions.js; without JS nothing is hidden. */
html.js body { opacity: 0; transform: translateY(6px); }
html.js.page-in body { opacity: 1; transform: none; transition: opacity 460ms var(--ease), transform 460ms var(--ease); }
html.js.page-out body { opacity: 0; transform: translateY(-6px); transition: opacity 230ms ease; }

@media (prefers-reduced-motion: reduce) {
  html.js body, html.js.page-out body { opacity: 1; transform: none; transition: none; }
  .facts .fact:hover, .tiles .tile:hover { transform: none; }
  [data-reveal], [data-reveal='plate'] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .mask > span { transform: none !important; transition: none !important; }
  .tile:hover { transform: none; }
  [data-tilt] { transform: none !important; }
}

/* A masked line revealed on scroll: the clip does all the work, so suppress
   the general fade-and-rise that would otherwise double the motion. */
[data-reveal='mask'] { opacity: 1; transform: none; transition: none; }

/* ------------------------------------------------- product page QOL ---- */

/* Back to catalogue, under the wordmark. */
.backbar { padding-top: var(--s4); }
.backbar .arrow { display: inline-block; margin-right: 0.55em; transition: transform 260ms var(--ease); }
.backbar .link:hover .arrow, .backbar .link:focus-visible .arrow { transform: translateX(-4px); }

/* The "i" beside an option label: a whisper of help, on demand. */
.info {
  position: relative; display: inline-grid; place-items: center;
  width: 1.05rem; height: 1.05rem; margin-left: 0.4em;
  border: 1px solid var(--line); border-radius: 50%;
  font-size: 0.6rem; font-weight: 600; font-style: normal;
  color: var(--muted); background: var(--paper);
  cursor: help; vertical-align: 2px; letter-spacing: 0;
  transition: border-color 200ms ease, color 200ms ease;
}
.info:hover, .info:focus-visible { border-color: var(--ink); color: var(--ink); }
.info::after {
  content: attr(data-tip);
  position: absolute; bottom: calc(100% + 10px); left: 50%;
  transform: translateX(-50%) translateY(4px);
  width: max-content; max-width: 32ch;
  background: var(--ink); color: var(--paper);
  text-transform: none; font-weight: 400; font-size: 0.72rem;
  letter-spacing: 0.01em; line-height: 1.5; text-align: left;
  padding: 0.55rem 0.75rem; border-radius: 4px;
  opacity: 0; pointer-events: none; z-index: 40;
  transition: opacity 200ms var(--ease), transform 200ms var(--ease);
}
.info:hover::after, .info:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }

/* The stage: a button that opens the detail view; the frame option renders
   as a real moulding around the sheet. */
.stage-open {
  height: 100%; width: 100%;
  display: grid; place-items: center;
  background: none; border: 0; padding: 0; cursor: zoom-in;
}
.viewer__hint { margin-top: var(--s2); text-align: center; }
.stage-frame {
  display: block; height: 100%; width: fit-content; box-sizing: border-box;
  transition: padding 280ms var(--ease), background 280ms var(--ease), box-shadow 280ms var(--ease);
}
.stage-frame[data-frame='oak'],
.stage-frame[data-frame='black'],
.stage-frame[data-frame='aluminium'] { padding: clamp(8px, 1.1vw, 14px); }
.stage-frame[data-frame='oak'] {
  background: linear-gradient(135deg, #c9aa7f, #ac8a5d 52%, #c3a276);
  box-shadow: inset 0 0 0 1px rgb(15 15 16 / 0.28), 0 1px 2px rgb(0 0 0 / 0.06), 0 18px 40px -16px rgb(0 0 0 / 0.30);
}
.stage-frame[data-frame='black'] {
  background: #141415;
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.07), 0 1px 2px rgb(0 0 0 / 0.08), 0 18px 40px -16px rgb(0 0 0 / 0.34);
}
.stage-frame[data-frame='aluminium'] {
  padding: clamp(6px, 0.9vw, 11px);
  background: linear-gradient(135deg, #d9dbdd, #adb0b4 50%, #d3d5d8);
  box-shadow: inset 0 0 0 1px rgb(15 15 16 / 0.18), 0 1px 2px rgb(0 0 0 / 0.06), 0 18px 40px -16px rgb(0 0 0 / 0.28);
}
.stage-frame:not([data-frame='none']) img { box-shadow: none; }

/* Detail view: the sheet at full quality, zoom and pan. */
.lightbox {
  position: fixed; inset: 0; z-index: 80;
  background: rgb(255 255 255 / 0.97);
  display: flex; align-items: center; justify-content: center;
  overscroll-behavior: contain;
}
.lightbox[hidden] { display: none; }
.lightbox img {
  max-width: min(92vw, 1500px); max-height: 90vh;
  transform-origin: 0 0;
  cursor: grab; touch-action: none; user-select: none; -webkit-user-drag: none;
  box-shadow: 0 30px 90px rgb(15 15 16 / 0.16);
}
.lightbox img:active { cursor: grabbing; }
.lightbox__close {
  position: absolute; top: 1.1rem; right: 1.25rem; z-index: 2;
  width: 2.6rem; height: 2.6rem; border-radius: 50%;
  background: var(--ink); color: var(--paper);
  font-size: 1.15rem; line-height: 1;
  transition: background-color 200ms ease;
}
.lightbox__close:hover { background: #26262a; }
.lightbox__hint { position: absolute; bottom: 1.2rem; left: 50%; transform: translateX(-50%); }

/* Sets on the shop page. */
.setgroup { margin-top: var(--s5); }
.setgroup__head { max-width: 62ch; margin-bottom: var(--s4); }
.setgroup__head h3 {
  margin: 0 0 var(--s1); font-size: var(--t-lead); font-weight: 700;
  letter-spacing: -0.02em; text-transform: lowercase;
}

/* The hidden attribute must always win, whatever display a class sets. */
[hidden] { display: none !important; }

/* ------------------------------------------------------ shop controls ---- */

.sortbar { display: flex; align-items: center; gap: var(--s1); flex-wrap: wrap; }
.sortbar .util { margin-right: var(--s1); }
#sort-dir { min-width: 2.4rem; font-size: 0.9rem; }

/* Rail filter buttons: the link language, but stateful. */
.filters__row { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.linkbtn {
  position: relative; display: inline-block; padding: 0 0 3px;
  background: none; border: 0; cursor: pointer; text-align: left;
  font-size: var(--t-small); font-weight: 500; text-transform: lowercase;
}
.linkbtn::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform 320ms var(--ease);
}
.linkbtn:hover::after, .linkbtn:focus-visible::after, .linkbtn[aria-pressed='true']::after { transform: scaleX(1); }
.filters__go { color: var(--muted); }
.filters__go:hover { color: var(--ink); }

.gridhead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3); margin-bottom: var(--s3);
}

/* ------------------------------------------------ frame preview ---------- */
/* The stage wrapper carries data-frame; the moulding is a border on the
   wrapper so it tilts with the print, plus a narrow mat between the two. */
.stage-frame { display: inline-block; line-height: 0; transition: padding 240ms var(--ease), border-color 240ms var(--ease), background 240ms var(--ease); }
.stage-frame[data-frame='none'] { border: 0; padding: 0; background: none; }
.stage-frame[data-frame='oak'],
.stage-frame[data-frame='black'],
.stage-frame[data-frame='aluminium'] {
  padding: clamp(0.5rem, 0.3rem + 0.8vw, 0.9rem);
  background: #fdfdfc;
  box-shadow: 0 18px 50px rgba(15, 15, 16, 0.16);
}
.stage-frame[data-frame='oak'] { border: 0.62rem solid #a5794e; }
.stage-frame[data-frame='black'] { border: 0.62rem solid #17171a; }
.stage-frame[data-frame='aluminium'] { border: 0.5rem solid #c4c8cc; }
.stage-frame[data-frame='oak'],
.stage-frame[data-frame='black'],
.stage-frame[data-frame='aluminium'] { border-radius: 1px; }
.stage-frame[data-frame] img { display: block; }

/* ---- cart + set builder (cart.js) ---- */

/* Quick add on catalogue cards. The name column takes the slack so the
   price and the affordance sit together on the right. */
.card__body > div:first-child { flex: 1; }
.qadd {
  position: relative; flex: none; align-self: baseline;
  padding: 0 0 3px; white-space: nowrap;
  font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.06em;
  text-transform: lowercase; color: var(--muted);
  transition: color 200ms ease, opacity 240ms var(--ease);
}
.qadd::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: currentColor;
  transform: scaleX(0); transform-origin: left;
  transition: transform 240ms var(--ease);
}
.qadd:hover, .qadd:focus-visible, .qadd.is-added { color: var(--ink); }
.qadd:hover::after, .qadd:focus-visible::after { transform: scaleX(1); }
/* Hidden until hover where a cursor exists; always present on touch. */
@media (hover: hover) and (pointer: fine) {
  .qadd { opacity: 0; }
  .card:hover .qadd, .card:focus-within .qadd, .qadd.is-added { opacity: 1; }
}

/* The drawer: a white panel behind one hairline, slid in from the right. */
.bag-scrim {
  position: fixed; inset: 0; z-index: 60;
  background: rgb(15 15 16 / 0.14);
  opacity: 0; visibility: hidden;
  transition: opacity 240ms var(--ease), visibility 0s 240ms;
}
.bag-open .bag-scrim { opacity: 1; visibility: visible; transition: opacity 240ms var(--ease); }

.bag-panel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 70;
  width: min(380px, 92vw);
  background: var(--paper); border-left: 1px solid var(--line);
  box-shadow: -32px 0 70px -48px rgb(15 15 16 / 0.28);
  display: flex; flex-direction: column;
  transform: translateX(102%); visibility: hidden;
  transition: transform 240ms var(--ease), visibility 0s 240ms;
}
.bag-open .bag-panel { transform: none; visibility: visible; transition: transform 240ms var(--ease); }

.bag-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
}
.bag-head h2 { margin: 0; font-size: var(--t-lead); font-weight: 700; letter-spacing: -0.02em; text-transform: lowercase; }
.bag-close {
  width: 2.25rem; height: 2.25rem; display: grid; place-items: center;
  margin-right: -0.5rem; font-size: 1.2rem; line-height: 1;
  transition: opacity 200ms ease;
}
.bag-close:hover { opacity: 0.55; }

.bag-body { flex: 1; overflow-y: auto; padding: 0 var(--s4) var(--s4); }
.bag-empty { margin: 0; padding: var(--s4) 0; color: var(--muted); font-size: var(--t-small); }

.bag-item {
  display: grid; grid-template-columns: 60px 1fr auto; gap: 0 var(--s3);
  align-items: start; padding: var(--s3) 0;
  border-bottom: 1px solid var(--line);
}
.bag-item:last-child { border-bottom: 0; }
.bag-item__thumb {
  width: 60px; aspect-ratio: 3 / 4; padding: 6px;
  background: var(--fill); display: grid; place-items: center;
}
.bag-item__thumb img { max-height: 100%; max-width: 100%; width: auto; }
.bag-item__name { font-size: var(--t-small); font-weight: 500; text-transform: lowercase; line-height: 1.35; }
.bag-item__opts { margin-top: 2px; font-size: var(--t-micro); color: var(--muted); }
.bag-item__set {
  margin-top: var(--s1); padding: 0 0 2px;
  font-size: var(--t-micro); font-weight: 500; letter-spacing: 0.06em; text-transform: lowercase;
  color: var(--muted); border-bottom: 1px dashed #cfcfca;
  transition: color 200ms ease, border-color 200ms ease;
}
.bag-item__set:hover, .bag-item__set:focus-visible { color: var(--ink); border-color: var(--ink); }
.bag-item__set[aria-pressed='true'] { color: var(--ink); border-bottom-style: solid; border-color: var(--ink); }
.bag-item__side { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s1); }
.bag-item__price { font-size: var(--t-small); font-variant-numeric: tabular-nums; }
.bag-item__remove {
  width: 1.5rem; height: 1.5rem; display: grid; place-items: center;
  margin-right: -0.35rem; color: var(--muted); font-size: 1rem; line-height: 1;
  transition: color 200ms ease;
}
.bag-item__remove:hover, .bag-item__remove:focus-visible { color: var(--ink); }

/* The set builder: three dashed squares that fill as prints are toggled in. */
.bag-set { margin-top: var(--s2); padding-top: var(--s4); border-top: 1px solid var(--line); }
.bag-set__head { margin: 0; font-size: var(--t-small); font-weight: 700; letter-spacing: -0.01em; text-transform: lowercase; }
.bag-set__sub { margin: 2px 0 0; }
.bag-mode { display: flex; gap: var(--s2); margin-top: var(--s2); }
.bag-mode__chip {
  appearance: none; cursor: pointer;
  padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: none; color: var(--muted);
  font: inherit; font-size: var(--t-micro); letter-spacing: 0.04em;
  transition: color 200ms var(--ease), border-color 200ms var(--ease);
}
.bag-mode__chip:hover { color: var(--ink); }
.bag-mode__chip[aria-pressed="true"] { color: var(--ink); border-color: var(--ink); }
.bag-slots { display: flex; gap: var(--s2); margin-top: var(--s2); }
.bag-slot {
  width: 56px; aspect-ratio: 1; padding: 5px;
  border: 1px dashed #d6d6d1;
  display: grid; place-items: center;
}
.bag-slot.is-filled { border-style: solid; border-color: var(--line); background: var(--fill); }
.bag-slot img { max-height: 100%; max-width: 100%; width: auto; }
.bag-slots.is-flash .bag-slot { animation: bag-flash 420ms ease; }
@keyframes bag-flash { 40% { border-color: var(--ink); } }
.bag-set__line { margin: var(--s3) 0 0; font-size: var(--t-small); font-variant-numeric: tabular-nums; }
.bag-set__line s { color: var(--muted); margin-right: var(--s1); }
.bag-set__save { display: block; margin-top: 2px; }

.bag-foot { border-top: 1px solid var(--line); padding: var(--s3) var(--s4) var(--s4); }
.bag-foot__row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.bag-subtotal { font-variant-numeric: tabular-nums; }
.bag-foot .add { margin-top: var(--s3); }
.bag-foot .add:disabled { opacity: 0.35; cursor: default; }
.bag-foot .add:disabled:hover { background: var(--ink); }
.bag-note { margin: var(--s2) 0 0; text-align: center; }

@media (prefers-reduced-motion: reduce) {
  .bag-panel, .bag-scrim, .qadd, .qadd::after { transition: none; }
  .bag-slots.is-flash .bag-slot { animation: none; }
}
/* ---- end cart ---- */
