/* ---------- the opening reveal ---------- */
.loader { display: none; }
.is-loading .loader, .loader.is-done { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; background: var(--brown); color: var(--alabaster); }
.is-loading body { overflow: hidden; }
/* The opening reveal is slow and settled: every grain drifts down a few units into place with
   no overshoot, the ribbon draws across on one long ease, the name rises softly, and the curtain
   fades out rather than flying off. Nothing scales from zero and nothing bounces. */
.loader__in { display: grid; justify-items: center; gap: 1.1rem; transition: opacity 700ms cubic-bezier(0.33, 0, 0.2, 1), transform 900ms cubic-bezier(0.33, 0, 0.2, 1); }
.loader__mark { width: min(40vw, 176px); height: auto; overflow: visible; }
.loader__grains circle { fill: var(--alabaster); opacity: 0; transform-box: fill-box; transform-origin: 50% 100%; animation: grain-settle 1100ms cubic-bezier(0.22, 0.61, 0.36, 1) both; animation-delay: calc(var(--i) * 11ms + 60ms); }
.loader__ribbon { fill: var(--moss-on-brown); clip-path: inset(0 100% 0 0); animation: ribbon-in 1150ms cubic-bezier(0.45, 0, 0.2, 1) 380ms forwards; }
.loader__word { width: min(36vw, 156px); aspect-ratio: 183.88 / 23; background: var(--alabaster); -webkit-mask: url("../brand/wordmark-mono.svg") center / contain no-repeat; mask: url("../brand/wordmark-mono.svg") center / contain no-repeat; opacity: 0; transform: translateY(6px); animation: word-in 900ms cubic-bezier(0.22, 0.61, 0.36, 1) 620ms forwards; }
.loader__bar { width: min(30vw, 110px); height: 2px; border-radius: 2px; background: rgb(243 239 228 / 0.14); overflow: hidden; }
.loader__bar span { display: block; height: 100%; background: var(--moss); transform: scaleX(0); transform-origin: left; animation: bar-fill 1450ms cubic-bezier(0.45, 0, 0.25, 1) 60ms forwards; }
[dir=rtl] .loader__bar span { transform-origin: right; }
.loader.is-done { opacity: 0; transition: opacity 820ms cubic-bezier(0.33, 0, 0.2, 1) 160ms; }
.loader.is-done .loader__in { opacity: 0; transform: translateY(-6px); }
@keyframes grain-settle { from { opacity: 0; transform: translateY(-5px); } 40% { opacity: 1; } to { opacity: 1; transform: none; } }
@keyframes ribbon-in { to { clip-path: inset(0 0 0 0); } }
@keyframes word-in { to { opacity: 1; transform: none; } }
@keyframes bar-fill { to { transform: scaleX(1); } }
/* RS Granules · homepage v2 · motion
 * Rules: animate transform and opacity only (compositor), never clip-path or filter on scroll.
 * Scroll choreography uses view() timelines where the browser has them and an IntersectionObserver
 * fallback (entry only) where it does not. Overlays sit outside every animated wrapper.
 * Reduced motion and ?capture both land on the settled page.
 */

html { scroll-behavior: smooth; }

/* ============================================================
   load choreography: header drops in, hero lines rise, then the rest
   ============================================================ */
.js:not(.is-capture) .hd__island { opacity: 0; transform: translateY(-14px); }
.is-loaded:not(.is-capture) .hd__island { opacity: 1; transform: none; transition: opacity 700ms var(--ease-out) 120ms, transform 900ms var(--ease-out) 120ms, box-shadow var(--d-4) var(--ease-out), border-color var(--d-4) var(--ease-out); }

/* the frame is visible from the first paint (it carries the largest image); it only settles in scale */
.js:not(.is-capture) .hero__stage { transform: scale(0.982); }
.is-loaded:not(.is-capture) .hero__stage { transform: none; transition: transform 1400ms var(--ease-out); }

.js:not(.is-capture) .hero:not(.is-settled) .hero__line { overflow: hidden; padding: 0.06em 0.08em 0.18em; margin: -0.06em -0.08em -0.18em; }
.js:not(.is-capture):lang(ur) .hero:not(.is-settled) .hero__line { padding-block: 0.36em; margin-block: -0.36em; }
.js:not(.is-capture) .hero__line > span { display: block; transform: translateY(112%); }
.is-loaded:not(.is-capture) .hero__line > span { transform: none; transition: transform 1150ms var(--ease-out) 380ms; }
.is-loaded:not(.is-capture) .hero__line + .hero__line > span { transition-delay: 500ms; }
.js:not(.is-capture) :is(.hero__lede, .hero__ctas, .hero__reel) { opacity: 0; transform: translateY(14px); }
.is-loaded:not(.is-capture) :is(.hero__lede, .hero__ctas, .hero__reel) { opacity: 1; transform: none; transition: opacity 900ms var(--ease-out) 760ms, transform 1100ms var(--ease-out) 760ms; }
.is-loaded:not(.is-capture) .hero__ctas { transition-delay: 880ms; }
.is-loaded:not(.is-capture) .hero__reel { transition-delay: 1040ms; }

/* Ken Burns drift on the playing clip (transform only) */
.hero__v.is-drift { animation: hero-drift 9000ms linear both; }
/* no slow zoom on phones: scaling a film while it plays at 24 or 25 fps on a 60 Hz screen reads as judder */
@media (max-width: 47.5rem) { .hero__v.is-drift { animation: none; } }
@keyframes hero-drift { from { transform: scale(1.08); } to { transform: scale(1.005); } }

/* ============================================================
   language switch: text fades out, swaps, fades back
   ============================================================ */
main, .ft, .hd__nav, .hd__tools > .btn { transition: opacity 380ms var(--ease-out); }
.is-lang-out :is(main, .ft, .hd__nav, .hd__tools > .btn) { opacity: 0; transition: opacity 160ms var(--ease-in); }

/* ============================================================
   scroll choreography (view timelines)
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .js:not(.is-capture) [data-rv] { animation-duration: 1ms; animation-timing-function: linear; animation-fill-mode: both; animation-timeline: view(); animation-range: cover calc(var(--i, 0) * 2.5%) cover 100%; }
    .js:not(.is-capture) [data-rv="rise"] { animation-name: rv-rise; }
    .js:not(.is-capture) [data-rv="title"] { animation-name: rv-title; }
    .js:not(.is-capture) [data-rv="media"] { animation-name: rv-media; }
    .js:not(.is-capture) [data-rv="plate"] { animation-name: rv-plate; }
    /* interactive blocks settle in and then stay put: no exit while someone may be using them */
    .js:not(.is-capture) [data-rv="enter"] { animation-name: rv-enter; animation-range: cover 0% cover 32%; }

    /* hero: the film sinks and the words lift away as the page scrolls on */
    .js:not(.is-capture) .hero__media { animation: hero-sink linear both; animation-timeline: view(); animation-range: exit 0% exit 100%; }
    .js:not(.is-capture) .hero__content { animation: hero-lift linear both; animation-timeline: view(); animation-range: exit -10% exit 60%; }

    /* season fold: the photograph moves slower than the page */
    .js:not(.is-capture) .fold__media img { animation: fold-pan linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    /* the fold's timeline is its own figure, so the plate can drift against it */
    .js:not(.is-capture) .fold__plate { animation: fold-plate linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }

    /* decorative motifs: granules drift through, furrows draw themselves */
    .js:not(.is-capture) [data-motif="drift"] { animation: motif-drift linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
    .js:not(.is-capture) [data-motif="draw"] path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: furrow-draw linear both; animation-timeline: --furrows; animation-range: cover 0% cover 55%; }
    .js:not(.is-capture) [data-motif="draw"] { view-timeline: --furrows block; }
    .js:not(.is-capture) [data-motif="draw"] path:nth-child(2) { animation-range: cover 6% cover 62%; }
    .js:not(.is-capture) [data-motif="draw"] path:nth-child(3) { animation-range: cover 12% cover 70%; }

    /* the dark band's content rises a touch later than the band */
    .js:not(.is-capture) .anatomy__list li { animation: rv-row linear both; animation-timeline: view(); animation-range: cover calc(var(--i, 0) * 1.5%) cover 40%; }
  }
}

@keyframes rv-rise {
  0% { opacity: 0; transform: translateY(46px); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  24% { opacity: 1; transform: none; }
  84% { opacity: 1; transform: none; animation-timing-function: cubic-bezier(0.5, 0, 0.8, 0.4); }
  100% { opacity: 0; transform: translateY(-26px); }
}
@keyframes rv-title {
  0% { opacity: 0; transform: translateY(0.55em); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  26% { opacity: 1; transform: none; }
  86% { opacity: 1; transform: none; animation-timing-function: cubic-bezier(0.5, 0, 0.8, 0.4); }
  100% { opacity: 0; transform: translateY(-0.4em); }
}
@keyframes rv-media {
  0% { opacity: 0; transform: translateY(40px) scale(0.955); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  30% { opacity: 1; transform: none; }
  88% { opacity: 1; transform: none; animation-timing-function: cubic-bezier(0.5, 0, 0.8, 0.4); }
  100% { opacity: 0.2; transform: translateY(-20px) scale(0.985); }
}
@keyframes rv-plate {
  0% { opacity: 0; transform: translateY(64px) scale(0.97); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  28% { opacity: 1; transform: none; }
  100% { opacity: 1; transform: none; }
}
@keyframes rv-enter {
  from { opacity: 0; transform: translateY(40px); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  to { opacity: 1; transform: none; }
}
@keyframes rv-row {
  from { opacity: 0; transform: translateX(calc(-18px * var(--flip))); }
  to { opacity: 1; transform: none; }
}
@keyframes hero-sink { to { transform: translateY(6%) scale(1.12); } }
@keyframes hero-lift { to { opacity: 0; transform: translateY(-48px); } }
@keyframes fold-pan { from { transform: translateY(-7%); } to { transform: translateY(7%); } }
@keyframes fold-plate {
  0% { opacity: 0; transform: translateY(90px); animation-timing-function: cubic-bezier(0.2, 0.7, 0.2, 1); }
  34% { opacity: 1; transform: none; }
  100% { opacity: 1; transform: translateY(-40px); }
}
@keyframes motif-drift {
  0% { opacity: 0; transform: translateY(70px) rotate(-14deg) scale(0.82); }
  32% { opacity: 1; }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-70px) rotate(12deg) scale(1.06); }
}
@keyframes furrow-draw { to { stroke-dashoffset: 0; } }

/* inside a sideways scroller the block-axis view timeline has nothing to track: reveal the row as one */
@media (max-width: 40rem) {
  .js .plates [data-rv], .js .finder__tiles [data-rv] { animation: none !important; opacity: 1 !important; transform: none !important; }
}

@media (min-width: 40.01rem) {
  .js .plates[data-rv], .js .finder__tiles[data-rv] { animation: none !important; }
}

/* fallback: IntersectionObserver adds .is-in (entry only) */
@media (prefers-reduced-motion: no-preference) {
  @supports not (animation-timeline: view()) {
    .js:not(.is-capture) [data-rv]:not(.is-in) { opacity: 0; transform: translateY(34px); }
    .js:not(.is-capture) [data-rv="media"]:not(.is-in) { transform: translateY(34px) scale(0.965); }
    .js:not(.is-capture) [data-rv].is-in { transition: opacity 900ms var(--ease-out), transform 1100ms var(--ease-out); transition-delay: calc(var(--i, 0) * 70ms); }
  }
}

/* ============================================================
   in-place swaps: product filter, crop panel, year detail, form steps
   ============================================================ */
.shelf.is-leaving > * { opacity: 0; transform: translateY(8px); transition: opacity 180ms var(--ease-in), transform 200ms var(--ease-in); }
.shelf.is-entering > .shelf__head { animation: swap-in 520ms var(--ease-out) both; }
.shelf.is-entering .plate > * { animation: swap-in 620ms var(--ease-out) both; animation-delay: calc(var(--n, 0) * 70ms); }
.shelf.is-entering .plate > .plate__body { animation-delay: calc(var(--n, 0) * 70ms + 60ms); }
.panel__in.is-swap > * { animation: swap-in 560ms var(--ease-out) both; }
.panel__in.is-swap > :nth-child(2) { animation-delay: 70ms; }
.panel__in.is-swap > :nth-child(3) { animation-delay: 130ms; }
.panel__in.is-swap > :nth-child(4) { animation-delay: 180ms; }
.year__detail.is-swap > .yd__head, .year__detail.is-swap .yd__row { animation: swap-in 520ms var(--ease-out) both; }
.year__detail.is-swap .yd__row:nth-child(2) { animation-delay: 30ms; }
.year__detail.is-swap .yd__row:nth-child(3) { animation-delay: 60ms; }
.year__detail.is-swap .yd__row:nth-child(4) { animation-delay: 90ms; }
.year__detail.is-swap .yd__row:nth-child(5) { animation-delay: 120ms; }
.year__detail.is-swap .yd__row:nth-child(6) { animation-delay: 150ms; }
.st__viewport > .is-entering { opacity: 0; transform: translateX(calc(46px * var(--dir, 1) * var(--flip))); }
.st__viewport > .is-entering.is-in { opacity: 1; transform: none; transition: opacity 420ms var(--ease-out) 110ms, transform 640ms var(--ease-out) 60ms; }
.st__viewport > .is-leaving.is-out { opacity: 0; transform: translateX(calc(-30px * var(--dir, 1) * var(--flip))); transition: opacity 200ms var(--ease-in), transform 260ms var(--ease-in); }
@keyframes swap-in { from { opacity: 0; transform: translateY(14px); } }

/* ============================================================
   motif colouring
   ============================================================ */
.motif--granules circle:nth-child(3n + 1) { fill: var(--moss); }
.motif--granules circle:nth-child(3n + 2) { fill: var(--moss-deep); }
.motif--granules circle:nth-child(3n) { fill: var(--wheat); }
.dealers__motif circle:nth-child(3n) { fill: var(--moss-hi); }

/* ============================================================
   settled states
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; animation-delay: 0ms !important; transition-duration: 1ms !important; transition-delay: 0ms !important; }
  .hero__v.is-drift { animation: none !important; }
}
.is-capture *, .is-capture *::before, .is-capture *::after { transition: none !important; animation: none !important; }
.is-capture { scroll-behavior: auto; }
