/* ═══════════════════════════════════════════════════════════════════════════
   motion.css — apple-design behavioural layer
   ═══════════════════════════════════════════════════════════════════════════
   Loaded LAST, after styles.css and desktop.css, so it wins by source order
   with no !important and no specificity games.

   Foundational tokens live in styles.css :root. This file is behaviour:
   press feedback, focus, materials, and the accessibility media queries the
   skill requires. § references point at the skill section.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── §1 Response — feedback on pointer-DOWN, not release ──────────────────
   "The moment lag appears, the feeling of directness falls off a cliff."
   Every pressable surface gets an instant press state. --dur-press is the
   shortest duration on the site precisely so this reads as immediate. */
.pill,
.cta,
.chip,
.year-step,
.qty__btn,
.shop-card__add,
.shop-card,
.bottle-card,
.tab,
.shop-tab,
.faq summary,
.menu-btn,
.cart-btn,
.pd-fav,
.topnav a,
a.brand {
  /* §2 — removes the legacy ~300ms tap delay on touch. Anything on the input
     path that is not essential is a regression. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.pill:active,
.cta:active,
.chip:active,
.year-step:active,
.qty__btn:active,
.shop-card__add:active,
.menu-btn:active,
.cart-btn:active,
.pd-fav:active,
a.brand:active {
  transform: scale(0.97);
  transition: transform var(--dur-press) var(--ease-out-soft);
}

/* Cards are large surfaces — the same 0.97 on a 380px card reads as a lurch,
   so they compress less. §7 Craft: every value is a deliberate choice. */
.shop-card:active,
.bottle-card:active {
  transform: scale(0.988);
  transition: transform var(--dur-press) var(--ease-out-soft);
}

/* Releasing returns on the softer outbound curve, mirroring the press (§19). */
.pill,
.cta,
.chip,
.shop-card,
.bottle-card,
.shop-card__add,
.qty__btn {
  transition: transform var(--dur-quick) var(--ease-standard),
    box-shadow var(--dur-quick) var(--ease-standard),
    background-color var(--dur-quick) var(--ease-standard),
    color var(--dur-quick) var(--ease-standard);
}

/* ── §1/§16 Focus — visible, and never removed ────────────────────────── */
:focus-visible {
  outline: 2px solid var(--wine);
  outline-offset: 3px;
  border-radius: 4px;
}

.sec--deep :focus-visible,
.footer :focus-visible,
.drawer :focus-visible,
.pd-panel :focus-visible {
  outline-color: var(--gold);
}

/* ── §3/§8 Gesture-driven motion must not run through CSS transitions ─────
   `wb-motion` is set by js/spring.js only when the motion system is live, so
   without JavaScript the original CSS transition still animates the sheets.
   Progressive enhancement, not a hard dependency.

   `visibility` keeps its transition: it is discretely animated, so it flips at
   the END of the duration, which is what keeps a closing sheet on screen while
   the spring carries it out. */
.wb-motion .drawer,
.wb-motion .cart-drawer {
  transition: visibility var(--dur-sheet) ease;
}

/* The scrim's opacity is driven per-frame by the sheet spring, so it must not
   also be interpolated by CSS — two authorities on one property is the classic
   cause of a laggy, rubbery scrim. */
.wb-motion .menu-scrim,
.wb-motion .cart-scrim {
  transition: visibility var(--dur-sheet) ease;
}

/* ── §12 Materials — translucent chrome with content scrolling under ──────
   The previous code deliberately refused backdrop-filter here, with a real
   reason: a blur over scrolling content re-samples every frame and is a
   classic scroll-jank source. That objection is answered rather than ignored:

     · the blur only exists once scrolled (--scrolled), so the hero — where
       the 3D canvas is already compositing every frame — never pays for it;
     · the blurred strip is short, so the re-sampled area stays small;
     · `will-change: backdrop-filter` promotes it to its own layer once;
     · it is switched off entirely under prefers-reduced-transparency (§32).

   If jank ever reappears on a low-end device, delete this one block — the
   solid fallback below it is still there. */
.topbar--scrolled {
  background: var(--material-thin-bg);
  -webkit-backdrop-filter: var(--material-thin-blur);
  backdrop-filter: var(--material-thin-blur);
  will-change: backdrop-filter;
  /* §12 a bright top edge reads as light catching the material */
  box-shadow: inset 0 1px 0 var(--material-edge), 0 1px 0 var(--hairline);
}

/* §12 bigger surfaces read as thicker: more blur, deeper shadow than the bar. */
.wb-motion .cart-drawer {
  background: var(--material-thick-bg);
  -webkit-backdrop-filter: var(--material-thick-blur);
  backdrop-filter: var(--material-thick-blur);
  box-shadow: var(--shadow-material);
}

/* §12 "never stack a light translucent surface on another" — the checkout
   panel sits inside the already-translucent cart drawer, so it is solid. */
.wb-motion .cart-drawer .checkout,
.wb-motion .cart-drawer .cart-done {
  background: var(--surface);
  backdrop-filter: none;
}

/* §12 vibrancy: over a translucent surface, don't use flat grey — carry more
   contrast, a touch more weight, and a small tracking bump so the text stays
   legible as whatever is behind it scrolls past. */
.wb-motion .cart-drawer .cart-item__name,
.wb-motion .cart-drawer .cart-total {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: 0.005em;
}

/* ── §12 Scroll edge effect, not a hard divider ───────────────────────────
   Fade content out where it meets the floating bar instead of drawing a 1px
   rule under it. Only applied where floating chrome actually overlaps. */
.wb-motion .topbar--scrolled::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 12px;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(250, 247, 242, 0.7), rgba(250, 247, 242, 0));
}

/* ── The packing photograph behind section 1 (the hero) ───────────────────
   Same depth trick as the cellar band below — z-index 0 inside .stage, so it
   sits behind the 3D bottle rather than in front of it.

   top:0 / height:100svh pins it to the hero band exactly. The hero is the
   first 100svh of the stage and .cellar-bg starts at 100svh, so the two
   photographs tile the stage end to end with no overlap and no gap. */
.hero-bg {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 100svh;
  z-index: 0;
  pointer-events: none;
  background-image: url('../images/packing-by-hand.jpg');
  background-size: cover;
  /* The source is square; a phone crops it to the middle ~46% horizontally,
     which is where the hands, the bottle and the bag already sit. */
  background-position: center center;
  /* Not background-attachment: fixed — see the note on .cellar-bg. */
}

/* The veil. 0.66, deliberately the SAME value as the cellar band, so the two
   photographic bands on this page are one treatment rather than two.

   It is sized against a black photograph, not against this one. That is not
   over-caution here: the image measures a minimum luminance of 0.0009 in the
   capsule and the tape dispenser, i.e. it genuinely contains near-black.

       veil   wine    ink     muted
       0.62   4.51    5.93    1.89
       0.66   5.09    6.68    2.13   ← chosen
       0.70   5.71    7.50    2.39

   Solid cream for the first 6% keeps the photograph out from under the fixed
   top bar, and solid again at the bottom so the hero meets .cellar-bg's own
   cream top edge with no seam (§7 spatial consistency, §12 scroll edges). */
.hero-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    var(--bg) 0%,
    var(--bg) 6%,
    rgba(250, 247, 242, 0.66) 13%,
    rgba(250, 247, 242, 0.66) 92%,
    var(--bg) 100%
  );
}

/* §12 vibrancy, and the same defect the store band had: --muted is 5.02:1 on
   plain cream but only 2.13:1 over this veil, and no veil that leaves the
   photograph visible can rescue it — at 0.86 it is still 3.64:1. Ink at
   weight 500 measures 6.68:1. This is a contrast fix forced by the new
   backdrop, not a restyle of the hero. */
.hero .sub {
  color: var(--ink);
  font-weight: 500;
}

/* Desktop framing lives here rather than in desktop.css, because this file
   loads last and would otherwise override it. A landscape window crops the
   square photograph vertically instead of horizontally, and centred it cuts
   the bottle's cap off the top. Biasing up keeps the hands, the bottle and
   the bag's shoulder in frame; what is lost is the table, which carries
   nothing. Phones never read this block, so the mobile crop cannot drift. */
@media (min-width: 960px) {
  .hero-bg {
    background-position: center 34%;
  }
}

@media (prefers-contrast: more) {
  .hero-bg::after {
    background: var(--bg);
  }
}

/* The cellar photograph lived here twice — first as a veiled backdrop behind
   section 2, then as a <figure> in #cellar — and was removed from the page on
   11 Aug at the founder's request. `images/cellar-room.jpg` is still on disk
   and untouched; nothing references it. */

/* ── The Tallinn interior behind the "coming soon" store band ─────────────
   Simpler than the cellar: this section is not inside .stage, so there is no
   3D bottle to sit in front of and a background on the section itself works.
   The photograph is already soft-focus, which is why it can carry text at all. */
.store-band {
  position: relative;
  isolation: isolate; /* keep the veil's z-index local to this section */
  background-image: url('../images/store-tallinn.jpg');
  background-size: cover;
  background-position: center 40%;
  /* The band is a <section>, so it inherits min-height:100svh. With a flat
     tint that was invisible; with a photograph behind it, top-aligned copy
     left the whole lower half as empty backdrop. Centre it in its own band. */
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.store-band::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Fades to solid at both ends so the band does not hard-edge into the
     sections above and below (§7 spatial consistency). */
  background: linear-gradient(
    to bottom,
    var(--bg) 0%,
    rgba(250, 247, 242, 0.72) 18%,
    rgba(250, 247, 242, 0.72) 82%,
    var(--bg) 100%
  );
}

/* §12 vibrancy — "over blurred/translucent surfaces, don't use flat gray text;
   use higher contrast and slightly heavier weight."
   This paragraph was --muted #6f6a62, which cannot pass AA over ANY photograph
   (3.64:1 even under an 86% veil). Ink at this veil measures ~7:1. */
.store-band__text {
  color: var(--ink);
  font-weight: 500;
}

/* §12 "put colour on a solid layer, not the translucent foreground" — the tag
   pill's fill is a 7% wine tint, which over a photograph is effectively
   transparent and left its own label unreadable. Solid cream instead. */
.store-band__tag {
  background: var(--bg);
  box-shadow: 0 1px 3px rgba(59, 10, 20, 0.12);
}

@media (prefers-contrast: more) {
  .store-band::before {
    background: var(--bg);
  }
}

/* §32 — translucency off means the photograph goes too. Both of these are
   decorative images showing through under text, which is exactly what §32 is
   about. A content <img> would NOT belong in this list — hiding content
   because a user dislikes translucency is the wrong reading of the rule. */
@media (prefers-reduced-transparency: reduce) {
  .hero-bg,
  .store-band {
    background-image: none;
  }
}

/* ── §14 / §31 Reduced motion — gentler, not absent ───────────────────────
   "Reduced motion doesn't mean no feedback." Slides and springs become short
   opacity cross-fades; overshoot is dropped; colour and opacity changes that
   aid comprehension stay. */
@media (prefers-reduced-motion: reduce) {
  .drawer,
  .cart-drawer {
    transition: opacity var(--dur-quick) ease, visibility var(--dur-quick) ease;
    transform: none !important;
  }

  .drawer.is-open,
  .cart-drawer.is-open {
    opacity: 1;
  }

  .drawer:not(.is-open),
  .cart-drawer:not(.is-open) {
    opacity: 0;
  }

  /* Press feedback survives — it is instant and non-vestibular. */
  .pill:active,
  .cta:active,
  .chip:active {
    transform: none;
    opacity: 0.72;
  }

  /* §34 no slow looping oscillations (near 0.2 Hz reads as drift). */
  .pd-hero__img,
  .scroll-cue {
    animation: none !important;
  }
}

/* ── §32 Reduced transparency — frostier and solid, blur dropped ───────── */
@media (prefers-reduced-transparency: reduce) {
  .topbar--scrolled,
  .wb-motion .cart-drawer {
    background: var(--bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    will-change: auto;
  }

  .wb-motion .topbar--scrolled::after {
    display: none;
  }

  .topbar::before {
    display: none;
  }
}

/* ── §33 Increased contrast — near-solid with a defined border ─────────── */
@media (prefers-contrast: more) {
  .topbar--scrolled,
  .wb-motion .cart-drawer,
  .drawer {
    background: var(--bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border: 1px solid var(--ink);
  }

  .drawer,
  .sec--deep,
  .footer {
    background: var(--deep);
  }

  :focus-visible {
    outline-width: 3px;
  }

  .badge,
  .pill--ghost,
  .chip {
    border-color: var(--ink);
  }

  .muted,
  .sec-sub,
  .shop-card__meta {
    color: var(--ink);
  }
}
