/* ============================================
   PAUL SAGOO — Design System v2
   Restrained luxury. Ink, ivory, antique gold.
   Colour lives in the product, not the page.
   ============================================ */

:root {
  --ink: #12110e;
  --ink-soft: #1c1a16;
  --paper: #f5f2ea;
  --paper-deep: #ece7db;
  --gold: #a8894a;
  --gold-bright: #c8a86a;
  /* --gold is decorative: 2.96:1 on paper, which fails WCAG AA, and it was
     carrying 9-11px text. --gold-ink is the same hue at 5.02:1 on paper — use
     it for gold TEXT on a light ground. --gold stays for rules, borders and
     large display type. --gold-bright is 8.33:1 on ink and is fine on dark. */
  --gold-ink: #7c6536;
  --line-dark: rgba(255,255,255,0.14);
  --line-light: rgba(18,17,14,0.16);

  --font-display: 'Cormorant Garamond', Georgia, serif;
  --font-body: 'Archivo', sans-serif;

  --pad: clamp(24px, 5vw, 96px);
  --nav-h: 118px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* FUN-005. `scroll-behavior: smooth` was here. A CSS smooth scroll is silently
   CANCELLED by any competing scroll — a scroll listener, a parallax RAF, a
   reveal observer shifting layout mid-animation. When that happens the hash
   updates and the page does not move, with no error and nothing to debug. An
   audit found the homepage's primary CTA doing exactly that: URL changed to
   #collection, scrollY stayed 0.
   The motion now lives in js/chrome.js, where it is one explicit call that
   either runs or throws, and it honours prefers-reduced-motion. Do not put
   scroll-behavior back. */

body {
  font-family: var(--font-body);
  background: var(--ink);
  color: var(--paper);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

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

/* ---------- Type ---------- */
.display {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: 0.005em;
}
.display em { font-style: italic; font-weight: 500; }
.display--xl { font-size: clamp(3rem, 8.5vw, 7.5rem); }
.display--lg { font-size: clamp(2.2rem, 5vw, 4.6rem); }
.display--md { font-size: clamp(1.6rem, 3vw, 2.6rem); }
.display--sm { font-size: clamp(1.2rem, 1.8vw, 1.6rem); }

.eyebrow {
  font-size: 0.66rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.42em;
  opacity: 0.75;
}

.body-lg { font-size: clamp(0.98rem, 1.25vw, 1.12rem); line-height: 1.75; font-weight: 400; }
.muted { opacity: 0.7; }

/* ---------- Rules & ornaments ---------- */
.rule { border: 0; height: 1px; background: var(--line-dark); }
.bg-paper .rule, .bg-paper-deep .rule { background: var(--line-light); }
.orn { color: var(--gold); font-size: 0.8rem; letter-spacing: 0.6em; text-transform: uppercase; }

/* ---------- Nav ---------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--pad);
  z-index: 1000;
  transition: background 0.4s ease, border-color 0.4s ease;
  border-bottom: 1px solid transparent;
}
.nav.scrolled { background: rgba(18,17,14,0.94); backdrop-filter: blur(14px); border-bottom-color: var(--line-dark); }
.nav__logo img { height: 72px; width: auto; display: block; }
.nav__links { display: flex; gap: 40px; align-items: center; }
.nav__links a, .nav__cart {
  font-size: 0.66rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  position: relative;
  background: none;
  border: none;
  color: inherit;
}
.nav__links a::after, .nav__cart::after {
  content: '';
  position: absolute;
  left: 0; bottom: -8px;
  width: 0; height: 1px;
  background: var(--gold-bright);
  transition: width 0.35s ease;
}
.nav__links a:hover::after, .nav__cart:hover::after { width: 100%; }
.nav__cart .count { color: var(--gold-bright); margin-left: 6px; }
@media (max-width: 720px) {
  .nav__links a:not(.nav__cart) { display: none; }
}

/* ---------- Sections ---------- */
.block {
  position: relative;
  padding: calc(var(--pad) * 1.5) var(--pad);
  overflow: hidden;
}
.block--full { min-height: 92vh; display: flex; flex-direction: column; justify-content: center; }

.bg-ink { background: var(--ink); color: var(--paper); }
.bg-ink-soft { background: var(--ink-soft); color: var(--paper); }
.bg-paper { background: var(--paper); color: var(--ink); }
.bg-paper-deep { background: var(--paper-deep); color: var(--ink); }

.text-gold { color: var(--gold-bright); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 17px 44px;
  font-weight: 500;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  border-radius: 0;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  transition: background 0.35s ease, color 0.35s ease, border-color 0.35s ease;
}
.bg-ink .btn:hover, .bg-ink-soft .btn:hover { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.bg-paper .btn:hover, .bg-paper-deep .btn:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn--solid { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn--solid:hover { background: transparent; color: var(--ink); }
.btn--white { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.btn--white:hover { background: transparent; color: var(--paper); }
.btn--gold { background: transparent; color: var(--gold-bright); border-color: var(--gold); }
.btn--gold:hover { background: var(--gold); color: var(--ink); }

.link-quiet {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.3em;
  border-bottom: 1px solid var(--gold);
  padding-bottom: 6px;
}

/* ---------- Footer ---------- */
.footer { padding: calc(var(--pad)*1.2) var(--pad); }
.footer__grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 48px; margin-top: 56px; }
.footer__grid h3, h4 { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.38em; margin-bottom: 22px; color: var(--gold-bright); font-weight: 500; }
.footer__grid a { display: block; margin-bottom: 12px; font-size: 0.85rem; opacity: 0.65; transition: opacity .25s; }
.footer__grid a:hover { opacity: 1; }
.footer__legal { margin-top: 72px; padding-top: 24px; border-top: 1px solid var(--line-dark); display: flex; justify-content: space-between; font-size: 0.7rem; opacity: 0.45; letter-spacing: 0.08em; }
@media (max-width: 720px) { .footer__grid { grid-template-columns: 1fr 1fr; } }

/* ---------- Utility ---------- */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: calc(var(--pad) * 1.2); align-items: center; }
@media (max-width: 860px) { .grid-2 { grid-template-columns: 1fr; } }
.center { text-align: center; }
.mt-1 { margin-top: 18px; } .mt-2 { margin-top: 36px; } .mt-3 { margin-top: 64px; }
.reveal { opacity: 0; transform: translateY(24px); transition: opacity 1s ease, transform 1s cubic-bezier(.16,.6,.2,1); }
.reveal.in { opacity: 1; transform: none; }

/* ---------- Cart drawer ---------- */
.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(440px, 100vw);
  background: var(--paper);
  color: var(--ink);
  z-index: 2000;
  transform: translateX(100%);
  transition: transform 0.45s cubic-bezier(.16,.6,.2,1);
  display: flex;
  flex-direction: column;
}
.drawer.open { transform: none; box-shadow: -30px 0 80px rgba(0,0,0,0.45); }
.drawer__head { display: flex; justify-content: space-between; align-items: center; padding: 28px 32px; border-bottom: 1px solid var(--line-light); }
.drawer__head .display { font-size: 1.5rem; }
.drawer__close { background: none; border: none; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.3em; border-bottom: 1px solid var(--ink); padding-bottom: 4px; }
.drawer__items { flex: 1; overflow-y: auto; padding: 32px; }
.drawer__foot { padding: 28px 32px; border-top: 1px solid var(--line-light); }
.cart-item { display: flex; gap: 18px; margin-bottom: 28px; padding-bottom: 28px; border-bottom: 1px solid var(--line-light); }
.cart-item__swatch { width: 56px; height: 56px; flex-shrink: 0; border: 1px solid var(--line-light); }
.cart-item__meta { flex: 1; font-size: 0.82rem; }
.cart-item__meta strong { display: block; font-size: 1.15rem; font-family: var(--font-display); font-weight: 500; margin-bottom: 6px; }
.cart-item__meta .line { display: flex; justify-content: space-between; opacity: 0.65; margin-top: 4px; }
.cart-item button.remove { background: none; border: none; font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.2em; border-bottom: 1px solid currentColor; margin-top: 10px; opacity: 0.5; }
.overlay { position: fixed; inset: 0; background: rgba(10,9,7,0.55); z-index: 1500; opacity: 0; pointer-events: none; transition: opacity 0.4s; }
.overlay.show { opacity: 1; pointer-events: auto; }

/* ============================================
   v3 — Editorial colour, monogram texture, motion
   ============================================ */

:root {
  --sapphire: #16305e;
  --emerald: #14503c;
  --oxblood: #4a1f1a;
  --saffron: #a06a1e;
  --plum: #3d1f4a;
}

/* Campaign fields — full-bleed colour, replaced by photography later */
.campaign {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(var(--pad) * 1.5) var(--pad);
  overflow: hidden;
  color: var(--paper);
}
.campaign__bg {
  position: absolute;
  inset: -12%;
  background-size: cover;
  background-position: center;
  animation: slowpan 26s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes slowpan {
  from { transform: scale(1.02) translate3d(-1.5%, -1%, 0); }
  to   { transform: scale(1.1) translate3d(1.5%, 1%, 0); }
}
.campaign__veil { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,9,7,0.25), transparent 30%, transparent 65%, rgba(10,9,7,0.45)); }
.campaign > .inner { position: relative; z-index: 2; }

/* Monogram texture */
.monogram {
  position: absolute; inset: 0;
  background-image: url('../assets/ps-pattern.svg');
  background-size: 190px;
  opacity: 0.07;
  pointer-events: none;
}
.monogram--fine { background-size: 120px; opacity: 0.05; }

/* Jewel gradients (photography placeholders) */
.field-sapphire { background: radial-gradient(120% 90% at 20% 10%, #2c4f8f 0%, var(--sapphire) 45%, #0c1a36 100%); }
.field-emerald  { background: radial-gradient(120% 90% at 80% 15%, #2a7a5c 0%, var(--emerald) 50%, #08281d 100%); }
.field-oxblood  { background: radial-gradient(120% 90% at 30% 85%, #7a3a30 0%, var(--oxblood) 50%, #200d0b 100%); }
.field-saffron  { background: radial-gradient(120% 90% at 70% 20%, #c8944a 0%, var(--saffron) 55%, #4a2e0c 100%); }
.field-ink      { background: radial-gradient(110% 80% at 50% 20%, #26221a 0%, var(--ink) 60%); }

/* Reveal variants */
.reveal--clip { opacity: 1; transform: none; clip-path: inset(0 0 100% 0); transition: clip-path 1.2s cubic-bezier(.16,.6,.2,1); }
.reveal--clip.in { clip-path: inset(0 0 0% 0); }
.reveal--left { transform: translateX(-32px); }
.reveal--right { transform: translateX(32px); }
[data-stagger] > * { opacity: 0; transform: translateY(22px); transition: opacity .9s ease, transform .9s cubic-bezier(.16,.6,.2,1); }
[data-stagger].in > * { opacity: 1; transform: none; }
[data-stagger].in > *:nth-child(2) { transition-delay: .12s; }
[data-stagger].in > *:nth-child(3) { transition-delay: .24s; }
[data-stagger].in > *:nth-child(4) { transition-delay: .36s; }
[data-stagger].in > *:nth-child(5) { transition-delay: .48s; }

/* Parallax */
[data-parallax] { will-change: transform; }

/* Editorial product card */
.pcard { display: block; position: relative; overflow: hidden; }
.pcard__stage { background: var(--paper-deep); padding: 15% 11%; overflow: hidden; position: relative; }
.pcard__stage > div { transition: transform 1.1s cubic-bezier(.16,.6,.2,1); }
.pcard:hover .pcard__stage > div { transform: scale(1.045); }
.pcard__meta { display: flex; justify-content: space-between; align-items: baseline; margin-top: 22px; }

/* Ritual (unboxing) steps */
.ritual { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line-dark); border: 1px solid var(--line-dark); }
@media (max-width: 900px) { .ritual { grid-template-columns: 1fr 1fr; } }
.ritual__step { background: var(--ink); padding: 44px 30px 40px; position: relative; overflow: hidden; transition: background .5s ease; }
.ritual__step:hover { background: var(--ink-soft); }
.ritual__step .num { font-family: var(--font-display); font-size: 2.6rem; color: var(--gold); font-weight: 400; font-style: italic; }
.ritual__step h3, h4 { font-family: var(--font-display); font-size: 1.35rem; font-weight: 500; margin: 14px 0 10px; }
.ritual__step p { font-size: 0.8rem; opacity: 0.6; line-height: 1.7; }

/* Journey (finishing) rows */
.journey { border-top: 1px solid var(--line-light); }
.journey__row { display: grid; grid-template-columns: 90px 1fr 2fr auto; gap: 28px; align-items: center; padding: 30px 0; border-bottom: 1px solid var(--line-light); transition: padding-left .4s ease; }
.journey__row:hover { padding-left: 12px; }
.journey__row .num { font-family: var(--font-display); font-style: italic; font-size: 1.6rem; color: var(--gold); }
.journey__row h3, h4 { font-family: var(--font-display); font-size: 1.5rem; font-weight: 500; }
.journey__row p { font-size: 0.82rem; opacity: 0.6; line-height: 1.7; }
.journey__row .tag { font-size: 0.62rem; letter-spacing: 0.28em; text-transform: uppercase; opacity: 0.5; white-space: nowrap; }
@media (max-width: 820px) { .journey__row { grid-template-columns: 60px 1fr; } .journey__row p, .journey__row .tag { grid-column: 2; } }

/* Colourway ribbon */
.ribbon { overflow: hidden; white-space: nowrap; padding: 20px 0; border-top: 1px solid var(--line-dark); border-bottom: 1px solid var(--line-dark); }
.ribbon__inner { display: inline-flex; align-items: center; gap: 56px; animation: ribbon 40s linear infinite; padding-right: 56px; }
@keyframes ribbon { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.ribbon__item { display: inline-flex; align-items: center; gap: 14px; font-size: 0.64rem; letter-spacing: 0.34em; text-transform: uppercase; opacity: 0.75; }
.ribbon__dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }

/* ---------- Cinematic intro: blurry → beautifully clear ---------- */
#intro { position: fixed; inset: 0; z-index: 5000; background: var(--ink); overflow: hidden; cursor: pointer; }
#intro.done { opacity: 0; visibility: hidden; transition: opacity 1.1s ease, visibility 0s 1.1s; }
.intro__img {
  position: absolute; inset: -4%;
  background-size: cover; background-position: center 40%;
  filter: blur(38px) brightness(0.55) saturate(1.1);
  transform: scale(1.3);
  animation: introFocus 3.4s cubic-bezier(.3,.6,.15,1) 0.3s forwards;
}
@keyframes introFocus {
  60% { filter: blur(10px) brightness(0.75); }
  100% { filter: blur(0) brightness(0.92); transform: scale(1.02); }
}
.intro__veil { position: absolute; inset: 0; background: radial-gradient(75% 60% at 50% 62%, rgba(8,8,6,0.62) 0%, rgba(8,8,6,0.28) 55%, rgba(8,8,6,0.12) 100%); }
.intro__copy { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; color: var(--paper); padding: 0 24px; }
.intro__line { font-family: var(--font-display); font-weight: 500; font-size: clamp(2.6rem, 7vw, 6rem); line-height: 1.04; opacity: 0; transform: translateY(26px); animation: introLine 1.2s cubic-bezier(.16,.6,.2,1) forwards; }
.intro__line em { font-style: italic; }
.intro__line--1 { animation-delay: 1.5s; }
.intro__line--2 { animation-delay: 2.0s; }
.intro__tag { margin-top: 26px; font-size: 0.72rem; letter-spacing: 0.5em; text-transform: uppercase; color: var(--gold-bright); opacity: 0; animation: introLine 1.2s ease 2.7s forwards; }
@keyframes introLine { to { opacity: 1; transform: none; } }
/* MOB-004: this was 35x19px at 55% opacity, bottom-right, over a moving
   multicolour radial — effectively undismissable on a phone. Now a proper
   44px+ target, top-right where a dismiss belongs, on its own scrim. */
.intro__skip { position: absolute; top: 20px; right: 20px; bottom: auto; left: auto;
  min-width: 96px; min-height: 48px; display: inline-flex; align-items: center; justify-content: center;
  background: rgba(10,9,8,0.82); border: 1px solid rgba(245,242,234,0.55); border-radius: 0;
  color: #f5f2ea; font-size: 0.82rem; letter-spacing: 0.2em; text-transform: uppercase;
  padding: 12px 20px; cursor: pointer; z-index: 2; }
.intro__skip:hover, .intro__skip:focus-visible { background: #f5f2ea; color: #12110e; }
@media (prefers-reduced-motion: reduce) { #intro { display: none; } }

/* Photo cards / galleries */
/* The collection masters are not one shape — 1200x1500, 1600x1600 — so `cover`
   in a fixed 4:4.6 tile crops a square shot's temple tips off. `contain` on the
   photographs' own ground (#f7f6f4, not --paper-deep) keeps every frame whole
   and makes the tile edge invisible, whatever shape the master is. */
.pcard__photo { aspect-ratio: 4/4.6; overflow: hidden; background: #f7f6f4; }
.pcard__photo img { width: 100%; height: 100%; object-fit: contain; background: #f7f6f4;
  transition: transform 1.1s cubic-bezier(.16,.6,.2,1); }
.pcard:hover .pcard__photo img { transform: scale(1.05); }
/* The product page's views, laid out as one set — square tiles, uniform gaps.
   Scoped to #pGallery: .gallery is also the homepage campaign strip, which is a
   horizontal scroller and was being forced into a 4-column grid by this rule,
   stranding its fifth panel on a row of its own. */
/* 30 Aug 2026: five across, not four. The rail is four photographs plus the
   live-tinted colour tile. On a four-column grid the colour tile was stranded
   alone on a second row and read as an unfinished set. Five columns puts the
   whole rail on one line. If the worn shots land it becomes seven and wraps
   5 + 2, which is fine. */
#pGallery { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;
  margin-top: 24px; padding-bottom: 6px; }
#pGallery img { width: 100%; height: 100%; object-fit: contain; display: block; }
@media (max-width: 520px) { #pGallery { grid-template-columns: repeat(3, 1fr); gap: 8px; } }

/* the campaign strip: a scroller again, and one that says so */
.gallery { display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory;
  margin-top: 24px; padding-bottom: 10px; scroll-padding-left: var(--pad); }
.gallery > * { scroll-snap-align: start; flex: 0 0 auto; }
.gallery::-webkit-scrollbar { height: 3px; }
.gallery::-webkit-scrollbar-thumb { background: rgba(200,168,106,0.5); }
.gallery::-webkit-scrollbar-track { background: rgba(255,255,255,0.06); }
/* 10 Sep 2026. Says out loud what the tiles do. Same wording as the trunk
   pages so the two galleries teach the same gesture. */
.gallery__note { margin: 10px 0 0; font-size: 0.68rem; letter-spacing: 0.18em;
  text-transform: uppercase; opacity: 0.62; text-align: center; }
.gallery__note b { font-weight: 400; color: var(--gold); opacity: 1; }
.gthumb::after { content: ''; position: absolute; right: 4px; bottom: 4px;
  width: 15px; height: 15px; opacity: 0.62; pointer-events: none; transition: opacity .25s ease;
  background: no-repeat center/contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c9a227' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5 21 21M10.5 7.5v6M7.5 10.5h6'/%3E%3C/svg%3E"); }
.gthumb:hover::after, .gthumb.on::after { opacity: 1; }
.trunkgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 14px; }
/* These are 1195x1600 model shots. A flat 220px height in a ~208px column made
   the box very nearly square and `cover` took 21% off — enough to crop a head
   or a strap out of a photograph of someone wearing the piece. Match the tile
   to the photography instead of the other way round. */
.trunkgrid img { width: 100%; height: auto; aspect-ratio: 3/4; object-fit: cover; }

/* Broken-image resilience */
img { background: rgba(128,120,100,0.08); min-height: 20px; }
.trunkgrid img, .gallery img { background: var(--paper-deep, #ece7db); }

/* ---------- Responsive pass ---------- */
@media (max-width: 720px) {
  .nav__logo img { height: 56px !important; }
  .footer__legal { flex-direction: column; gap: 8px; }
  .ritual { grid-template-columns: 1fr; }
  .journey__row:hover { padding-left: 0; }
  .trunkgrid img { height: auto; }
  .buybar { flex-wrap: wrap; padding: 12px 20px; }
  .buybar .btn { padding: 13px 26px; }
  .drawer { width: 100vw; }
}

/* ---------- Animated logo ---------- */
.nav__logo { position: relative; display: inline-block; padding: 14px 0; }
.nav__logo img { animation: logoIn 1.2s cubic-bezier(.16,.6,.2,1) both; }
@keyframes logoIn { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.nav__logo .sheen {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(110deg, transparent 35%, rgba(200,168,106,0.95) 50%, transparent 65%);
  background-size: 260% 100%;
  animation: sheen 5.5s ease-in-out infinite;
}
@keyframes sheen { 0%, 55% { background-position: 120% 0; } 85%, 100% { background-position: -140% 0; } }
.nav__logo:hover img { animation: logoSpin 0.9s cubic-bezier(.3,.6,.2,1); }
@keyframes logoSpin { 50% { transform: scale(1.06); filter: brightness(1.35); } }

/* ---- bag placeholder slots ---- */
.bagslot { aspect-ratio: 3/3.6; border: 1px solid rgba(200,168,106,0.35); position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  background:
    radial-gradient(circle at 50% 120%, rgba(200,168,106,0.10), transparent 60%),
    repeating-conic-gradient(from 0deg at 50% 130%, rgba(200,168,106,0.05) 0deg 4deg, transparent 4deg 8deg);
}
.bagslot::after { content: ''; position: absolute; inset: 10px; border: 1px solid rgba(200,168,106,0.15); pointer-events: none; }
/* 3 Sep 2026. The halo. Three separate things were stacking up inside one
   tile: the tile is 3/3.6 while every bag photograph is 3/4, so object-fit
   contain left a bar of tile background down each side of the picture; the
   img carried background:var(--paper-deep) which is cream, against the
   photographs' own 241 ground, so the picture edge showed as a seam; and
   ::after drew a second gold rule 10px inside the tile. Three nested
   rectangles before the eye reached the bag. Once a tile holds a photograph,
   match the tile to the picture and let the photograph be the only rectangle. */
.bagslot:has(img) { aspect-ratio: 3/4; background: #f1f1f1; }
.bagslot:has(img)::after { display: none; }

.bagslot__num { font-family: var(--font-display); font-style: italic; font-size: 2.2rem; color: var(--gold-bright); }
.bagslot__note { font-size: 0.6rem; letter-spacing: 0.28em; text-transform: uppercase; opacity: 0.55; text-align: center; line-height: 1.9; }

/* arcade cabinet selector */
.arcade-stage.is-on { background: var(--paper); color: var(--ink); border-color: var(--paper); }

/* ============================================================ ONE CHROME
   shared nav + drawer + footer (js/chrome.js) */
:root { --nav-h: 100px; }
/* The mark needs air above it or it reads as clipped by the window edge.
   100px bar, 58px mark, centred: 21px top and bottom. */
.nav__logo img { height: 58px !important; width: auto !important; }
.nav__logo { padding: 12px 0; }
.nav__links { gap: 26px; }
.nav__links a, .nav__cart { font-size: 0.6rem; letter-spacing: 0.24em; white-space: nowrap; }
.nav__links a[aria-current="page"] { color: var(--gold-bright); }
.nav__burger { display: none; background: none; border: 0; padding: 10px; cursor: pointer; }
.nav__burger span { display: block; width: 26px; height: 1.5px; background: currentColor; margin: 6px 0;
  transition: transform .3s ease, opacity .3s ease; }
body.drawer-open .nav__burger span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
body.drawer-open .nav__burger span:nth-child(2) { opacity: 0; }
body.drawer-open .nav__burger span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

.navdrawer { position: fixed; inset: 0 0 0 auto; width: min(420px, 88vw); background: #12110e;
  color: var(--paper); z-index: 1200; transform: translateX(100%); transition: transform .42s cubic-bezier(.16,.7,.2,1);
  padding: calc(var(--nav-h) + 24px) 34px 34px; overflow-y: auto; display: flex; flex-direction: column; }
body.drawer-open .navdrawer { transform: none; }
.navdrawer__close { position: absolute; top: 26px; right: 30px; background: none; border: 0; color: var(--gold);
  font-family: var(--font-body); font-size: 0.56rem; letter-spacing: 0.26em; text-transform: uppercase; cursor: pointer; }
.navdrawer__links { display: flex; flex-direction: column; gap: 4px; }
.navdrawer__links a, .navdrawer__bag { display: block; padding: 15px 0; font-family: var(--font-display);
  font-size: 1.5rem; color: var(--paper); border-bottom: 1px solid rgba(255,255,255,0.07);
  background: none; border-left: 0; border-right: 0; border-top: 0; text-align: left; width: 100%; cursor: pointer; }
.navdrawer__bag { color: var(--gold-bright); }
.navdrawer__legal { margin-top: auto; padding-top: 30px; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.navdrawer__legal a { font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; opacity: 0.5; }
.navdrawer__scrim { position: fixed; inset: 0; background: rgba(6,6,5,0.6); backdrop-filter: blur(3px);
  opacity: 0; pointer-events: none; transition: opacity .42s ease; z-index: 1150; }
body.drawer-open .navdrawer__scrim { opacity: 1; pointer-events: auto; }
body.drawer-open { overflow: hidden; }

/* the header can no longer collide: below 1100px the links become a drawer */
@media (max-width: 1100px) {
  .nav__links a:not(.nav__cart) { display: none; }
  .nav__burger { display: block; }
  .nav__links { gap: 18px; }
}
@media (max-width: 720px) {
  :root { --nav-h: 84px; }
  .nav__logo img { height: 46px !important; width: auto !important; }
}

/* footer */
.footer__news label { display: block; font-size: 0.58rem; letter-spacing: 0.26em; text-transform: uppercase;
  color: var(--gold-bright); margin-bottom: 12px; }
.footer__newsrow { display: flex; border-bottom: 1px solid rgba(255,255,255,0.25); }
.footer__newsrow input { flex: 1; background: none; border: 0; color: var(--paper); padding: 11px 0;
  font-family: var(--font-body); font-size: 0.9rem; }
.footer__newsrow input:focus-visible { outline: none; }
.footer__newsrow button { background: none; border: 0; color: var(--gold-bright); cursor: pointer;
  font-family: var(--font-body); font-size: 0.58rem; letter-spacing: 0.26em; text-transform: uppercase; padding: 0 4px; }
.footer__consent { font-size: 0.68rem; line-height: 1.8; opacity: 0.45; margin-top: 12px; max-width: 300px; }
.footer__consent a { text-decoration: underline; }
.footer__thanks { font-size: 0.88rem; line-height: 1.9; opacity: 0.8; max-width: 300px; }
.footer__legallinks { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.footer__legallinks a { opacity: 1; }
@media (max-width: 720px) { .footer__grid { grid-template-columns: 1fr; gap: 34px; } }

/* accessibility: a real focus ring and a skip link */
.skiplink { position: absolute; left: -9999px; top: 0; z-index: 2000; background: var(--gold);
  color: #12110e; padding: 12px 22px; font-size: 0.62rem; letter-spacing: 0.24em; text-transform: uppercase; }
.skiplink:focus { left: 12px; top: 12px; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--gold-bright); outline-offset: 3px; border-radius: 1px;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

/* header at small widths: bag sits with the burger, and the bar stays legible
   over the hero rather than floating on top of the radial */
@media (max-width: 1100px) {
  .nav__links { margin-left: auto; gap: 0; }
  .nav__burger { margin-left: 18px; }
  .nav:not(.scrolled)::before {
    content: ''; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(180deg, rgba(10,9,8,0.92) 0%, rgba(10,9,8,0.72) 62%, transparent 100%);
  }
  .nav { isolation: isolate; }
}

/* Intrinsic width/height attributes exist to reserve space and stop layout
   shift. Neither may become a hard LAYOUT size.
   This rule used to release only the height. The width attribute stayed live,
   so any image given a CSS height — the campaign strip is set to height:380px —
   was laid out at its attribute width against that height and squashed. A
   914x1600 portrait rendered 914x380. Release both; the browser still reserves
   the correct box from the attribute-derived aspect-ratio. */
/* Presentational width/height attributes reserve layout space before an image
   loads, which is what stops the page jumping. But left live they also SET the
   rendered size, which is how the campaign panels ended up squashed. Releasing
   both to auto fixed that.

   The side effect, found in the nav: this selector is (0,2,1) and beats
   `.nav__logo img { height: 60px }` at (0,1,1), so the mark ignored its own
   sizing and rendered at its natural ratio — 79px inside a 92px bar, 6px of
   air above it. Anything that sets its own height opts out. */
img[width][height] { width: auto; height: auto; }

/* the bag shows two colours: the acetate and the lens. Never a hex code. */
.cart-item__swatches { display: flex; flex-direction: column; gap: 5px; }
.cart-item__swatch { display: block; width: 42px; height: 42px; border-radius: 2px;
  border: 1px solid rgba(255,255,255,0.18); }
.cart-item__swatch--lens { height: 20px; }


/* ============================================ GRID: no dead columns
   A two-column block whose left side is a short heading and whose right side is
   a long list was centring the heading, leaving hundreds of pixels of empty
   column. The heading now sticks to the top of the viewport as the list scrolls
   past it, so the column is never dead. */
.grid-2[data-sticky] > :first-child { position: sticky; top: calc(var(--nav-h) + 40px); align-self: start; }
@media (max-width: 860px) { .grid-2[data-sticky] > :first-child { position: static; } }

/* The journey list crushed its description into a ~90px column on anything
   narrower than a desktop. It now drops to two rows instead of four columns. */
@media (max-width: 1080px) {
  .journey__row { grid-template-columns: 60px 1fr; gap: 8px 20px; }
  .journey__row h3, h4 { grid-column: 2; }
  .journey__row p  { grid-column: 2; }
  .journey__row > :last-child { grid-column: 2; justify-self: start; }
  .journey__row .num { grid-row: 1 / span 3; align-self: start; }
}

/* Auto-fit grids left a hole when a row was not full. Centre the last row. */
[data-stagger] { justify-content: center; }

/* ============================================ HEADER: stop the bleed
   The fixed bar was painting a dark band across the cream sections and content
   was scrolling underneath it. Anchored content now clears the bar. */
:target, [id]:not(body):not(html) { scroll-margin-top: calc(var(--nav-h) + 24px); }
.nav { box-shadow: none; }
.nav.scrolled { box-shadow: 0 1px 0 rgba(0,0,0,0.18); }
.footer__mark { font-size: 0.62rem; letter-spacing: 0.34em; text-transform: uppercase;
  opacity: 0.5; margin-top: 12px; }
.footer__mark sup { font-size: 0.7em; }

/* consent — required before any personal data is taken */
.consent { display: flex; gap: 12px; align-items: flex-start; margin: 22px 0 6px;
  font-size: 0.8rem; line-height: 1.7; opacity: 0.78; cursor: pointer; }
.consent input { margin-top: 3px; flex: 0 0 auto; width: 16px; height: 16px;
  accent-color: var(--gold); }
.consent a { text-decoration: underline; }
.rights { font-size: 0.76rem; line-height: 1.9; opacity: 0.62; margin-top: 14px;
  border-left: 2px solid var(--gold); padding-left: 16px; }
.rights a { text-decoration: underline; }

/* a forthcoming piece must not read as a sold-out one */
.pcard__flag { font-size: 0.58rem; letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--gold); opacity: 0.85; margin-top: 14px; }
/* 9 Sep 2026. The third collection card. It used to be a grey box saying the
   frames were not photographed yet, which next to two real product shots read
   as a failed image. Same ground and same 4/4.6 ratio as the photo tiles, set
   as type: a stated intention rather than a hole. */
.nexttile { display: flex; flex-direction: column; align-items: center;
  justify-content: center; aspect-ratio: 4/4.6; background: #f7f6f4;
  text-align: center; padding: 8% 10%; }
.nexttile__names { font-family: var(--font-display, Georgia, serif); font-weight: 400;
  font-size: clamp(1.35rem, 2.4vw, 2rem); line-height: 1.28; color: var(--ink, #1a1a1a);
  opacity: 0.82; }
.nexttile__amp { font-family: inherit; font-style: italic; font-size: 0.62em;
  opacity: 0.5; }
.nexttile__rule { display: block; width: 34px; height: 1px; margin: 20px 0 16px;
  background: var(--gold, #c8a86a); opacity: 0.55; }
.nexttile__when { font-size: 0.6rem; letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--gold-ink, var(--gold, #c8a86a)); opacity: 0.85; }
.pcard__which { position: absolute; left: 14px; bottom: 14px; z-index: 2;
  background: rgba(10,9,8,0.72); color: var(--paper); padding: 7px 12px;
  font-size: 0.54rem; letter-spacing: 0.24em; text-transform: uppercase; }
/* available to screen readers, absent from the page */
.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; }


/* ================================================ HERO IS NEVER HIDDEN
   The headline and the buy buttons must not depend on an observer plus a
   transition completing. They render visible; the animation is the
   enhancement, applied only once JS confirms it can run. */
header .reveal, .hero .reveal, #main > header .reveal { opacity: 1; transform: none; }
html.ps-anim header .reveal:not(.in),
html.ps-anim .hero .reveal:not(.in) { opacity: 0; transform: translateY(24px); }

/* ================================================ TABLET / SMALL LAPTOP
   The site was built for >1200 and <500 and fell apart in between — which is
   every iPad and a lot of laptops. */
@media (max-width: 1200px) {
  .journey__row { grid-template-columns: 56px 1fr; gap: 6px 18px; padding: 24px 0; }
  .journey__row h3, .journey__row h4 { grid-column: 2; font-size: 1.3rem; }
  .journey__row p { grid-column: 2; }
  .journey__row > :last-child { grid-column: 2; justify-self: start; margin-top: 6px; }
  .journey__row .num { grid-row: 1 / span 3; align-self: start; }
  .grid-2 { gap: calc(var(--pad) * 0.8); }
}
@media (max-width: 1100px) and (min-width: 861px) {
  /* a 2-up grid of three products leaves one stranded beside a hole */
  #collectionGrid { grid-template-columns: 1fr 1fr; }
  #collectionGrid > :last-child { grid-column: 1 / -1; max-width: 520px; margin: 0 auto; }
}
@media (max-width: 1000px) {
  .grid-2 { grid-template-columns: 1fr; }
  .grid-2[data-sticky] > :first-child { position: static; }
}
@media (max-width: 1200px) and (min-width: 861px) {
  :root { --pad: 44px; }
  .display--lg { font-size: clamp(2.2rem, 5vw, 3.4rem); }
}

/* ================================================ NOTHING UNDER THE HEADER
   Fixed bars eat the top of any panel that positions itself from the top. */
.hud, .hud__readout, #hudReadout, .specbar, .pdp-spec {
  top: calc(var(--nav-h) + 20px) !important;
}
.legal h1, .wrap > h1 { scroll-margin-top: calc(var(--nav-h) + 30px); }
.await { font-family: var(--font-body); font-size: 0.44em; letter-spacing: 0.2em;
  text-transform: uppercase; opacity: 0.55; vertical-align: middle; }

/* ================================== NATIVE CONTROLS, DRESSED
   Two colour wells, a checkbox and a slider were shipping as raw OS widgets on
   a page arguing for hand-finishing. Same elements, same semantics, house skin. */
.ctrl-row { display: flex; flex-wrap: wrap; gap: 22px; align-items: center; }
.ctrl-row label { display: inline-flex; align-items: center; gap: 12px;
  font-size: 0.58rem; letter-spacing: 0.24em; text-transform: uppercase; opacity: 0.72; }

input[type="color"] {
  -webkit-appearance: none; appearance: none;
  width: 44px; height: 30px; padding: 0; cursor: pointer;
  background: none; border: 1px solid rgba(0,0,0,0.28); border-radius: 0;
}
input[type="color"]::-webkit-color-swatch-wrapper { padding: 3px; }
input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 0; }
input[type="color"]::-moz-color-swatch { border: 0; border-radius: 0; }

/* checkbox → a small square that fills gold when set */
input[type="checkbox"].ps-check {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border: 1px solid rgba(0,0,0,0.42);
  background: transparent; cursor: pointer; position: relative; flex: 0 0 auto;
  transition: background .2s ease, border-color .2s ease;
}
input[type="checkbox"].ps-check:checked { background: var(--gold); border-color: var(--gold); }
input[type="checkbox"].ps-check:checked::after {
  content: ''; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
  border: solid #12110e; border-width: 0 1.6px 1.6px 0; transform: rotate(42deg);
}

/* slider → a hairline track with a brass thumb */
input[type="range"].ps-range {
  -webkit-appearance: none; appearance: none;
  width: 150px; height: 18px; background: none; cursor: pointer;
}
input[type="range"].ps-range::-webkit-slider-runnable-track {
  height: 1px; background: rgba(0,0,0,0.32);
}
input[type="range"].ps-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; margin-top: -7px; border-radius: 50%;
  background: var(--gold); border: 1px solid rgba(0,0,0,0.35);
  box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
input[type="range"].ps-range::-moz-range-track { height: 1px; background: rgba(0,0,0,0.32); }
input[type="range"].ps-range::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%; background: var(--gold);
  border: 1px solid rgba(0,0,0,0.35);
}
.bg-ink input[type="checkbox"].ps-check { border-color: rgba(255,255,255,0.45); }
.bg-ink input[type="range"].ps-range::-webkit-slider-runnable-track { background: rgba(255,255,255,0.3); }
.provisional { margin-top: 18px; padding: 14px 16px; border: 1px solid rgba(200,168,106,0.45);
  background: rgba(200,168,106,0.07); font-size: 0.76rem; line-height: 1.8; opacity: 0.85; }

/* a panel label is not a document heading */
.panel-label { font-size: 0.58rem; letter-spacing: 0.28em; text-transform: uppercase;
  opacity: 0.55; margin: 26px 0 12px; }

/* the colour ribbon must be stoppable — WCAG 2.2.2 */
.ribbon { position: relative; }
.ribbon.is-paused .ribbon__inner { animation-play-state: paused; }
.ribbon__pause { position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  z-index: 2; background: rgba(10,9,8,0.72); border: 1px solid rgba(200,168,106,0.5);
  color: var(--gold); font-family: var(--font-body); font-size: 0.5rem; letter-spacing: 0.22em;
  text-transform: uppercase; padding: 7px 11px; cursor: pointer; }
.ribbon:hover .ribbon__inner { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .ribbon__inner { animation: none; } }

/* ================================================ THE STAGE (photographs)
   Real angles of the real frame, not a canvas drawing. */
.stage-photo { position: relative; width: 100%; height: 100%; display: block;
  cursor: grab; user-select: none; -webkit-user-select: none; touch-action: pan-y;
  background: #0e0d0b; overflow: hidden; }
.stage-photo.is-dragging { cursor: grabbing; }
.stage-photo:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: -4px; }
.stage-photo__track { position: absolute; inset: 0; }
.stage-photo__img { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; opacity: 0; transition: opacity .28s ease; pointer-events: none;
  mix-blend-mode: normal; }
.stage-photo__img.is-on { opacity: 1; }
.stage-photo__veil { position: absolute; inset: 0; pointer-events: none;
  mix-blend-mode: hue; opacity: 0; transition: opacity .3s ease, background .3s ease; }
.stage-photo__caption { position: absolute; left: 0; right: 0; bottom: 62px; margin: 0;
  text-align: center; font-size: 0.56rem; letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--paper); opacity: 0.55; pointer-events: none; }
.stage-photo__dots { position: absolute; left: 0; right: 0; bottom: 28px;
  display: flex; gap: 10px; justify-content: center; z-index: 3; }
.stage-photo__dot { width: 8px; height: 8px; border-radius: 50%; padding: 0;
  border: 1px solid rgba(245,242,234,0.5); background: transparent; cursor: pointer;
  transition: background .25s ease, transform .25s ease; }
.stage-photo__dot.is-on { background: var(--gold); border-color: var(--gold); transform: scale(1.3); }
@media (max-width: 860px) {
  .stage-photo__caption { bottom: 54px; font-size: 0.5rem; }
  .stage-photo__dots { bottom: 22px; }
}

/* ---- the stage now holds packshots on a paper sweep, so the furniture
   that used to sit on black has to invert to read at all ---- */
.stage-photo { background: #f1f1f1; }
.stage-photo__img { object-fit: contain; }
.stage-photo__caption { color: var(--ink); opacity: 0.45; bottom: 54px; }
.stage-photo__dot { border-color: rgba(0,0,0,0.32); }
.stage-photo__dot.is-on { background: var(--gold); border-color: var(--gold); }

.pdp__stage:has(.stage-photo) .hud__readout,
.pdp__stage:has(.stage-photo) .hud__edition { color: var(--ink); }
.pdp__stage:has(.stage-photo) .hud__readout { background: rgba(255,255,255,0.82);
  backdrop-filter: blur(6px); padding: 14px 16px; border: 1px solid rgba(0,0,0,0.08);
  max-width: 210px; }
.pdp__stage:has(.stage-photo) .hud__readout b { color: #12110e; }
.pdp__stage:has(.stage-photo) .hud__edition { color: #8a6f34; }
.pdp__stage:has(.stage-photo) .hud__corner { border-color: rgba(0,0,0,0.22) !important; }
/* over a real photograph the stage ground is near-white, so the hint goes ink
   — but 0.42 opacity took it back under AA. */
.pdp__stage:has(.stage-photo) .stage__hint { color: var(--ink); opacity: 0.8; }
.pdp__stage:has(.stage-photo) .hud__scan { display: none; }

/* fallback for browsers without :has() */
.stage-photo ~ .hud .hud__readout { color: var(--ink); }

/* keep the whole frame in shot and leave room for the furniture */
.stage-photo .stage-photo__img { object-fit: contain !important;
  padding: 40px 40px 86px; box-sizing: border-box; }
.stage-photo__caption { z-index: 4; }
.stage-photo__dots { z-index: 4; }
.stage-photo__dot { width: 9px; height: 9px; background: rgba(0,0,0,0.10); }
@media (max-width: 860px) { .stage-photo .stage-photo__img { padding: 24px 20px 74px; } }

/* ============================== STAGE FURNITURE: one zone each
   Four separate labels were all anchored to the bottom of the viewer and piled
   on top of one another with the carousel dots over the words. Each now owns a
   corner and nothing shares a band. */
.pdp__stage .hud__readout { top: 18px; left: 18px; bottom: auto; }
.pdp__stage .hud__edition { top: 18px; left: auto; right: 18px; bottom: auto;
  text-align: right; max-width: 210px; }
.pdp__stage .hud__edition small { text-align: right; }
.pdp__stage .stage__hint { top: auto; bottom: 74px; }
.stage-photo__caption { bottom: 46px; }
.stage-photo__dots { bottom: 20px; }
.stage-photo .stage-photo__img { padding: 96px 40px 104px; }

@media (max-width: 900px) {
  .pdp__stage .hud__edition { top: 12px; right: 12px; font-size: 0.95rem; max-width: 150px; }
  .pdp__stage .hud__edition small { font-size: 0.46rem; letter-spacing: 0.14em; }
  .pdp__stage .stage__hint { bottom: 66px; font-size: 0.48rem; }
  .stage-photo__caption { bottom: 42px; }
  .stage-photo__dots { bottom: 18px; }
  .stage-photo .stage-photo__img { padding: 74px 18px 92px; }
}

/* the configurator must never swallow the wheel */
.pdp, .pdp__panel { overscroll-behavior: auto; }
.pdp__panel { overflow: visible; }

/* ============================================ ZOOM
   The enlarged view is a gallery, not a single picture: arrows either side,
   a thumbnail rail along the bottom, a counter. Scroll or pinch to magnify,
   drag to pan, Escape to close. */
.zoomer { position: fixed; inset: 0; z-index: 2000;
  background: #0b0a09;
  background-image: radial-gradient(ellipse at 50% 42%, #16140f 0%, #0b0a09 68%);
  opacity: 0; transition: opacity .26s ease; overflow: hidden; touch-action: none;
  display: grid; grid-template-rows: 1fr auto; }
.zoomer.is-open { opacity: 1; }

/* the picture fills the room it is given, minus the rail and the chrome */
.zoomer__frame { position: relative; display: grid; place-items: center;
  min-height: 0; padding: 68px 92px 12px; }
.zoomer__img { max-width: 100%; max-height: 100%; width: auto; height: auto;
  transform-origin: center; transition: transform .12s linear, opacity .18s ease;
  cursor: zoom-in; user-select: none; -webkit-user-drag: none; display: block;
  background: var(--paper-deep, #f7f6f4); }
.zoomer__img.is-swapping { opacity: 0; }

/* arrows — big enough to hit, quiet enough not to shout */
.zoomer__nav { position: absolute; top: 50%; transform: translateY(-50%);
  width: 60px; height: 60px; display: grid; place-items: center; cursor: pointer;
  background: rgba(18,17,14,0.5); border: 1px solid rgba(200,168,106,0.42);
  border-radius: 50%; color: var(--gold-bright); z-index: 3;
  transition: background .22s ease, border-color .22s ease, transform .22s ease;
  backdrop-filter: blur(6px); }
.zoomer__nav svg { width: 26px; height: 26px; fill: none; stroke: currentColor;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.zoomer__nav:hover { background: rgba(18,17,14,0.86); border-color: var(--gold-bright); }
.zoomer__nav--prev { left: 22px; }
.zoomer__nav--next { right: 22px; }
.zoomer__nav--prev:hover { transform: translateY(-50%) translateX(-3px); }
.zoomer__nav--next:hover { transform: translateY(-50%) translateX(3px); }
.zoomer__nav:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; }

/* the bar underneath: what you are looking at, the other views, where you are */
.zoomer__bar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 20px; padding: 14px 28px 22px; border-top: 1px solid rgba(200,168,106,0.16); }
.zoomer__cap { margin: 0; color: var(--paper); opacity: 0.72; font-size: 0.56rem;
  letter-spacing: 0.26em; text-transform: uppercase; justify-self: start; }
.zoomer__count { margin: 0; color: var(--gold); font-size: 0.56rem;
  letter-spacing: 0.24em; justify-self: end; font-variant-numeric: tabular-nums; }
.zoomer__rail { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none;
  max-width: min(560px, 60vw); padding: 2px; }
.zoomer__rail::-webkit-scrollbar { display: none; }
.zoomer__thumb { flex: 0 0 auto; width: 56px; height: 56px; padding: 0; cursor: pointer;
  background: var(--paper-deep, #f7f6f4); border: 1px solid rgba(255,255,255,0.14);
  opacity: 0.5; transition: opacity .22s ease, border-color .22s ease; }
.zoomer__thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.zoomer__thumb:hover { opacity: 0.85; border-color: rgba(200,168,106,0.6); }
.zoomer__thumb.is-on { opacity: 1; border-color: var(--gold-bright); }
.zoomer__thumb:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }

.zoomer__close { position: absolute; top: 22px; right: 26px; z-index: 4;
  display: inline-flex; align-items: center; gap: 9px;
  background: rgba(18,17,14,0.5); backdrop-filter: blur(6px);
  border: 1px solid rgba(200,168,106,0.5); color: var(--gold-bright); cursor: pointer;
  font-family: var(--font-body); font-size: 0.54rem; letter-spacing: 0.24em;
  text-transform: uppercase; padding: 10px 16px;
  transition: background .22s ease, border-color .22s ease; }
.zoomer__close svg { width: 13px; height: 13px; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; }
.zoomer__close:hover { background: rgba(18,17,14,0.9); border-color: var(--gold-bright); }

.zoomer__hint { position: absolute; top: 30px; left: 50%; transform: translateX(-50%);
  margin: 0; z-index: 3; white-space: nowrap;
  color: var(--paper); opacity: 0.3; font-size: 0.48rem; letter-spacing: 0.22em;
  text-transform: uppercase; pointer-events: none; transition: opacity .22s ease; }
.zoomer.is-zoomed .zoomer__hint { opacity: 0; }
@media (max-width: 1100px) { .zoomer__hint { display: none; } }

@media (max-width: 860px) {
  .zoomer__frame { padding: 60px 14px 8px; }
  .zoomer__nav { width: 46px; height: 46px; }
  .zoomer__nav svg { width: 20px; height: 20px; }
  .zoomer__nav--prev { left: 8px; }
  .zoomer__nav--next { right: 8px; }
  .zoomer__bar { grid-template-columns: 1fr; gap: 10px; justify-items: center;
    padding: 12px 14px 18px; }
  .zoomer__cap, .zoomer__count { justify-self: center; }
  .zoomer__count { order: -1; }
  .zoomer__rail { max-width: 92vw; }
  .zoomer__thumb { width: 46px; height: 46px; }
  .zoomer__hint { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .zoomer, .zoomer__img, .zoomer__nav { transition: none; }
}

.stage-photo { cursor: zoom-in; }
.stage-photo.is-dragging { cursor: grabbing; }

/* ============================== THE BURGER MUST BE FINDABLE
   Three thin currentColor bars over a dark radial read as nothing. It is the
   only way to navigate below 1100px, so it gets a border, gold bars and a label. */
.nav__burger { border: 1px solid rgba(200,168,106,0.55); padding: 11px 12px;
  background: rgba(10,9,8,0.55); backdrop-filter: blur(6px); border-radius: 1px;
  display: none; align-items: center; gap: 9px; }
.nav__burger span { background: var(--gold-bright); width: 22px; height: 1.6px; margin: 5px 0; }
.nav__burger::after { content: 'Menu'; font-family: var(--font-body); font-size: 0.5rem;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--gold-bright);
  margin-left: 2px; }
.nav__burger:hover { border-color: var(--gold-bright); background: rgba(10,9,8,0.75); }
body.drawer-open .nav__burger::after { content: 'Close'; }
@media (max-width: 1100px) { .nav__burger { display: inline-flex; } }
.nav__burger > span:nth-child(1) { margin-top: 0; }
.nav__burger > span:nth-child(3) { margin-bottom: 0; }
/* stack the three bars, then the word beside them */
.nav__burger { flex-direction: row; }
.nav__burger > span { display: block; }
.nav__burger-bars { display: inline-block; }
.nav__burger-bars span { display: block; width: 22px; height: 1.6px;
  background: var(--gold-bright); margin: 5px 0; transition: transform .3s ease, opacity .3s ease; }
.nav__burger-bars span:first-child { margin-top: 0; }
.nav__burger-bars span:last-child { margin-bottom: 0; }
body.drawer-open .nav__burger-bars span:nth-child(1) { transform: translateY(6.6px) rotate(45deg); }
body.drawer-open .nav__burger-bars span:nth-child(2) { opacity: 0; }
body.drawer-open .nav__burger-bars span:nth-child(3) { transform: translateY(-6.6px) rotate(-45deg); }
/* One tile per view. Square, same size, same background — the set reads as a set. */
.gthumb { position: relative; padding: 0; cursor: zoom-in; display: block;
  aspect-ratio: 1 / 1; overflow: hidden;
  background: var(--paper-deep, #f7f6f4);
  border: 1px solid rgba(18,17,14,0.10);
  transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease; }
.gthumb img { display: block; width: 100%; height: 100%; object-fit: contain;
  transition: transform .5s cubic-bezier(.16,.6,.2,1); }
.gthumb:hover { border-color: var(--gold); transform: translateY(-2px);
  box-shadow: 0 8px 22px rgba(18,17,14,0.10); }
.gthumb:hover img { transform: scale(1.045); }
.gthumb.on { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.gthumb:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* a quiet magnifier, so it is obvious the tile opens */
.gthumb::after { content: ''; position: absolute; right: 7px; bottom: 7px;
  width: 15px; height: 15px; opacity: 0; transition: opacity .25s ease;
  background: no-repeat center/contain
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c9a227' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5 21 21M10.5 7.5v6M7.5 10.5h6'/%3E%3C/svg%3E"); }
.gthumb:hover::after { opacity: 0.9; }

/* ============================================ THE REAL FOOTAGE
   Two of the craft panels are film from the bench and the cutting floor, not
   photographs. They sit in the same 4:3 slot as the stills either side of them
   so the row still reads as one grid. Muted and looping — no controls, nothing
   to click, they simply run. `prefers-reduced-motion` gets the poster instead. */
.craftvid { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block;
  background: var(--paper-deep, #f1efe9); }
@media (prefers-reduced-motion: reduce) {
  .craftvid { /* the poster frame stands in; the browser holds on it when paused */ }
}

/* ---------------------------------------------------------------- THE COLLECTION
   Three cards. The column count now lives here rather than in an inline style,
   which was overriding every media query and leaving an empty third column at
   the widths between 861 and 1100px. */
#collectionGrid { grid-template-columns: repeat(3, 1fr); gap: calc(var(--pad) * 0.6); }
@media (max-width: 1100px) {
  #collectionGrid { grid-template-columns: 1fr 1fr; }
  #collectionGrid > :last-child { grid-column: 1 / -1; max-width: 520px; margin: 0 auto; }
}
@media (max-width: 700px) {
  #collectionGrid { grid-template-columns: 1fr; }
  #collectionGrid > :last-child { max-width: none; }
}
/* three packaging shots, three columns — no stranded third */
@media (max-width: 760px) {
  .reveal[style*="max-width:820px"][style*="grid"] { grid-template-columns: 1fr !important; }
}

/* ============================================================
   ACCESSIBILITY — contrast and minimum type size
   An audit measured gold text at 2.96:1 on paper and text down to 8.8px.
   Two causes, both fixed here rather than in twenty page-level <style> blocks:
     1. --gold is a decorative gold. On paper it is 2.96:1 and fails AA.
     2. Small caps type was ALSO carrying opacity 0.5-0.75, which multiplies
        into the contrast ratio — a 5:1 colour at 0.6 opacity measures ~3:1.
   So: gold text on a light ground goes to --gold-ink, and the opacity comes
   off anything already set in a muted colour.
   ============================================================ */

/* ---- 1. Gold TEXT: the right gold for the ground it sits on ----
   --gold (2.96:1 on paper) was carrying text on both light and dark sections.
   The body default is ink, so the default here is the bright gold; light
   containers switch to --gold-ink; and a dark island inside a light page wins
   again because its rule comes last at equal specificity. */

/* every place gold is used as TEXT rather than as a rule or a border */
[style*="color:var(--gold)"], .opt-group h3, .pcard__flag, .journey__row .num,
.bagslot__num, .slotph .roman, .slotph .lab, .slotph .ai, .bgal__thumbs .n,
.spec dt, .field label, .rxguide .ex, .link-quiet, .btn--gold {
  color: var(--gold-bright) !important;
}

.bg-paper [style*="color:var(--gold)"], .bg-paper-deep [style*="color:var(--gold)"],
.drawer [style*="color:var(--gold)"], .panel [style*="color:var(--gold)"],
.pdp__panel [style*="color:var(--gold)"], body.bg-paper [style*="color:var(--gold)"],
.bg-paper .opt-group h3, .pdp__panel .opt-group h3, body.bg-paper .opt-group h3,
.bg-paper .pcard__flag, body.bg-paper .pcard__flag,
.bg-paper .journey__row .num, body.bg-paper .journey__row .num,
.bg-paper .bagslot__num, body.bg-paper .bagslot__num,
body.bg-paper .slotph .roman, body.bg-paper .slotph .lab, body.bg-paper .slotph .ai,
body.bg-paper .bgal__thumbs .n,
.bg-paper .spec dt, body.bg-paper .spec dt,
.bg-paper .field label, .panel .field label, body.bg-paper .field label,
.bg-paper .rxguide .ex, body.bg-paper .rxguide .ex,
.bg-paper .link-quiet, .bg-paper-deep .link-quiet, .pdp__panel .link-quiet,
body.bg-paper .link-quiet, .drawer .link-quiet,
.bg-paper .btn--gold, .bg-paper-deep .btn--gold, .panel .btn--gold, body.bg-paper .btn--gold {
  color: var(--gold-ink) !important;
}

/* a dark island inside a light page takes the bright gold back */
.bg-ink [style*="color:var(--gold)"], .bg-ink-soft [style*="color:var(--gold)"],
.campaign [style*="color:var(--gold)"],
.bg-ink .opt-group h3, .bg-ink-soft .opt-group h3,
.bg-ink .pcard__flag, .bg-ink-soft .pcard__flag,
.bg-ink .journey__row .num, .bg-ink-soft .journey__row .num,
.bg-ink .bagslot__num, .bg-ink-soft .bagslot__num,
.bg-ink .slotph .roman, .bg-ink .slotph .lab, .bg-ink .slotph .ai,
.bg-ink .bgal__thumbs .n,
.bg-ink .spec dt, .bg-ink-soft .spec dt,
.bg-ink .field label, .bg-ink-soft .field label,
.bg-ink .link-quiet, .bg-ink-soft .link-quiet, .campaign .link-quiet,
.bg-ink .btn--gold, .bg-ink-soft .btn--gold, .campaign .btn--gold {
  color: var(--gold-bright) !important;
}
.bg-paper .btn--gold, .bg-paper-deep .btn--gold, .panel .btn--gold, body.bg-paper .btn--gold { border-color: var(--gold-ink); }
.bg-paper .btn--gold:hover, .bg-paper-deep .btn--gold:hover, .panel .btn--gold:hover { background: var(--gold-ink); color: var(--paper) !important; }

/* ---- 2. Opacity was eating the contrast ratio ---- */
.eyebrow { opacity: 1 !important; }
.pcard__flag, .journey__row .tag, .bagslot__note, .bagslot .ai,
.spec dt, .field label, .footer__consent, .ribbon__item,
.hud__edition small, .await, .stage__hint, .breakdown,
.navdrawer__legal a, .footer__mark, .panel-label, .pcard__which {
  opacity: 1 !important;
}
/* keep a softer look without dropping below AA */
.journey__row .tag, .ribbon__item, .footer__consent { color: rgba(18,17,14,0.68); }
.bg-ink .journey__row .tag, .bg-ink .ribbon__item, .bg-ink .footer__consent,
.bg-ink-soft .journey__row .tag, .bg-ink-soft .ribbon__item { color: rgba(245,242,234,0.78); }
.hud__edition small, .await, .stage__hint, .breakdown { color: rgba(245,242,234,0.88); }

/* ---- 3. A floor under the type size, at EVERY width ----
   9px small-caps with 0.3em tracking is not a design choice, it is an
   unreadable one. Nothing carrying words goes below 12px. */
.eyebrow, .pcard__flag, .pcard__which, .journey__row .tag, .ribbon__item,
.bagslot__note, .bagslot .ai, .spec dt, .field label, .footer__consent,
.footer__grid h3, .footer__grid h4, .navdrawer__legal a, .footer__mark,
.panel-label, .cart-item button.remove, .drawer__close, .navdrawer__close,
.hud__edition small, .await, .breakdown, .stage__hint, .stage-photo__caption,
.opt-group h3, .opt-card .p, .rx th, .legend, .pick, .n, .tag,
.btn, .btn--solid, .btn--gold, .btn--white, .link-quiet,
.nav__links a, .nav__cart, .intro__tag, .intro__skip, .zoomer__cap, .zoomer__count {
  font-size: max(0.75rem, 1em) ;
}
.eyebrow { font-size: 0.75rem !important; letter-spacing: 0.26em; }
.btn, .btn--solid, .btn--gold, .btn--white { font-size: 0.75rem; letter-spacing: 0.22em; }
.link-quiet { font-size: 0.75rem; letter-spacing: 0.2em; }
.nav__links a, .nav__cart { font-size: 0.75rem; letter-spacing: 0.16em; }
.footer__grid h3, .footer__grid h4 { font-size: 0.75rem; letter-spacing: 0.26em; }
.pcard__flag, .pcard__which, .journey__row .tag, .ribbon__item, .bagslot__note,
.spec dt, .field label, .panel-label, .footer__mark, .navdrawer__legal a,
.cart-item button.remove, .drawer__close, .navdrawer__close, .tag, .legend, .pick {
  font-size: 0.75rem !important; letter-spacing: 0.16em;
}
.hud__edition small, .await, .breakdown, .stage__hint, .stage-photo__caption,
.zoomer__cap, .zoomer__count, .intro__tag, .intro__skip, .bagslot .ai {
  font-size: 0.75rem; letter-spacing: 0.16em;
}
.opt-group h3 { font-size: 0.75rem; letter-spacing: 0.28em; }
.rx th { font-size: 0.75rem; letter-spacing: 0.14em; }
.opt-card .p { font-size: 0.85rem; }
.bagslot .n { font-size: 0.9rem; }
@media (max-width: 900px) {
  .eyebrow, .btn, .link-quiet, .nav__links a, .nav__cart { letter-spacing: 0.14em; }
}

/* ---- 4. Touch targets. WCAG 2.5.8 asks 24px; 44px is comfortable. ---- */
@media (pointer: coarse) {
  button, .btn, a.btn, .swatch, .opt-card, .gthumb, .n, .pick {
    min-height: 44px;
  }
  .swatch, .gthumb { min-width: 44px; }
  input[type="checkbox"], input[type="radio"] { min-width: 24px; min-height: 24px; }
}

/* ---- 5. State announced by more than colour, and a visible focus ring ---- */
[aria-pressed="true"] { outline: 1px solid var(--gold); outline-offset: 2px; }
:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; }

/* The ribbon prints each colourway name in that colourway. Some of the house
   colours land under 4.5:1 on paper at small size, so the names are set at the
   large-text threshold (24px) where 3:1 applies and they all pass. */
.ribbon__item .cw-name, .ribbon__item strong, .ribbon__item em { font-size: 1.5rem; }

/* A dark section inside a page whose <body> carries .bg-paper: `body.bg-paper X`
   outranks `.bg-ink X` on specificity, so the dark island needs the same weight
   and a later position to take the bright gold back. */
body .bg-ink [style*="color:var(--gold)"], body .bg-ink-soft [style*="color:var(--gold)"],
body .bg-ink .field label, body .bg-ink-soft .field label,
body .bg-ink .link-quiet, body .bg-ink-soft .link-quiet,
body .bg-ink .spec dt, body .bg-ink-soft .spec dt,
body .bg-ink .opt-group h3, body .bg-ink-soft .opt-group h3,
body .bg-ink .btn--gold, body .bg-ink-soft .btn--gold,
body .bg-ink .journey__row .num, body .bg-ink-soft .journey__row .num,
body .bg-ink .pcard__flag, body .bg-ink-soft .pcard__flag {
  color: var(--gold-bright) !important;
}
body .bg-ink .btn--gold, body .bg-ink-soft .btn--gold { border-color: var(--gold); background: transparent; }
body .bg-ink .btn--gold:hover, body .bg-ink-soft .btn--gold:hover { background: var(--gold); color: var(--ink) !important; }

/* A <select> on a dark section inherits the dark ground, so its options were
   rendering ink-on-ink — the chosen value was invisible until you opened it. */
.bg-ink .field select option, .bg-ink-soft .field select option,
body .bg-ink select option, body .bg-ink-soft select option {
  color: var(--ink); background: var(--paper);
}

/* Inline sub-12px font sizes, at every width. There were 115 of them on the
   homepage alone, some as small as 8px with 0.3em tracking. */
[style*="font-size:0.7rem"], [style*="font-size: 0.7rem"],
[style*="font-size:0.6"], [style*="font-size: 0.6"],
[style*="font-size:0.5"], [style*="font-size: 0.5"],
[style*="font-size:0.4"], [style*="font-size: 0.4"] {
  font-size: 0.75rem !important;
}
[style*="letter-spacing:0.3em"], [style*="letter-spacing:0.34em"],
[style*="letter-spacing:0.38em"], [style*="letter-spacing:0.42em"] {
  letter-spacing: 0.2em;
}

/* The last of the sub-12px type: the skip link (only visible on focus, but it
   still has to be readable then), the ribbon pause control, the footer legal
   row, the newsletter label and the spec runs under the Coffret. */
.skiplink:focus, .skiplink { font-size: 0.75rem; }
.ribbon__pause { font-size: 0.72rem !important; letter-spacing: 0.14em; min-height: 32px; padding: 4px 10px; }
.footer__legal, .footer__legal a, .footer__legal span { font-size: 0.78rem; }
.footer__news label, .footer__news button { font-size: 0.75rem !important; letter-spacing: 0.16em; }

/* A text path to every product from every page. */
.footer__shop { display: flex; flex-wrap: wrap; gap: 10px 26px; padding-bottom: 22px;
                margin-bottom: 22px; border-bottom: 1px solid var(--line-dark); }
.footer__shop a { font-size: 0.8rem; opacity: 0.7; transition: opacity .25s; }
.footer__shop a:hover { opacity: 1; border-bottom: 1px solid var(--gold); }

/* Previous / next between the four Coffrets. */
.bagpager { display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap;
            margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--line-light); }
.bagpager a { font-size: 0.8rem; opacity: 0.75; }
.bagpager a:hover { opacity: 1; border-bottom: 1px solid var(--gold); }

/* UX-009 — the PAUSE control was positioned absolutely INSIDE the marquee's
   overflow box, so the colour names scrolled underneath it and the strip
   directly below the hero read as a rendering fault ("HONE…PAUSE…ISE").
   Reserve a gutter on the right and put the control in it. */


/* UX-010 — at the foot of the page the sticky header PS mark stacked directly
   above the footer PS mark and the wordmark: three brand lockups in a 200px
   column, which reads as a duplicated asset. Fade the header out once the
   footer is on screen. */
.nav { transition: background 0.4s ease, border-color 0.4s ease, opacity 0.35s ease, transform 0.35s ease; }
.nav.at-footer { opacity: 0; transform: translateY(-100%); pointer-events: none; }

/* A text path to every product from every page. */
.footer__shop { display: flex; flex-wrap: wrap; gap: 10px 26px; padding-bottom: 22px;
                margin-bottom: 22px; border-bottom: 1px solid var(--line-dark); }
.footer__shop a { font-size: 0.8rem; opacity: 0.7; transition: opacity .25s; }
.footer__shop a:hover { opacity: 1; border-bottom: 1px solid var(--gold); }

/* Previous / next between the four Coffrets. */
.bagpager { display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap;
            margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--line-light); }
.bagpager a { font-size: 0.8rem; opacity: 0.75; }
.bagpager a:hover { opacity: 1; border-bottom: 1px solid var(--gold); }

/* UX-009 — the PAUSE control was positioned absolutely INSIDE the marquee's
   overflow box, so the colour names scrolled underneath it and the strip
   directly below the hero read as a rendering fault ("HONE…PAUSE…ISE").
   Reserve a gutter on the right and put the control in it. */


/* UX-010 — at the foot of the page the sticky header PS mark stacked directly
   above the footer PS mark and the wordmark: three brand lockups in a 200px
   column, which reads as a duplicated asset. Fade the header out once the
   footer is on screen. */
.nav { transition: background 0.4s ease, border-color 0.4s ease, opacity 0.35s ease, transform 0.35s ease; }
.nav.at-footer { opacity: 0; transform: translateY(-100%); pointer-events: none; }

/* ============================================================
   PUR-001 — THE HERO.
   First attempt floated the product photograph as a card on top
   of the radial. Two whites two shades apart, a hard rectangle
   over a busy pattern: it read as a mistake, and it was.
   The panel now runs edge to edge and full height, so the
   photograph is a deliberate half of the composition. The panel
   takes the photograph's own ground (#f7f6f4, not --paper) so
   there is no visible image edge at all.
   ============================================================ */

/* (a stray closing brace sat here, orphaned by an earlier edit. CSS parsers
   recover from these silently, which is exactly why it survived nine rounds) */

/* the type floor above catches .intro__skip; the dismiss control needs to be
   bigger than the floor, not equal to it */
.intro__skip { font-size: 0.85rem !important; letter-spacing: 0.18em; }

/* If a page ever constrains both axes of a photograph, letterbox it rather
   than distort it. `fill` on a replaced element is almost never intended —
   it is what stretched the campaign strip 914x1600 into 914x380. */
img[style*="height:100%"][style*="width:100%"]:not([style*="object-fit"]) { object-fit: contain; }
.intro__skip { font-size: 0.85rem !important; letter-spacing: 0.18em; }

/* UX-009 — the PAUSE control was absolutely positioned INSIDE the marquee's
   overflow box. Padding does not clip, so the colour names scrolled underneath
   it and the strip read "DEEP …PAUSE… OCEAN". The ribbon is a flex row now:
   the animating track has its own clipping box, and the control sits beside it
   in normal flow with an opaque ground. Nothing can pass under it. */
.ribbon { display: flex; align-items: stretch; padding-right: 0; overflow: visible; }
.ribbon__track { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; }
.ribbon__pause { position: static; transform: none; flex: 0 0 auto;
  width: auto; min-width: 108px; display: flex; align-items: center; justify-content: center;
  background: var(--ink); border: 0; border-left: 1px solid var(--line-dark);
  color: var(--gold-bright); }
@media (max-width: 560px) { .ribbon__pause { min-width: 84px; } }

/* MOB-001 — REGRESSION, mine. The hero centres inside 100vh and the nav is
   fixed and 78px tall, so on a phone the eyebrow — the one line that says what
   the house is and what it sells — sat behind the logo. This went when I pulled
   out the split-hero CSS. It is a padding rule, not a layout change. */
@media (max-width: 900px) {
  .campaign { padding-top: calc(var(--nav-h) + 34px); }
}

/* CNT-005 — .footer__grid a { display: block } is for the link columns and was
   leaking into the consent paragraph, so the full stop after the Privacy Notice
   link was stranded alone on its own line under the newsletter signup. */
.footer__consent a, .footer__legal a, p a { display: inline; }

/* A11Y-007 — the edition readout sits over a product photograph whose backdrop
   is near-white, and it was near-white at 7.36px. That line is the reason the
   frame costs £350. It gets a scrim of its own so it is legible over any shot
   in the gallery, and it never drops below 12px. */
.hud__edition { background: rgba(18,17,14,0.72); padding: 10px 14px; border-radius: 2px;
                backdrop-filter: blur(3px); max-width: calc(100% - 24px); }
.hud__edition .await, .hud__edition small { color: #f5f2ea !important; }
.hud__edition small { font-size: 0.75rem !important; letter-spacing: 0.16em; opacity: 1; }
.hud__edition .await { font-size: 0.9rem !important; letter-spacing: 0.14em; }

/* MOB-005 — the dots were 9x9px and are the ONLY view switcher on a phone; the
   desktop thumbnails do not render there. Five of six views of a £350 frame
   were unhittable. The painted dot stays 9px; the target is 44px. */
.stage-photo__dots { gap: 0; }
.stage-photo__dot {
  width: 44px !important; height: 44px !important;
  padding: 17px; box-sizing: border-box;
  background-clip: content-box; border-radius: 50%;
  background-color: rgba(245,242,234,0.42);
}
.stage-photo__dot[aria-selected="true"], .stage-photo__dot.on {
  background-color: var(--gold-bright);
}

/* UX-006 — inline validation messaging */
.field-error { font-size: 0.8rem; line-height: 1.6; margin-top: 6px; color: #b81e2e; }
.bg-ink .field-error, .bg-ink-soft .field-error { color: #ff8a96; }
.form-summary { font-size: 0.85rem; line-height: 1.7; margin-bottom: 18px;
  padding: 12px 16px; border: 1px solid #b81e2e; color: #b81e2e; }
.bg-ink .form-summary, .bg-ink-soft .form-summary { border-color: #ff8a96; color: #ff8a96; }
[aria-invalid="true"] { border-color: #b81e2e !important; }

/* MOB-003 — the 44px target floor was keyed on `pointer: coarse` only, so it
   never applied to a narrow desktop window, which is exactly how most people
   check a site on a phone-sized viewport. Key it on width as well. */
@media (max-width: 860px) {
  button, .btn, a.btn, .swatch, .opt-card, .gthumb, .n, .pick, .tab,
  .nav__cart, .navdrawer__close, .drawer__close, .cart-item button.remove,
  .ribbon__pause, .vidtoggle, .fbtn, .sw, .stage-photo__dot, .bagslot,
  .footer__news button, .arcade-stage {
    min-height: 44px;
  }
  .swatch, .gthumb, .sw, .stage-photo__dot { min-width: 44px; }
  /* NB: `.footer__grid a` also matches the Privacy Notice link inside the
     consent paragraph, which is prose — making it a block re-strands the full
     stop on its own line (CNT-005). Exclude prose links explicitly. */
  .footer__grid a:not(.footer__consent a), .footer__shop a,
  .navdrawer__legal a, .footer__legal a,
  .link-quiet, .trust a, .bagpager a {
    display: inline-block; padding: 11px 0; min-height: 44px;
  }
  input[type="checkbox"], input[type="radio"] { min-width: 24px; min-height: 24px; }
}

/* CNT-005, belt and braces: a link inside a sentence is part of the sentence.
   MOB-004: but a ROW of links is not a sentence. This rule was flattening
   "See the certificate", "See the book of the edition" and "Verify a piece" to
   15px tall, because they happen to sit in a <p>. .linkrow opts out. */
.footer__consent a:not(.link-quiet), p:not(.linkrow) a:not(.link-quiet):not(.tap),
li a:not(.link-quiet), dd a:not(.link-quiet), summary a:not(.link-quiet) {
  display: inline !important; padding: 0 !important; min-height: 0 !important;
}

/* MOB-004, second pass. The first fix was opt-in per markup instance
   (.linkrow on the paragraph), which meant every quiet link written after it
   started non-compliant. The rule now lives on the COMPONENT: .link-quiet and
   .skiplink are 44px wherever they appear, and the prose rule above explicitly
   steps aside for them. .linkrow stays, but only for layout. */
.link-quiet, a.skiplink, .linkrow a, a.tap {
  display: inline-flex !important; align-items: center;
  min-height: 44px !important; padding: 10px 0 !important;
}

/* UX-005 — the contact form sat alone in a 640px column with the right 40% of
   the page empty down its whole length. The panel beside it repeats nothing:
   the address to write to, what can be answered without writing at all, and
   the company details a UK trader has to show. */
.contact__grid { display: grid; grid-template-columns: minmax(0,1.1fr) minmax(0,0.75fr);
                 gap: clamp(28px, 5vw, 72px); align-items: start; max-width: 1100px; }
.contact__aside { display: flex; flex-direction: column; gap: 32px;
                  border-left: 1px solid var(--line-light); padding-left: clamp(20px, 3vw, 40px); }
.bg-ink .contact__aside { border-left-color: var(--line-dark); }
.contact__aside ul { list-style: none; padding-left: 0; }
.contact__aside li a { border-bottom: 1px solid transparent; }
.contact__aside li a:hover { border-bottom-color: var(--gold); }
@media (max-width: 860px) {
  .contact__grid { grid-template-columns: 1fr; }
  .contact__aside { border-left: 0; padding-left: 0; padding-top: 28px;
                    border-top: 1px solid var(--line-light); margin-top: 8px; }
}

/* PUR-004 — the objections that were driving people to email instead of buy,
   answered where the decision is made. Everything in these blocks is already
   published on the policy pages; this only moves it to the point of sale. */
.faq-block { margin-top: 40px; padding-top: 28px; border-top: 1px solid var(--line-light); }
.faq-block .faq details { border-bottom: 1px solid var(--line-light); }
.faq-block .faq summary { cursor: pointer; padding: 14px 0; font-size: 0.92rem;
  list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 14px; min-height: 44px; }
.faq-block .faq summary::-webkit-details-marker { display: none; }
.faq-block .faq summary::after { content: '+'; font-size: 1.1rem; color: var(--gold-ink, var(--gold)); flex: 0 0 auto; }
.faq-block .faq details[open] summary::after { content: '\2212'; }
.faq-block .faq p { font-size: 0.88rem; line-height: 1.9; opacity: 0.8; padding: 0 0 18px; margin: 0; }
.faq-block .faq p a { border-bottom: 1px solid var(--gold); white-space: nowrap; }
.bg-ink .faq-block, .bg-ink-soft .faq-block { border-top-color: var(--line-dark); }
.bg-ink .faq-block .faq details { border-bottom-color: var(--line-dark); }

/* ============================================================
   THE CONCIERGE — chat panel (js/concierge.js)
   Renders only when window.PS_CHAT_ENDPOINT is set.
   ============================================================ */
.concierge__launch {
  position: fixed; right: 20px; bottom: 20px; z-index: 1500;
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 48px; padding: 13px 22px;
  background: var(--ink); color: var(--gold-bright);
  border: 1px solid var(--gold); border-radius: 0;
  font-family: var(--font-body); font-size: 0.75rem;
  letter-spacing: 0.2em; text-transform: uppercase; cursor: pointer;
  box-shadow: 0 18px 40px rgba(0,0,0,0.35);
}
.concierge__launch:hover { background: var(--gold); color: var(--ink); }
.concierge__launch span { font-size: 0.6rem; }

/* `display: flex` beats the `hidden` attribute, so without this the panel is
   invisible AND still laid out — it sat over the launcher swallowing every
   click. Any component styled with display and toggled with `hidden` needs
   this line. */
.concierge[hidden] { display: none; }
.concierge {
  position: fixed; right: 20px; bottom: 20px; z-index: 1600;
  width: min(400px, calc(100vw - 40px)); max-height: min(620px, calc(100vh - 40px));
  display: flex; flex-direction: column;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--gold); box-shadow: 0 30px 70px rgba(0,0,0,0.45);
}
.concierge__head { display: flex; justify-content: space-between; align-items: flex-start;
  gap: 14px; padding: 18px 20px; border-bottom: 1px solid var(--line-light); }
.concierge__head .eyebrow { color: var(--gold-ink); margin: 0; }
.concierge__sub { font-size: 0.78rem; line-height: 1.7; opacity: 0.7; margin-top: 6px; }
.concierge__close { background: none; border: none; font-family: var(--font-body);
  font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase;
  border-bottom: 1px solid var(--ink); padding: 0 0 3px; cursor: pointer;
  min-height: 44px; flex: 0 0 auto; }

.concierge__log { flex: 1 1 auto; overflow-y: auto; padding: 18px 20px;
  display: flex; flex-direction: column; gap: 16px; }
.concierge__msg .who { display: block; font-size: 0.66rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold-ink); margin-bottom: 5px; }
.concierge__msg p { font-size: 0.9rem; line-height: 1.75; margin: 0; }
.concierge__msg--you { align-self: flex-end; max-width: 88%; text-align: right; }
.concierge__msg--you p { background: var(--ink); color: var(--paper); padding: 10px 14px; }
.concierge__msg--house { max-width: 94%; }
.concierge__msg.is-pending p { opacity: 0.5; font-style: italic; }

.concierge__form { display: flex; gap: 0; border-top: 1px solid var(--line-light); }
.concierge__form input { flex: 1 1 auto; min-width: 0; min-height: 52px;
  padding: 14px 18px; border: 0; background: transparent; color: inherit;
  font-family: var(--font-body); font-size: 0.9rem; outline: none; }
.concierge__form input:focus { background: rgba(168,137,74,0.07); }
.concierge__form button { flex: 0 0 auto; min-height: 52px; padding: 0 22px;
  background: var(--ink); color: var(--paper); border: 0;
  font-family: var(--font-body); font-size: 0.72rem; letter-spacing: 0.2em;
  text-transform: uppercase; cursor: pointer; }
.concierge__form button[disabled] { opacity: 0.5; cursor: progress; }

.concierge__foot { font-size: 0.72rem; line-height: 1.7; opacity: 0.65;
  padding: 12px 20px 16px; border-top: 1px solid var(--line-light); margin: 0; }
.concierge__foot a { border-bottom: 1px solid var(--gold); }

@media (max-width: 560px) {
  .concierge { right: 0; bottom: 0; left: 0; width: 100%;
               max-height: 88vh; border-left: 0; border-right: 0; border-bottom: 0; }
  .concierge__launch { right: 14px; bottom: 14px; }
}
@media (prefers-reduced-motion: reduce) { .concierge, .concierge__launch { transition: none; } }


/* ==========================================================================
   BUY BAR  —  CNV-015
   Lifted out of product.html's inline <style> so bag.html can use the same
   component. The £350 frame had a persistent purchase bar and the £1,450
   Coffret had one button at 46% page depth; the priority was inverted.
   ========================================================================== */
.buybar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 900;
  background: var(--ink); color: var(--paper);
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px var(--pad); gap: 16px; border-top: 1px solid var(--line-dark);
}
.buybar .total { font-family: var(--font-display); font-size: 1.6rem; }
.buybar .breakdown { font-size: 0.68rem; opacity: 0.72; letter-spacing: 0.04em; }

/* ==========================================================================
   THE TYPE FLOOR AND TAP TARGETS AT TOUCH WIDTHS  —  MOB-003 / MOB-004
   Deliberately scoped to <=860px and nowhere else. The desktop typography is
   a design decision and is left exactly as drawn; 11.52px on a phone asking
   £1,450 is an accessibility defect and is not. The floor is 0.9rem (14.4px):
   this buyer skews over forty and is, by definition, interested in eyesight. The attribute selectors are
   the only thing that beats an inline style, which is where most of the small
   type on this site is declared.
   ========================================================================== */
@media (max-width: 860px) {
  /* Prefix matches, not one rule per value. 0.5x, 0.6x, 0.7x and 0.8x all sit
     under the floor; 0.9rem is the floor itself and is left alone. Both the
     spaced and unspaced forms, because an inline style written by hand and one
     written by a script do not agree on whitespace. */
  [style*="font-size:0.5"], [style*="font-size: 0.5"],
  [style*="font-size:0.6"], [style*="font-size: 0.6"],
  [style*="font-size:0.7"], [style*="font-size: 0.7"],
  [style*="font-size:0.8"], [style*="font-size: 0.8"] { font-size: 0.9rem !important; }

  /* Sized by a rule on an ancestor or on a bare tag, so neither the attribute
     selectors nor the class list below reaches them. Walked out of the rendered
     DOM at 407px across seventeen pages, not guessed. */
  .nav__links a,
  .navdrawer__legal a,
  .footer__legallinks a,
  .footer__legal span,
  .footer__grid h3,
  .footer__news label,
  .footer__newsrow button,
  .journey__row .tag,
  .ritual__step p,
  .vidtoggle,
  .field label,
  .opt-group h3,
  .tint-controls label,
  .trust a, .trust b,
  .hud__edition small,
  .dims dt, .dims dd,
  .spec dl dt, .spec dl dd,
  .bswitch a, .bagpager a,
  .tryon__panel .pick h3 { font-size: 0.9rem !important; }

  /* Specification tables were the worst of it — 9.3px column headings on a size
     guide someone is reading to decide whether a £350 frame will fit. */
  table th, table td, table th small, dl dt, dl dd { font-size: 0.9rem !important; }

  /* Last sweep at the 14px floor: footer link columns and the consent line,
     the configurator option cards, the prescription table shell, the journey
     rows and the proof line. Verified clean at 407px afterwards. */
  .footer__grid a, .footer__consent, .footer__consent a,
  .opt-card strong, .opt-card .p, .opt-card .d,
  .rx table, .rx tbody, .rx tr,
  .journey__row p, .journey__row p a,
  .micro-proof, .micro-proof a,
  .buyband__line,
  /* the empty-slot numeral in the Coffret thumbnail rail, added with the
     six-frame standard — it was landing at 8.8px */
  .bgal__thumbs button, .bgal__thumbs .n { font-size: 0.9rem !important; }

  /* every class that measured under 13px at 407px, enumerated rather than
     guessed — the list came from walking the rendered DOM of eleven pages */
  .eyebrow, .breakdown, figcaption, .legend, .footnote,
  .btn, .consent, .count, .d, .dims, .drawer__close, .fbtn,
  .footer__legal, .footer__legallinks, .footer__mark, .hint, .hud__readout,
  .intro__tag, .lab, .link-quiet, .nav__cart, .navdrawer__close, .note,
  .panel-label, .pcard__flag, .pcard__which, .pick, .ribbon__item,
  .ribbon__pause, .rights, .sel, .skiplink, .stage-photo__caption,
  .stage__hint, .status, .sub, .tag, .updated,
  .trust small, .muted small, small, sup { font-size: 0.9rem !important; }
  .skiplink { min-height: 44px; display: inline-flex; align-items: center; }
  .swatch-btn, .cw, button.pick { min-width: 44px; min-height: 44px; }
  /* wide tracking at 8px is a texture; at 13px it is words. Ease it off so the
     bigger type still fits the line it was drawn for. */
  .eyebrow, [style*="letter-spacing:0.32em"], [style*="letter-spacing:0.28em"] {
    letter-spacing: 0.16em !important;
  }
}


/* the enlarged view shows it is working while a master is on its way */
.zoomer.is-loading .zoomer__frame::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 34px; height: 34px; margin: -17px 0 0 -17px;
  border: 2px solid rgba(200,168,106,0.25); border-top-color: var(--gold);
  border-radius: 50%; animation: zspin 0.7s linear infinite;
}
@keyframes zspin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .zoomer.is-loading .zoomer__frame::after { animation: none; } }


/* ==========================================================================
   THE STAGE CAPTION AND THE VIEW DOTS  —  they were colliding
   The dots sit 20-28px off the bottom and the caption 42-54px, which is not
   enough clearance once the dots carry a touch target. The fix is to keep the
   VISIBLE dot at 8px and hang the 44px hit area off a pseudo-element, so the
   thing you can hit is big and the thing you can see is not.
   ========================================================================== */
.stage-photo__dot {
  position: relative;
  width: 8px; height: 8px;
  flex: 0 0 auto;
}
.stage-photo__dot::after {
  content: ''; position: absolute;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px;          /* WCAG 2.5.5 target size */
}
.stage-photo__dots { bottom: 18px; gap: 16px; pointer-events: auto; }
.stage-photo__caption { bottom: 56px; }
@media (max-width: 860px) {
  .stage-photo__dots { bottom: 16px; gap: 18px; }
  .stage-photo__caption { bottom: 54px; }
}


/* CNV-010 — the quote strip. Hidden entirely until there is something in it. */
[data-proof][hidden] { display: none; }
.proof__row { display: grid; gap: 26px; margin-top: 18px;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.proof__item { margin: 0; }
.proof__item blockquote { margin: 6px 0 10px; font-family: var(--font-display);
  font-style: italic; font-size: 1.15rem; line-height: 1.45; }
.proof__item figcaption { font-size: 0.72rem; letter-spacing: 0.16em;
  text-transform: uppercase; opacity: 0.7; }
.proof__piece { display: block; opacity: 0.6; margin-top: 3px; }
.proof__rating { color: var(--gold); letter-spacing: 0.18em; font-size: 0.8rem; }


/* UX-101 — THE ERROR SUMMARY WAS BREAKING THE FIELD IT DESCRIBED.
   The summary is injected as a sibling inside the inline flex row, so on the
   homepage waiting-list form it took 129px of the row and squeezed the email
   input from 274px to 145px — the value the visitor was trying to correct
   became unreadable at exactly the moment they needed to read it.
   Forcing it onto its own line costs nothing and fixes every inline form. */
.form-summary {
  flex: 1 0 100%;
  width: 100%;
  order: -1;              /* above the row it belongs to, not beside it */
  margin: 0 0 10px;
}
.footer__newsrow, .form-row, form { flex-wrap: wrap; }
.footer__newsrow input[type="email"], .form-row input[type="email"] {
  min-width: 240px; flex: 1 1 240px;
}


/* ==========================================================================
   PUR-001 — THE PROOF BAND
   Three credibility signals on the commercial path. Every line is lifted from
   story.html; nothing here is a new claim.
   ========================================================================== */
.proof { padding: clamp(70px,9vw,120px) var(--pad); background: var(--ink); color: var(--paper); text-align: center; }
.proof__grid { display: grid; gap: 2.4rem; grid-template-columns: repeat(3,1fr); list-style: none; padding: 0;
  max-width: 1080px; margin: 42px auto 0; text-align: left; }
.proof__grid strong { display: block; font-family: var(--font-display); font-size: 1.25rem; font-weight: 500;
  letter-spacing: 0.02em; margin-bottom: 12px; color: var(--gold-bright); }
.proof__grid span { display: block; font-size: 0.95rem; line-height: 1.65; opacity: 0.78; }
@media (max-width: 780px) { .proof__grid { grid-template-columns: 1fr; gap: 1.6rem; text-align: center; } }

/* The one-line version, for the pages where someone is about to commit. */
.micro-proof { font-size: 0.82rem; line-height: 1.6; opacity: 0.68; margin-top: 14px; }
.micro-proof a { border-bottom: 1px solid var(--gold); }


/* A11Y-005 — the prescription region is a fieldset so the grouping is real,
   but a fieldset arrives with a border, padding and margin of its own. Reset
   to nothing so the panel looks exactly as it was drawn. */
.rx__set { border: 0; padding: 0; margin: 0; min-width: 0; }
.rx__set--pd { margin-top: 14px; }
.rx__set > legend { padding: 0; }
.rx__set--pd > legend { margin-bottom: 10px; }


/* ==========================================================================
   ROUND 11 — the findings from the fresh audit that are CSS, not markup
   ========================================================================== */

/* UX-001. The header is sticky and 100px tall, so anything reached by anchor,
   by browser find, or by a restored scroll position landed underneath it. The
   atelier swatch row was the visible case. */
html { scroll-padding-top: calc(var(--nav-h) + 16px); }
section, header, h1, h2, h3, [id] { scroll-margin-top: calc(var(--nav-h) + 16px); }

/* A11Y-003. TikTok measured 38.8x44 in the footer columns and Privacy Notice
   43.8px tall in the consent line, which is an inline element inheriting a line
   box. Scoped to touch widths so the desktop footer rhythm is untouched. */
@media (max-width: 860px) {
  /* The column links carry an inline padding of 11px 0 from chrome.js, which
     an ordinary rule cannot beat. */
  footer a, .footer a, .footer__legallinks a, .footer__legal a {
    padding-left: 6px !important; padding-right: 6px !important;
  }
  .footer__consent a {
    display: inline-block; min-height: 44px; line-height: 44px;
    padding-left: 4px; padding-right: 4px;
  }
}

/* A11Y-001. The price line and the commission line are the two that carry the
   offer and the terms, and they were set over the radial artwork with nothing
   behind them. A soft scrim sits behind the copy column only; the artwork is
   untouched everywhere else. */
.campaign .inner.center { position: relative; }
.campaign .inner.center::before {
  content: ''; position: absolute; z-index: 0;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 128%; height: 118%;
  background: radial-gradient(58% 50% at 50% 50%,
    rgba(10,10,10,0.62) 0%, rgba(10,10,10,0.42) 55%, rgba(10,10,10,0) 100%);
  pointer-events: none;
}
.campaign .inner.center > * { position: relative; z-index: 1; }
.hero__qualify { font-size: 0.82rem; font-weight: 500; opacity: 0.95 !important; }
.hero__commission { opacity: 0.78 !important; }

/* UX-002. Eight tint swatches laid out seven and one. Four by two is a grid;
   seven and one reads as a bug on the section that carries the whole idea. */
#tintRow { display: grid !important; grid-template-columns: repeat(4, max-content); gap: 14px; }
@media (max-width: 520px) { #tintRow { grid-template-columns: repeat(4, 1fr); } }


/* FUN-005 — the drawn view on the product stage. It is a div, not an img, so it
   needs the layout the photographs get from object-fit. */
/* Beats `.stage-photo .stage-photo__img { padding: 40px 40px 86px }`, which is
   sized for a photograph filling the frame, not for a centred drawing. */
.stage-photo .stage-photo__img.stage-photo__live {
  display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 26px;
  padding: 40px 40px 86px; box-sizing: border-box;
}
.stage-photo__live svg { width: 86%; max-width: 620px; height: auto; max-height: 58%;
  filter: drop-shadow(0 24px 48px rgba(0,0,0,0.28)); }
/* It is a technical drawing and it should read as one, rather than as a
   photograph that came out badly. */
.stage-photo__live::after {
  content: 'Drawn to the technical spec \2014 1 unit = 0.1 mm';
  font-size: 0.62rem; letter-spacing: 0.24em; text-transform: uppercase;
  opacity: 0.62; color: var(--ink);
}


/* CNV-004 — the mid-scroll purchase bands. Deliberately plain: one line, two
   buttons, no photography. They exist to be a route out, not a section. */
.buyband { background: var(--ink); color: var(--paper); text-align: center;
  padding: clamp(46px,5vw,72px) var(--pad); }
.buyband__line { font-size: 0.82rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold-bright); margin: 0 0 26px; line-height: 2; }
.buyband__cta { display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; }
@media (max-width: 620px) { .buyband__cta { flex-direction: column; align-items: center; }
  .buyband__cta .btn { width: 100%; max-width: 320px; justify-content: center; } }


/* ADD-TABLE-SCROLL — 28 Aug 2026. The size guide's measurement table is 542px
   of content. On a 390px phone it pushed the whole document sideways, so every
   section on the page could be dragged off-centre. The table now scrolls
   inside its own box and the page does not move. */
@media (max-width: 620px) {
  .legal table { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .legal table thead, .legal table tbody { display: table; width: max-content; min-width: 100%; }
}

/* 29 Aug 2026. `* { margin: 0 }` plus a section written as bare h3/p meant the
   certificate explainer on verify.html rendered as one unbroken wall of text.
   Scoped, so no other page's rhythm moves. */
.prose > h3 { margin: 30px 0 8px; }
.prose > h3:first-child { margin-top: 0; }
.prose > p  { margin: 0 0 4px; line-height: 1.95; }

/* ==========================================================================
   PDP STAGE — the hint, the caption and the dots were stacked on top of each
   other on a phone. The accessibility pass had forced .stage__hint up to
   0.9rem !important, which took it to two lines; at bottom:24px that put it
   straight through the view dots and the caption. Raise it clear rather than
   shrink it back under 13px.
   ========================================================================== */
@media (max-width: 620px) {
  .pdp__stage .stage__hint { bottom: 82px; }
}

/* ==========================================================================
   PDP STAGE ON A PHONE — undoing three things the 13px accessibility sweep
   did to the hero. That sweep enumerated every class measuring under 13px and
   pushed them all to 0.9rem !important. Correct for body copy; wrong for the
   three decorative overlays that sit ON the product photograph:

   - .stage-photo__dot picked up min-width/min-height:44px, so the view dots
     rendered as seven 57px discs across the bottom of the hero instead of the
     8px marks the design draws. The 44px target already exists as an invisible
     ::after; the minimum belongs there, not on the visible dot.
   - .hud__edition went to 15.2px and grew into a 150x142 slab sitting over the
     right lens.
   - .stage__hint went to 14.4px and wrapped to two full-width lines over the
     frame.

   None of the three is body copy, and every word in them is repeated in the
   text below the fold, so size is a design decision here rather than a
   legibility one.
   ========================================================================== */
@media (max-width: 620px) {
  .stage-photo__dots .stage-photo__dot {
    min-width: 0 !important; min-height: 0 !important;
    width: 8px !important; height: 8px !important; padding: 0 !important;
    font-size: 0 !important; flex: 0 0 8px !important;
  }
  .pdp__stage .hud__edition { font-size: 0.95rem !important; max-width: 150px;
    padding: 7px 10px; line-height: 1.25; }
  .pdp__stage .hud__edition small { font-size: 0.5rem !important;
    letter-spacing: 0.14em; line-height: 1.5; }
  .pdp__stage .stage__hint { font-size: 0.62rem !important; letter-spacing: 0.18em; }
  .pdp__stage .stage-photo__caption { font-size: 0.62rem !important; }
}

/* ==========================================================================
   THE TWO WORN VIEWS — her, then him. The photographs do not exist yet, so
   the slots say so rather than being silently absent from an order Paul set.
   Set `src` on CATALOG.wornShots and both of these stop rendering.
   ========================================================================== */
.stage-photo__pending {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; background: #f1f1f1; color: rgba(18,17,14,0.5); text-align: center;
}
.stage-photo__pending span {
  font-size: 0.62rem; letter-spacing: 0.3em; text-transform: uppercase; font-weight: 500;
}
.stage-photo__pending small { font-size: 0.6rem; letter-spacing: 0.14em; opacity: 0.75; }
.gthumb__pending {
  display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;
  background: #f1f1f1; border: 1px dashed rgba(0,0,0,0.22);
  font-size: 0.46rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(18,17,14,0.45); text-align: center; padding: 2px;
}

/* ===== 1 Oct 2026 — contrast pass, WCAG 2.2 AA (4.5:1 for text) =========
   Measured with axe on every page: 188 text nodes failed, almost all of them
   small gold or faded-grey text on the cream ground, plus the footer legal
   line. Gold TEXT on cream now uses the deep gold (--gold-ink, 5.0:1) at full
   strength; dark grounds keep the bright gold. Faded text fades a little less. */
.legal .eyebrow, .legal .text-gold, .legal th,
body.bg-paper .eyebrow:not(.bg-ink *):not(.campaign *):not(.tier--now *),
body.bg-paper .text-gold:not(.bg-ink *):not(.campaign *):not(.tier--now *),
.rxguide th, .rxguide .eyebrow, #rxGate, #rxGate strong,
#pGalNote b, #bagNote b, body.bg-paper a > b:not(.bg-ink *),
.nexttile__when, .nexttile__amp, #pDims > span:first-child
  { color: var(--gold-ink) !important; opacity: 1 !important; }
body .buybar .btn--gold, body .bg-ink .btn--gold, body .campaign .btn--gold,
body .tier--now .eyebrow { color: var(--gold-bright) !important; }
.footer__legal { opacity: 0.66 !important; }
#pDims > span:not(:first-child) { color: var(--ink) !important; opacity: 0.75 !important; }
#pGalNote, #bagNote { opacity: 1 !important; color: #5f5c56 !important; }
.legal .updated, .sub, .hint, .pcard__meta span, .rxguide p, [data-parallax] > .center,
p[style*="opacity:0.5"], span[style*="opacity:0.5"], div[style*="opacity:0.5"],
p[style*="opacity: 0.5"], span[style*="opacity: 0.5"], div[style*="opacity: 0.5"]
  { opacity: 0.8 !important; }
/* contrast pass, second sweep: elements whose parents were faded */
body .bg-ink .eyebrow.text-gold { color: var(--gold-bright) !important; }
.nexttile__names { opacity: 1 !important; }
#pDims, #pDims * { opacity: 1 !important; }
#pDims > span:not(:first-child) { color: var(--ink) !important; }
.trust a, .trust b { opacity: 1 !important; }
.trust a { color: #55524c !important; }
.trust b { color: var(--gold-ink) !important; }
