/* Motion layer. Every effect has a reduced-motion fallback and never changes final geometry —
   the measurement harness runs with transitions disabled and must still see the comp's values. */

/* scroll reveal */
.js [data-reveal] { opacity: 0; transform: translateY(12px); transition: opacity var(--t-reveal) var(--ease-out), transform var(--t-reveal) var(--ease-out); transition-delay: calc(var(--i, 0) * var(--stagger)); }
.js [data-reveal].is-in { opacity: 1; transform: none; }
/* client 2026-11-04: the tiles only fade — a scaled tile opened cream seams between its
   neighbours while the row revealed (the band behind them is ink, home.css) */
.js .tile[data-reveal] { transform: none; }

/* hero entrance */
.js [data-hero-item] { opacity: 0; transform: translateY(12px); animation: hero-in var(--t-reveal) var(--ease-out) forwards; animation-delay: calc(.15s + var(--i, 0) * var(--stagger)); }
.js .hero__bg { animation: hero-zoom 9s var(--ease-out) forwards; }
@keyframes hero-in { to { opacity: 1; transform: none; } }
@keyframes hero-zoom { from { transform: scale(1.05); } to { transform: scale(1); } }

/* header */
.site-header { transition: box-shadow var(--t-tint) var(--ease-out); }
.site-header.is-scrolled { box-shadow: 0 8px 24px rgba(44, 36, 32, .25); }

/* images fade in as they arrive */
.js img[loading="lazy"] { opacity: 0; transition: opacity var(--t-reveal) var(--ease-out); }
.js img[loading="lazy"].is-loaded, .js img[loading="lazy"][data-loaded] { opacity: 1; }

/* in-page navigation (results.js): the swapped regions cross-fade out and back in. The
   wrappers are bare, so with JS off the layout never notices them. */
:is([data-results], [data-swap-part], [data-swap-slot]) {
  transition: opacity var(--t-tint) var(--ease-out);
}
:is([data-results], [data-swap-part], [data-swap-slot]).is-swapping { opacity: 0; }

/* cart pill bump + wish toggle */
@keyframes bump { 0% { transform: scale(1); } 35% { transform: scale(1.08); } 100% { transform: scale(1); } }
.cart-pill.is-bumping { animation: bump var(--t-reveal) var(--ease-out); }
/* Comment 12: an active heart is the SOLID ink glyph (icon-heart-card-solid.svg, #2c2420) —
   no rosewood filter over it any more. */
[data-wish] img { transition: transform var(--t-move) var(--ease-out); }
[data-wish][aria-pressed="true"] img { transform: scale(var(--zoom)); }
.pdp__wish-on, [data-wish][aria-pressed="true"] .pdp__wish-off { display: none; }
[data-wish][aria-pressed="true"] .pdp__wish-on { display: block; }
[data-wish]:active img { transform: scale(var(--press)); }

/* button feedback */
.btn, .btn-pill, .pcard__add, .fcard__add, .pcard__go, .fcard__go, .tile__go, .best__nav {
  transition: background-color var(--t-tint) var(--ease-out),
    color var(--t-tint) var(--ease-out),
    border-color var(--t-tint) var(--ease-out),
    transform var(--t-move) var(--ease-out),
    box-shadow var(--t-tint) var(--ease-out);
}
.btn:active, .btn-pill:active, .pcard__add:active, .fcard__add:active { transform: scale(var(--press)); }
/* A button answers with its own surface — the tint each sheet declares, fading in and back
   out over --t-tint. No lift: a row of pills all rising together was the page's loudest
   gesture and said nothing about which control the pointer is on. */
.best__nav:hover, .best__nav:focus-visible { opacity: .65; }
/* The reveal rules above are more specific than a bare .pcard, so the hover state has to match
   them or the ring snaps (the transition never applies). */
.pcard, .js .pcard.is-in { transition: box-shadow var(--t-move) var(--ease-out); }
/* The card is a white plate: it draws a warm hairline inside its own edge instead of floating
   on a drop shadow. Inset, so nothing moves and no band below it shifts. */
.pcard:hover, .js .pcard.is-in:hover, .pcard:focus-within, .js .pcard.is-in:focus-within {
  box-shadow: inset 0 0 0 1px rgba(139, 99, 85, .22);
}
.js .pcard__media img, .js img.tile__bg, .js .bcard img,
.pcard__media img, .tile__bg, .bcard img { transition: transform var(--t-move) var(--ease-out); }
.pcard:hover .pcard__media img, .pcard:focus-within .pcard__media img { transform: scale(var(--zoom)); }
/* PH-02: the card's second photo is a hover state, not a lazy arrival — the image fade above
   (`.js img[loading=lazy].is-loaded`) must not show it at rest. Hidden until the card is hovered
   or focused. The swap itself is INSTANT (client, 2026-10-27: the cross-fade read as two photos
   at once) — only the zoom it shares with photo 1 moves, over --t-move. */
.js .pcard__media img.pcard__alt { opacity: 0; transition: opacity 0s, transform var(--t-move) var(--ease-out); }
.js .pcard:is(:hover, :focus-within) .pcard__media img.pcard__alt { opacity: 1; }
.tile:hover .tile__bg, .tile:focus-within .tile__bg { transform: scale(var(--zoom)); }
.tile__go { transition: background-color var(--t-tint) var(--ease-out), transform var(--t-move) var(--ease-out); }
/* the one thing that still moves: an arrow leans --nudge towards where it goes */
.tile:hover .tile__go, .tile:focus-within .tile__go { transform: translateX(var(--nudge)); }

/* ---- hover / focus: every state change fades in and back out, none of them snap ---- */
.site-nav a, .drawer__nav a, .site-footer__cols a, .bcard__title a, .tab,
.newsletter__consent a, .nl__consent a, .site-header__logo, .icon-btn, .cart-pill, .burger,
.drawer__close, .newsletter__submit, .newsletter__input, .site-footer__social a,
.dots .dot, .nl__field, .nl__field input, .nl__field button {
  transition: color var(--t-tint) var(--ease-out), background-color var(--t-tint) var(--ease-out),
    border-color var(--t-tint) var(--ease-out), opacity var(--t-tint) var(--ease-out),
    text-decoration-color var(--t-tint) var(--ease-out), transform var(--t-move) var(--ease-out);
}
.site-header__logo:hover, .icon-btn:hover, .cart-pill:hover, .burger:hover, .drawer__close:hover,
.newsletter__submit:hover, .site-footer__social a:hover { opacity: .65; }
.drawer__nav a:hover { color: var(--cream); }
/* the label leans into the pointer — 2px, the smallest shift that still reads */
.site-footer__cols a, .newsletter__consent a, .nl__consent a { display: inline-block; }
.site-footer__cols a:hover, .cart-continue:hover { transform: translateX(var(--nudge)); }
/* the card's name is what the pointer is really asking about — it tints wherever on the card
   the pointer (or the keyboard) landed, not only on the glyphs themselves */
.pcard__name a { transition: color var(--t-tint) var(--ease-out); }
.bcard__title a:hover, .bcard__title a:focus-visible,
.bcard:hover .bcard__title a, .bcard:focus-within .bcard__title a,
.pcard:hover .pcard__name a, .pcard:focus-within .pcard__name a { color: var(--accent); }
.newsletter__consent a:hover, .nl__consent a:hover { color: var(--gold); }
.nl__field:focus-within, .nl__field input:focus, .newsletter__input:focus { border-color: var(--gold); }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* comment 46: the search bar's input takes no ring — the caret and the bar itself are its focus cue */
.hsearch__input:focus-visible { outline: none; }

/* ---- gentle life on the otherwise static parts ---- */

/* nav links grow their own underline instead of blinking one on. Comment 08: the rule hugs the
   LABEL, not the fixed-width link box (a shorter label left it 11px past the ink), and stops
   short of the trailing letter-spacing the last glyph carries. */
.site-nav__label { position: relative; display: inline-block; }
.site-nav__label::after {
  content: ""; position: absolute; left: 0; right: .1em; bottom: -4px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-move) var(--ease-out), opacity var(--t-tint) var(--ease-out);
  opacity: 0;
}
.site-nav a:hover .site-nav__label::after, .site-nav a:focus-visible .site-nav__label::after,
.site-nav a[aria-current="page"] .site-nav__label::after {
  transform: scaleX(1); opacity: 1;
}

/* A journal card has no plate — it is a photo with loose text under it, so it answers the way
   the component reads: the photo grows to --zoom and the title tints to the brand ink. Nothing
   lifts and nothing casts a shadow (the text block used to slide 3px with a shadow around it). */
.bcard:hover img, .bcard:focus-within img { transform: scale(var(--zoom)); }

/* Comment 15 — the quiz band arrives as a pair: the rosewood BG unrolls from the right edge,
   the photo slides out from its left edge over it, and the copy follows in the usual 12px rise.
   All three are clip-path wipes / the standard reveal on --t-unveil / --t-reveal + --ease-out,
   staggered by --stagger; nothing overshoots and nothing reflows (clip-path paints only). The section
   itself no longer fades — the choreography inside it IS its reveal. */
.js .quiz[data-reveal] { opacity: 1; transform: none; }
/* R2-01 („šiek tiek lėčiau ir lengviau“): both wipes run on --t-unveil (800, the slow end of the
   reveal band) and FADE IN while they unroll, so the leading edge arrives soft instead of as a
   hard cut; the photo trails the BG by 2x --stagger and the copy rises after 5x --stagger. */
.js .quiz[data-reveal] .quiz__panel { clip-path: inset(0 0 0 100%); opacity: 0; }
.js .quiz[data-reveal] .quiz__img { clip-path: inset(0 100% 0 0); opacity: 0; }
.js .quiz[data-reveal] .quiz__copy { opacity: 0; transform: translateY(12px); }
.js .quiz[data-reveal] .quiz__panel, .js .quiz[data-reveal] .quiz__img {
  transition: clip-path var(--t-unveil) var(--ease-out), opacity var(--t-unveil) var(--ease-out);
}
.js .quiz[data-reveal] .quiz__img { transition-delay: calc(2 * var(--stagger)); }
.js .quiz[data-reveal] .quiz__copy {
  transition: opacity var(--t-reveal) var(--ease-out), transform var(--t-reveal) var(--ease-out);
  transition-delay: calc(5 * var(--stagger));
}
.js .quiz.is-in .quiz__panel, .js .quiz.is-in .quiz__img { clip-path: inset(0); opacity: 1; }
.js .quiz.is-in .quiz__copy { opacity: 1; transform: none; }

/* full-bleed photos drift inside their own frame — object-position, so nothing bleeds or
   reflows; only while the section is in view, and only once the reveal has landed */
@keyframes photo-drift {   /* around the admin's focal point (--fx/--fy, PH-19), else the centre */
  from { object-position: var(--fx, 50%) calc(var(--fy, 50%) - 4%); }
  to { object-position: var(--fx, 50%) calc(var(--fy, 50%) + 4%); }
}
.js .quiz.is-in .quiz__img, .js .editorial.is-in .editorial__img {
  animation: photo-drift var(--t-drift) var(--ease-out) infinite alternate;
}
/* object-position repaints the photo on every frame, so the drift holds still while the page
   scrolls (Lenis's class, wheel and native alike) and the scroll frames stay paint-free */
.lenis-scrolling .js .quiz.is-in .quiz__img,
.lenis-scrolling .js .editorial.is-in .editorial__img { animation-play-state: paused; }

/* inputs fade their border on focus, and every control answers the keyboard too */
input, textarea, select { transition: border-color var(--t-tint) var(--ease-out), box-shadow var(--t-tint) var(--ease-out); }
.site-nav a:focus-visible, .site-footer__cols a:focus-visible { color: var(--cream); }

/* parallax on the quote band (JS sets --py) */
.js [data-parallax] .quote__bg { transform: translateY(var(--py, 0)) scale(1.12); will-change: transform; }
/* …and on the PDP banner (2026-10-28 #6): ±24px inside the band, scaled just enough that the
   travel never shows an edge — the scale's overhang (h × (s − 1) / 2) ≥ 24 a side: 24 of the
   400 band at 1728, 24 of the 160 one on the 360 canvas (2026-11-04) */
.js [data-parallax] .pdp-wide__img { transform: translateY(var(--py, 0)) scale(1.12); will-change: transform; }
@media (max-width: 767px) {
  .js [data-parallax] .pdp-wide__img { transform: translateY(var(--py, 0)) scale(1.3); }
}

/* USP ticker on mobile (JS toggles) */
.usp__list li { transition: opacity var(--t-move) var(--ease-out); }

/* ---- inertial scrolling (Lenis 1.3.11, vendored) ---- */
html.lenis, html.lenis body { height: auto; }
.lenis:not(.lenis-autoToggle).lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }

/* ---- page transitions: a symmetric fade-through-cream between same-origin documents ----
   The header and footer are the same on every page, so only `main` fades: out to the cream
   body on the click (`is-leaving`, motion.js), and in from cream on the next document
   (`is-entering`, set and released by the inline script in base.html). Driven by JS, not by
   the browser's cross-document View Transitions: the MPA opt-in aborted on most navigations
   ("ViewTransition opt-in disabled") and threw into the page. */
.js main { transition: opacity var(--t-tint) var(--ease-out); }
.js.is-leaving main, .js.is-entering main { opacity: 0; }

/* ---- mini-cart drawer ---- */
.cart-drawer__scrim { transition: opacity var(--t-tint) var(--ease-out); }
.cart-drawer__panel { transition: transform var(--t-move) var(--ease-out); }
.cart-drawer.is-open .cart-drawer__scrim { opacity: 1; }
.cart-drawer__frost { transition: opacity var(--t-tint) var(--ease-out); }
.cart-drawer.is-open .cart-drawer__frost { opacity: 1; transition-delay: var(--t-move); }   /* after the slide */
@media (prefers-reduced-motion: reduce) { .cart-drawer.is-open .cart-drawer__frost { transition-delay: 0s; } }
.cart-drawer.is-open .cart-drawer__panel { transform: none; }
.cart-drawer__close, .qty__btn, .cart-line__del, .cart-cta, .cart-continue, .rec__add, .cart-recs__arrow {
  transition: color var(--t-tint) var(--ease-out), background-color var(--t-tint) var(--ease-out),
    border-color var(--t-tint) var(--ease-out), opacity var(--t-tint) var(--ease-out),
    transform var(--t-move) var(--ease-out);
}
.cart-drawer__close:hover, .cart-line__del:hover, .qty__btn:hover, .cart-recs__arrow:hover { opacity: .65; }
.cart-cta:hover, .cart-cta:focus-visible { background: var(--ink-hover); }           /* ASSETS 452:4464 */
.cart-continue:hover, .cart-continue:focus-visible { color: var(--accent); }
.rec__add:hover, .rec__add:focus-visible {                                     /* ASSETS 452:4469 */
  background: var(--ink-hover); border-color: var(--ink-hover); color: var(--cream); }
.cart-line__price { transition: opacity var(--t-tint) var(--ease-out); }
.cart-line.is-updating .cart-line__price { opacity: .25; }
.cart-line { transition: opacity var(--t-tint) var(--ease-out), transform var(--t-move) var(--ease-out); }
.cart-line.is-removing { opacity: 0; transform: translateX(24px); }
.cart-line.is-added { animation: cart-line-in .5s var(--ease-out); }
@keyframes cart-line-in { from { background: rgba(139, 99, 85, .12); } to { background: transparent; } }
.cart-ship__bar span { transition: width var(--t-move) var(--ease-out); }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  /* The visitor asked for no motion: nothing animates, anywhere, whatever a component
     declares in its own sheet. The reveals below still have to end up VISIBLE. */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  :root { --t-tint: 0ms; --t-move: 0ms; }
  .js [data-reveal], .js [data-hero-item], .js img[loading="lazy"]:not(.pcard__alt) { opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important; }
  .js .hero__bg, .js .quiz__img, .js .editorial__img, .js .qz-pills .qz-pill {
    animation: none !important; }
  .js .quiz[data-reveal] .quiz__panel, .js .quiz[data-reveal] .quiz__img,
  .js .quiz[data-reveal] .quiz__copy {
    clip-path: none !important; opacity: 1 !important; transform: none !important; transition: none !important; }
  .site-nav__label::after, .jl__tab::after { transition: none !important; }
  .js [data-parallax] .quote__bg, .js [data-parallax] .pdp-wide__img { transform: none; }
  html { scroll-behavior: auto; }
  .js main, .js.is-entering main, .js.is-leaving main { transition: none !important; opacity: 1 !important; }
  .carousel__track { scroll-behavior: auto; }
}
