/* ==========================================================================
   Studi002 — Lash Atelier
   --------------------------------------------------------------------------
   One stylesheet, ordered from tokens outward. Section markers are the
   ONLY headings; search for "== " to jump.

   The motion constants and radii are measured off drinkcana.com, which is
   the agreed reference: panels slide 300ms on cubic-bezier(.7,.01,.11,.96),
   the nav indicator moves 150ms on cubic-bezier(.4,0,.2,1), the backdrop
   blurs 22px over 500ms. Those three numbers are the whole feel of the site;
   changing them changes everything.
   ========================================================================== */


/* == Fonts ================================================================ */

/* Both reference faces (ABC Monument Grotesk, GT Super) are commercially
   licensed and cannot ship. Archivo stands in for the grotesk.

   For the serif the obvious substitute is Instrument Serif, and it is the
   wrong one — it is *the* free GT Super stand-in, which is exactly why it now
   turns up on every second template and reads as nobody's choice in
   particular. Bodoni Moda is the better fit on its own merits: a Didone, the
   genre fashion and beauty editorial has used for two centuries, whose
   high-contrast tapered strokes answer the flourishes in the gold monogram
   far more closely than Instrument Serif's flatter forms.

   It is variable on an optical-size axis (6–96), which matters for a Didone —
   opsz thickens the hairlines as the size drops, so .t-lede at ~18px stays
   solid instead of shattering. Both faces are SIL OFL and self-hosted. */

@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Bodoni Moda';
  src: url('../fonts/bodoni-moda.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Bodoni Moda';
  src: url('../fonts/bodoni-moda-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}


/* == Tokens =============================================================== */

:root {
  /* Ground. Warm greys rather than the reference's cool ones — gold turns
     muddy against blue-grey and clean against warm. */
  --ground:      #E9E6E0;
  --panel:       #FAF9F6;
  --chip:        #EFEDE6;
  --ink:         #141311;
  --ink-2:       #6E6A62;
  --ink-3:       #9A958B;
  --line:        rgba(20, 19, 17, 0.12);
  --line-strong: rgba(20, 19, 17, 0.22);
  --black:       #0C0B0A;

  /* Gold, sampled pixel-by-pixel from the monogram artwork. --gold-deep is
     the only one with enough contrast for text on a light ground. */
  --gold-deep: #B56F26;
  --gold:      #D29545;
  --gold-lit:  #EDBB64;
  --gold-pale: #F2C882;
  --gold-grad: linear-gradient(135deg, #F2C882 0%, #EDBB64 32%, #C8883A 68%, #B56F26 100%);

  /* Type */
  --sans:  'Archivo', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  --serif: 'Bodoni Moda', 'Didot', 'Times New Roman', Times, serif;

  /* Motion — see the note at the top of this file */
  --ease-panel: cubic-bezier(0.7, 0.01, 0.11, 0.96);
  --ease-ui:    cubic-bezier(0.4, 0, 0.2, 1);
  --t-panel:    300ms;
  --t-ui:       150ms;
  --t-backdrop: 500ms;

  /* Shape */
  --r-panel: 20px;
  --r-card:  12px;
  --r-pill:  9999px;

  /* Frame — the gutter panels are inset by, matching the reference's 44/24 */
  --gutter:   16px;
  --gutter-y: 12px;

  /* Layer order, declared once so nothing has to guess */
  --z-hero-ui:  10;
  --z-backdrop: 30;
  --z-panel:    40;
  --z-nav:      60;
  --z-drawer:   80;
}

@media (min-width: 768px) {
  :root {
    --gutter:   44px;
    --gutter-y: 24px;
  }
}


/* == Base ================================================================= */

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Locked while a panel or the cart is open, so the page behind cannot scroll
   out from under the overlay. */
body.is-locked { overflow: hidden; }

img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

/* The `hidden` attribute is a user-agent rule, so any class that sets display
   beats it — .detail is display:grid and would show through its own hidden
   attribute. This is the standard normalize fix and the panels depend on it. */
[hidden] { display: none !important; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 3px;
  border-radius: 4px;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Keyboard users get a way past the fixed nav into the page. */
.skip-link {
  position: absolute;
  top: -100px;
  left: var(--gutter);
  z-index: 999;
  background: var(--ink);
  color: #fff;
  padding: 10px 18px;
  border-radius: var(--r-pill);
  font-size: 13px;
  transition: top var(--t-ui) var(--ease-ui);
}
.skip-link:focus { top: var(--gutter-y); }


/* == Typography =========================================================== */

/* Tracking sits at or just above zero throughout. A Didone's thin strokes and
   small counters need air — the negative tracking that suits a low-contrast
   editorial serif closes Bodoni up and turns it muddy. Line heights are a
   touch looser than they would be otherwise, for the taller ascenders. */

.t-display {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.4rem, 6.2vw, 5.2rem);
  line-height: 1.02;
  letter-spacing: -0.005em;
  margin: 0;
}

.t-title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.6rem, 3.2vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: 0;
  margin: 0;
}

/* The reference sets its long-form copy in a serif and its interface in a
   grotesk. That split is most of why it reads as considered. */
.t-lede {
  font-family: var(--serif);
  font-size: clamp(1.15rem, 1.9vw, 1.6rem);
  line-height: 1.42;
  letter-spacing: 0.005em;
  margin: 0;
}

.t-body { font-size: 14px; line-height: 1.6; margin: 0; }

.t-eyebrow {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0;
}

.t-muted { color: var(--ink-2); }

/* The monogram at an explicit width.
   height:auto is not optional: studi002_img() writes real width and height
   attributes so the browser can reserve space, and those attributes act as
   presentational hints — constrain only the width and the S stretches into a
   ribbon. Anywhere the monogram is sized, it is sized through this class. */
.mark { width: var(--mark-w, 54px); height: auto; }


/* == Buttons ============================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 46px;
  padding: 0 24px;
  border-radius: var(--r-pill);
  font-size: 13px;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: background var(--t-ui) var(--ease-ui),
              color var(--t-ui) var(--ease-ui),
              opacity var(--t-ui) var(--ease-ui);
}

.btn--ink   { background: var(--ink); color: #fff; }
.btn--ink:hover   { background: #2C2A26; }

.btn--gold  { background: var(--gold-grad); color: var(--black); font-weight: 500; }
.btn--gold:hover  { opacity: 0.88; }

.btn--full  { width: 100%; }
.btn[disabled] { opacity: 0.45; pointer-events: none; }

/* Small pill, used for Close and for meta chips */
.chip {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  background: var(--chip);
  font-size: 11px;
  letter-spacing: 0.02em;
  transition: filter var(--t-ui) var(--ease-ui);
}
.chip:hover { filter: brightness(0.93); }


/* == Nav ================================================================== */

.nav {
  position: fixed;
  inset: var(--gutter-y) var(--gutter) auto;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  pointer-events: none;
}
.nav > * { pointer-events: auto; }

/* The pill. Translucent white over blur, so the hero video reads through it. */
.nav__pill {
  position: relative;
  display: flex;
  align-items: center;
  padding: 3px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  color: #2B2B2B;
}

/* Centred by flex, not by line-height. The reference sets line-height:0.85
   here, which sits the label high in the pill — fine for its own font's
   metrics, visibly leaning upward in Archivo. The cart button was always
   inline-flex, which is why it looked right when these did not. */
.nav__btn {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 33px;
  padding: 0 16px;
  border-radius: var(--r-pill);
  font-size: 14px;
  line-height: 1;
  white-space: nowrap;
  transition: color var(--t-ui) var(--ease-ui);
}
.nav__btn[aria-current='true'] { color: var(--ink); }

/* Single white lozenge that slides between items. JS sets left/width from the
   active button's box; CSS owns the movement. */
.nav__indicator {
  position: absolute;
  top: 50%;
  left: 0;
  z-index: 0;
  height: 35px;
  width: 0;
  margin-top: -17.5px;
  border-radius: var(--r-pill);
  background: #fff;
  opacity: 0;
  pointer-events: none;
  transition: left var(--t-ui) var(--ease-ui),
              width var(--t-ui) var(--ease-ui),
              opacity var(--t-ui) var(--ease-ui);
}

/* Centred wordmark */
.nav__mark {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}
.nav__mark img { width: 34px; height: auto; }
.nav__mark span {
  font-size: 11px;
  letter-spacing: 0.34em;
  /* Matching indent, so the trailing letter-space does not shove the
     wordmark off its own centre. */
  text-indent: 0.34em;
  color: var(--ink);
}

.nav__util { display: flex; align-items: center; gap: 4px; }

.nav__cart {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 33px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  font-size: 14px;
  transition: background var(--t-ui) var(--ease-ui);
}
.nav__cart:hover { background: #fff; }

/* Gold dot that fills in once the cart has something in it. */
.nav__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line-strong);
  transition: background var(--t-ui) var(--ease-ui),
              transform var(--t-ui) var(--ease-ui);
}
.nav__cart[data-count]:not([data-count='0']) .nav__dot {
  background: var(--gold);
  transform: scale(1.15);
}

/* Mobile keeps the monogram but drops the STUDI002 wordmark beside it. The
   bar has to hold the three-item pill and the cart button as well, and at
   375px there is not room for all three plus a tracked-out wordmark without
   them touching. The mark alone is the logo; the word is the part that can go.
   The pill tightens slightly to buy the gaps. */
@media (max-width: 767px) {
  /* The mark joins the flex row instead of being centred on top of it.
     Absolute centring is right on desktop, where the flanking widths are
     unequal and the mark should still sit on the page's centre line — but at
     375px the pill and the cart leave no middle to sit in, and an absolutely
     positioned mark simply lands on top of "Book". In flow, space-between
     gives all three room and nothing can overlap. */
  .nav__mark { position: static; transform: none; }
  .nav__mark img { width: 30px; }
  .nav__mark span:not(.sr-only) { display: none; }

  .nav__btn { padding: 0 11px; font-size: 13px; }
  .nav__cart { padding: 0 11px; }
}


/* == Hero ================================================================= */

.hero {
  position: relative;
  height: 100svh;
  min-height: 520px;
  overflow: hidden;
  background: #DEDBD5;
}

.hero__media,
.hero__media video,
.hero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A light wash across the top only. There is no hero copy to protect any
   more — this is purely so the nav pill, the cart and the gold monogram keep
   an edge against whatever the footage is doing behind them. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
              rgba(255,255,255,0.30) 0%,
              rgba(255,255,255,0.05) 22%,
              rgba(255,255,255,0) 40%);
  pointer-events: none;
}

/* Scroll cue, bottom centre */
.hero__cue {
  position: absolute;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  z-index: var(--z-hero-ui);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.55;
}
.hero__cue i {
  display: block;
  width: 1px;
  height: 26px;
  background: currentColor;
  animation: cue 2.4s var(--ease-ui) infinite;
  transform-origin: top;
}
@keyframes cue {
  0%, 100% { transform: scaleY(0.25); opacity: 0.3; }
  50%      { transform: scaleY(1);    opacity: 1; }
}


/* == Home sections ======================================================== */

.section { padding: clamp(44px, 6vw, 84px) var(--gutter); }
.section--flush { padding-left: 0; padding-right: 0; }

.wrap { max-width: 1360px; margin: 0 auto; }

.split {
  display: grid;
  gap: 14px;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1.35fr 1fr; }
}

/* The big rounded slabs the reference builds its homepage out of. */
.slab {
  position: relative;
  border-radius: var(--r-panel);
  overflow: hidden;
  min-height: 380px;
  display: flex;
  align-items: flex-end;
  padding: 26px;
  color: #fff;
}
.slab img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.slab::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(0deg, rgba(12,11,10,0.62) 0%, rgba(12,11,10,0.12) 46%, rgba(12,11,10,0) 72%);
}
.slab > * { position: relative; z-index: 2; }
.slab--tall { min-height: 520px; }

.slab--dark {
  background: var(--black);
  color: #fff;
  align-items: center;
  justify-content: center;
  text-align: center;
  flex-direction: column;
  gap: 18px;
  padding: 44px 32px;
}
.slab--dark::after { display: none; }
.slab--dark img {
  position: static;
  width: 92px;
  height: auto;
  object-fit: contain;
}

/* Editorial statement block — serif, generous, centred. */
.statement {
  max-width: 780px;
  margin: 0 auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 22px;
  align-items: center;
}

/* Photo rail. Scrolls by touch/trackpad; no autoplay, no cloning. */
.rail {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 0 var(--gutter);
  /* Without this, mandatory snapping aligns the first card to the scrollport
     edge and swallows the left gutter — the rail loads already nudged across,
     with card one flush against the window. scroll-padding moves the snap edge
     in by the same gutter, so the resting position is scrollLeft 0. */
  scroll-padding-left: var(--gutter);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.rail::-webkit-scrollbar { display: none; }

.rail__item {
  flex: 0 0 auto;
  width: min(70vw, 300px);
  scroll-snap-align: start;
}
.rail__item img {
  width: 100%;
  /* height:auto for the same reason as .mark — the height attribute is a
     presentational hint and would otherwise win over aspect-ratio, making
     every rail photo 1350px tall. */
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--r-card);
}
/* Service / value list.
   Every cell is placed explicitly. The row has three children and only two
   columns on mobile, so leaving it to auto-flow put the description in row 2
   of the 28px number column — 28px wide, 515px tall, one character per line.
   Auto-placement is not worth the ambiguity here. */
.list { border-top: 1px solid var(--line); }

.list__row {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 6px 18px;
  align-items: baseline;
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
}
.list__num {
  grid-column: 1;
  grid-row: 1;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--gold-deep);
}
.list__row h3 { grid-column: 2; grid-row: 1; }
/* Under the title on mobile, indented to it rather than to the number. */
.list__row p  { grid-column: 2; grid-row: 2; }

@media (min-width: 760px) {
  .list__row { grid-template-columns: 28px 260px 1fr; gap: 18px; }
  /* Wide enough for all three to share one line. */
  .list__row p { grid-column: 3; grid-row: 1; }
}


/* == Panels =============================================================== */

/* Two cooperating fixed layers, exactly as the reference does it:
   .backdrop blurs and dims what is behind; .panel holds the content and
   slides in from the right. Both are driven by data-visible on .panel,
   which app.js toggles. */

/* visibility, not just opacity. A full-viewport backdrop-filter is expensive
   even at opacity 0 — the compositor still allocates and blurs the layer on
   every frame, for a page that is idle. visibility:hidden takes it out of
   rendering entirely, and delaying that switch by the length of the fade means
   the blur is still there to fade out with. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-backdrop);
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
  background: rgba(233, 230, 224, 0.28);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--t-backdrop) var(--ease-ui),
              visibility 0s var(--t-backdrop);
}
.backdrop[data-visible='true'] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity var(--t-backdrop) var(--ease-ui),
              visibility 0s;
}

.panel {
  position: fixed;
  inset: 0;
  z-index: var(--z-panel);
  /* Clears the fixed nav (which is --gutter-y from the top and 39px tall)
     with room to spare, so panel headings never crowd the pill. */
  padding: calc(var(--gutter-y) + 64px) var(--gutter) var(--gutter-y);
  overflow-y: auto;
  overscroll-behavior: contain;
  pointer-events: none;
}
.panel[data-visible='true'] { pointer-events: auto; }

/* The moving part. Opacity flips instantly on the way in and is delayed to
   the end of the slide on the way out — that is the reference's
   `opacity 0s 300ms` trick, and it stops the panel ghosting mid-flight. */
.panel__inner {
  opacity: 0;
  transform: translateX(56px);
  transition: transform var(--t-panel) var(--ease-panel),
              opacity 0s var(--t-panel);
}
.panel[data-visible='true'] .panel__inner {
  opacity: 1;
  transform: translateX(0);
  transition: transform var(--t-panel) var(--ease-panel),
              opacity 0s;
}

.card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}


/* == Shop ================================================================= */

.shop {
  max-width: 1360px;
  margin: 0 auto;
}

.shop__grid {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}

.product {
  background: var(--panel);
  border-radius: var(--r-panel);
  overflow: hidden;
  text-align: left;
  width: 100%;
  display: flex;
  flex-direction: column;
  transition: transform var(--t-ui) var(--ease-ui);
}
.product:hover { transform: translateY(-3px); }

.product__media {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--chip);
  overflow: hidden;
}
.product__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 500ms var(--ease-ui);
}
.product:hover .product__media img { transform: scale(1.03); }

.product__badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background: var(--gold-grad);
  color: var(--black);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--r-pill);
}

.product__body {
  padding: 14px 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.product__name { font-size: 14px; }
.product__price { font-size: 13px; color: var(--ink-2); }
.product__price del { opacity: 0.5; margin-right: 6px; }
.product__price ins { text-decoration: none; color: var(--gold-deep); }

.shop__empty {
  background: var(--panel);
  border-radius: var(--r-panel);
  padding: 56px 28px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}


/* == Product detail ======================================================= */

/* Image left, buy column right — the reference's product layout. */
.detail {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr;
  max-width: 1360px;
  margin: 0 auto;
  align-items: start;
}
@media (min-width: 900px) {
  .detail { grid-template-columns: 1fr 400px; }
}

.detail__media {
  border-radius: var(--r-panel);
  overflow: hidden;
  background: var(--black);
  aspect-ratio: 4 / 5;
}
@media (min-width: 900px) {
  .detail__media { aspect-ratio: auto; height: min(78vh, 640px); }
}
.detail__media img { width: 100%; height: 100%; object-fit: cover; }

.detail__buy {
  background: var(--panel);
  border-radius: var(--r-panel);
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
@media (min-width: 900px) {
  .detail__buy { max-height: min(78vh, 640px); overflow-y: auto; }
}

.detail__desc { font-size: 13px; line-height: 1.65; color: var(--ink-2); }
.detail__desc p { margin: 0 0 10px; }
.detail__desc :last-child { margin-bottom: 0; }

.detail__foot { margin-top: auto; display: flex; flex-direction: column; gap: 10px; }

.qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 10px 14px;
  font-size: 13px;
}
.qty__ctrl { display: flex; align-items: center; gap: 4px; }
.qty__btn {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--chip);
  display: grid;
  place-items: center;
  font-size: 15px;
  line-height: 1;
  transition: filter var(--t-ui) var(--ease-ui);
}
.qty__btn:hover { filter: brightness(0.92); }
.qty__val { min-width: 26px; text-align: center; }

.detail__note { font-size: 11px; color: var(--ink-3); text-align: center; }

/* Variable products and anything else WooCommerce needs a real form for get
   the plugin's own markup, restyled just enough to sit in the card. */
.detail__wc .variations { width: 100%; margin-bottom: 12px; }
.detail__wc .variations td,
.detail__wc .variations th { padding: 5px 0; font-size: 12px; text-align: left; }
.detail__wc select {
  width: 100%;
  height: 40px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: #fff;
  font: inherit;
  font-size: 13px;
}
.detail__wc .quantity input[type='number'] {
  width: 72px;
  height: 46px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: #fff;
  font: inherit;
}
.detail__wc .single_add_to_cart_button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 46px;
  margin-top: 10px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: #fff;
  font-size: 13px;
  cursor: pointer;
}


/* == Cart drawer ========================================================== */

.drawer {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  pointer-events: none;
}
.drawer[data-visible='true'] { pointer-events: auto; }

.drawer__scrim {
  position: absolute;
  inset: 0;
  background: rgba(12, 11, 10, 0.28);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity var(--t-backdrop) var(--ease-ui);
}
.drawer[data-visible='true'] .drawer__scrim { opacity: 1; }

.drawer__panel {
  position: absolute;
  top: calc(var(--gutter-y) + 52px);
  right: var(--gutter);
  bottom: var(--gutter-y);
  width: min(400px, calc(100% - var(--gutter) * 2));
  background: var(--panel);
  border-radius: var(--r-panel);
  display: flex;
  flex-direction: column;
  opacity: 0;
  transform: translateX(calc(100% + var(--gutter)));
  transition: transform var(--t-panel) var(--ease-panel),
              opacity 0s var(--t-panel);
}
.drawer[data-visible='true'] .drawer__panel {
  opacity: 1;
  transform: translateX(0);
  transition: transform var(--t-panel) var(--ease-panel),
              opacity 0s;
}

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line);
}
/* Wraps the lines and the totals together, because the cart endpoints replace
   both in one go. min-height:0 is what lets the lines scroll instead of
   pushing the totals off the bottom. */
.drawer__region { flex: 1; display: flex; flex-direction: column; min-height: 0; }

.drawer__body { flex: 1; overflow-y: auto; padding: 6px 18px; }
.drawer__foot { padding: 16px 18px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 10px; }

.drawer__empty { padding: 48px 8px; text-align: center; color: var(--ink-2); font-size: 13px; }

.line {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.line:last-child { border-bottom: 0; }
.line img { width: 56px; height: 70px; object-fit: cover; border-radius: 8px; }
.line__name { font-size: 13px; }
.line__meta { font-size: 12px; color: var(--ink-2); }
.line__remove { font-size: 11px; color: var(--ink-3); text-decoration: underline; }
.line__remove:hover { color: var(--ink); }

.totals { display: flex; justify-content: space-between; font-size: 14px; }


/* == Book ================================================================= */

.book { max-width: 1100px; margin: 0 auto; }

.book__card {
  background: var(--panel);
  border-radius: var(--r-panel);
  padding: 22px;
}

/* Amelia ships its own design. Rather than fight it, the theme only pins the
   pieces that would otherwise clash with the page: the accent colour and the
   button shape. Anything not listed here stays as the plugin drew it. */
.book__card .amelia-app-booking,
.book__card .amelia-v2-booking {
  font-family: var(--sans) !important;
  --am-c-primary: var(--gold-deep);
}
.book__card .am-button--primary,
.book__card .amelia-app-booking button.am-button-primary {
  border-radius: var(--r-pill) !important;
}

.book__fallback {
  padding: 48px 24px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}


/* == Footer =============================================================== */

.footer {
  background: var(--black);
  color: #fff;
  padding: clamp(48px, 7vw, 90px) var(--gutter) 26px;
}
.footer__grid {
  max-width: 1360px;
  margin: 0 auto;
  display: grid;
  gap: 36px;
  grid-template-columns: 1fr;
}
@media (min-width: 800px) {
  .footer__grid { grid-template-columns: 1.4fr 1fr 1fr; }
}

.footer__mark { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }
.footer__mark img { width: 62px; height: auto; }

.footer h3 {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.5);
  margin: 0 0 14px;
  font-weight: 400;
}
.footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.footer a { font-size: 14px; color: rgba(255,255,255,0.85); transition: color var(--t-ui) var(--ease-ui); }
.footer a:hover { color: var(--gold-lit); }

.footer__base {
  max-width: 1360px;
  margin: 44px auto 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255,255,255,0.14);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  justify-content: space-between;
  font-size: 11px;
  color: rgba(255,255,255,0.45);
}


/* == Scroll reveal ======================================================== */

/* IntersectionObserver adds .is-in. The 75ms stagger is the reference's. */
.reveal {
  opacity: 0.01;
  transform: translateY(2rem);
}
.reveal.is-in {
  animation: reveal 700ms var(--ease-panel) forwards;
  animation-delay: calc(var(--order, 0) * 75ms);
}
@keyframes reveal {
  to { opacity: 1; transform: translateY(0); }
}


/* == Plain pages ========================================================== */

/* Cart, checkout, account, single product, blog — anything that is a real
   WordPress page rather than a panel. Same shell, no overlay. */
.page {
  padding: calc(var(--gutter-y) + 90px) var(--gutter) clamp(60px, 8vw, 110px);
  min-height: 70vh;
}
.page__wrap { max-width: 1000px; margin: 0 auto; }
.page__head { margin-bottom: 32px; }

.page__body :where(h1,h2,h3) { font-family: var(--serif); font-weight: 400; }
.page__body a { text-decoration: underline; text-underline-offset: 3px; }
.page__body img { border-radius: var(--r-card); }


/* == Reduced motion ======================================================= */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* Panels still need to move between two states — they just arrive at once
     instead of sliding, and nothing loops. */
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .panel__inner,
  .drawer__panel { transform: none; }
  .reveal { opacity: 1; transform: none; }
  .hero__cue i { animation: none; transform: scaleY(1); }
}
