/* RESTOCK — motion layer (Phase 0 of docs/motion-plan.md).
   Loaded by index.html after owner.css; inner pages pick it up as they migrate
   to js/motion.js.

   EVERYTHING lives under html.rsm, which js/motion.js adds only when motion is
   allowed — never under prefers-reduced-motion, never under ?flat=1. The
   resting page is the finished page: strip this file or the class and nothing
   is missing, which is the same progressive-enhancement contract owner.css
   uses. Reveal and entrance states are driven by CSS animations rather than
   transitions on purpose: animations don't clobber the hover transitions the
   components already declare (tab buttons, role chips, cards).

   Scroll-linked transforms consume the --p custom property that js/motion.js
   writes to each [data-parallax] element — 0 as the element enters, 1 as it
   leaves ("exit" variants measure from the top edge instead). Transform and
   opacity only; no layout properties are ever animated here. */

/* ---------- reveal ----------
   Hidden state only until .is-in arrives; the stagger comes from --i, which
   js/motion.js stamps once at boot (standalone items just get --i: 0). */
.rsm [data-reveal]:not(.is-in){opacity:0;transform:translateY(1.75rem)}
.rsm [data-reveal].is-in{animation:m-reveal .7s cubic-bezier(.22,.61,.36,1) both;
  animation-delay:calc(var(--i,0)*60ms)}
@keyframes m-reveal{from{opacity:0;transform:translateY(1.75rem)}to{opacity:1;transform:none}}

/* ---------- hero entrance sequence ----------
   Trust line → headline → form → note cascade in on load; the headline's words
   rise individually inside their block (js/motion.js splits .lead into .w/.wi
   pairs and numbers them). Children: headline, capture, subscribe line, then
   the demo-output line, which stays display:none until submitted. */
.rsm .ow-hero__in>*{animation:m-rise 1s cubic-bezier(.22,.61,.36,1) both}
.rsm .ow-hero__in>:nth-child(1){animation-delay:.15s}
.rsm .ow-hero__in>:nth-child(2){animation-delay:.3s}
.rsm .ow-hero__in>:nth-child(3){animation-delay:.45s}
.rsm .ow-hero__in>:nth-child(4){animation-delay:.62s}
.rsm .ow-hero__h1 .lead .w{display:inline-block}
.rsm .ow-hero__h1 .lead .wi{display:inline-block;opacity:0;transform:translateY(.6em);
  animation:m-word .7s cubic-bezier(.22,.61,.36,1) forwards;
  animation-delay:calc(.45s + var(--i,0)*.07s)}
@keyframes m-rise{from{opacity:0;transform:translateY(1.5rem)}to{opacity:1;transform:none}}
@keyframes m-word{to{opacity:1;transform:none}}

/* ---------- parallax consumers ----------
   Hero: footage scales 1.08→1.05 and drifts up while the content column exits
   faster than the page — two depths leaving the same frame. The scrim is left
   alone on purpose: easing its opacity would thin the white handoff band at
   the hero's foot and expose a hard video edge against the next section. */
.rsm .ow-hero[data-parallax] .ow-hero__bg{
  transform:translateY(calc(var(--p,0)*-1.25rem)) scale(calc(1.08 - var(--p,0)*.03));
  will-change:transform}
.rsm .ow-hero[data-parallax] .ow-hero__in{transform:translateY(calc(var(--p,0)*-5rem))}

/* Integrations wall: the concentric rings turn slowly with scroll progress.
   fill-box + center resolves to the rings' shared middle regardless of where
   the svg sits in the section. */
.rsm .ow-wall[data-parallax] .ow-wall__rings g{
  transform-box:fill-box;transform-origin:center;
  transform:rotate(calc(var(--p,0)*40deg))}

/* Bento tiles: classic clip parallax — the image is scaled up inside its
   overflow-hidden frame and drifts against the scroll, so each picture settles
   as its card arrives. */
.rsm .ow-bcard[data-parallax] .ow-bcard__img img{
  transform:scale(1.12) translateY(calc((var(--p,.5) - .5)*-4rem));
  will-change:transform}

/* Closing CTA: photo-road drifts slower than the copy, same technique. */
.rsm .ow-cta[data-parallax] .ow-cta__bg img{
  transform:scale(1.15) translateY(calc((var(--p,.5) - .5)*-5rem));
  will-change:transform}

/* ---------- four-output panels ----------
   Toggling .is-on flips display, which restarts these animations on every tab
   change — autoplay, click, everything already handled by js/owner.js. Text
   block slides first, dashboard card rises behind it, then rows cascade with
   the --i indices js/motion.js stamped at boot. */
.rsm .ow-tpanel.is-on .ow-tpanel__txt>*{animation:m-rise .6s cubic-bezier(.22,.61,.36,1) both}
.rsm .ow-tpanel.is-on .ow-tpanel__txt>:nth-child(2){animation-delay:.08s}
.rsm .ow-tpanel.is-on .ow-tpanel__txt>:nth-child(3){animation-delay:.16s}
.rsm .ow-tpanel.is-on .card{animation:m-card .7s cubic-bezier(.22,.61,.36,1) both;animation-delay:.1s}
.rsm .ow-tpanel.is-on .recipe li,
.rsm .ow-tpanel.is-on .orders li,
.rsm .ow-tpanel.is-on .tbl tbody tr,
.rsm .ow-tpanel.is-on .kpi{animation:m-row .5s cubic-bezier(.22,.61,.36,1) both;
  animation-delay:calc(.3s + var(--i,0)*70ms)}
@keyframes m-card{from{opacity:0;transform:translateY(1.75rem)}to{opacity:1;transform:none}}
@keyframes m-row{from{opacity:0;transform:translateX(-.75rem)}to{opacity:1;transform:none}}

/* ============================================================
   #how SCROLL SCENE — docs/how-scene-plan.md §3–§5.
   A tall track with a sticky stage; js/motion.js scene() writes scroll
   progress into custom properties on [data-scene] and CSS only consumes
   them. The pin and the two-column stage need .rsm and ≥900px; the burger,
   bins, crate and meter additionally need .is-scene, which scene() adds once
   it is running. Until then (and below 900px) the static poster stands in.
   Every beat is a pure function of scroll: no transitions on anything the
   scroll drives, so a reload mid-track lands in the right state at once.
   Phones get the same scene in a stacked stage (below). */

/* the stage is sticky: an anchor inside it would make the browser "correct"
   the scroll every time the page settles, and a reload would land past the
   section. Anchor on anything outside the track instead. */
.rsm .ow-how__track{overflow-anchor:none}

@media (min-width:900px){
  .rsm .ow-how__track{height:450vh}
  .rsm .ow-how__stage{position:sticky;top:var(--how-top,5rem);
    height:calc(100vh - var(--how-top,5rem));display:flex;padding:1.25rem 0 2rem}
  .rsm .ow-how__grid{display:grid;height:100%;container-type:size;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);
    grid-template-areas:"menu menu" "scene panels";column-gap:3.5rem;row-gap:1.5rem}
  .rsm .ow-how .ow-tabs__menu{grid-area:menu;margin:0;grid-template-columns:repeat(4,1fr)}
  /* square, sized by whichever runs out first: the column or the stage */
  .rsm .ow-how__scene{grid-area:scene;order:0;align-self:center;justify-self:center;
    width:min(100%,calc(100cqh - 5.5rem));aspect-ratio:1;border-radius:var(--ow-card);
    background:var(--wash);overflow:hidden;isolation:isolate;container-type:size}
  .rsm .ow-how__flat{display:none}
  .rsm .ow-how__poster{display:block}
  .rsm .ow-how .ow-tabs__panels{grid-area:panels;align-self:center;background:none;
    border-radius:0;overflow:visible}
  .rsm .ow-how .ow-tpanel{flex-direction:column;align-items:stretch;padding:0;min-height:0;gap:1.75rem}
  .rsm .ow-how .ow-tpanel__txt{width:auto;max-width:34rem}
  .rsm .ow-how .ow-tpanel .ow-h4{font-size:1.625rem}
  .rsm .ow-how .ow-tpanel__vis{place-items:stretch}
  .rsm .ow-how .ow-tpanel__vis .card{max-width:none}
}

/* Phones and narrow tablets: one column, pinned under the nav. Tabs as a
   compact 2x2, the square scene, then the beat's kicker and headline; the
   dashboard card stays out of the pinned stage because there is no room to
   read it beside the picture, and the scene's meter and labels carry the
   numbers. svh, not vh: the stage must not grow and shrink with the URL bar. */
@media (max-width:899.98px){
  .rsm .ow-how__track{height:420svh}
  .rsm .ow-how__stage{position:sticky;top:var(--how-top,4rem);
    height:calc(100svh - var(--how-top,4rem));display:flex;padding:.75rem 0 1rem}
  .rsm .ow-how__grid{display:flex;flex-direction:column;justify-content:center;height:100%;gap:.875rem;container-type:size}
  .rsm .ow-how .ow-tabs__menu{order:0;margin:0;gap:0 .75rem}
  .rsm .ow-how .ow-tab{font-size:.8125rem;padding:.55rem 0}
  .rsm .ow-how__scene{order:1;flex:none;align-self:center;width:min(100%,calc(100cqh - 12.5rem));
    aspect-ratio:1;border-radius:1.25rem;background:var(--wash);overflow:hidden;isolation:isolate;
    container-type:size}
  .rsm .ow-how__flat{display:none}
  .rsm .ow-how__poster{display:block}
  /* fixed height: the beats' headlines differ in length, and the centred
     stack must not jump when the tab changes */
  .rsm .ow-how .ow-tabs__panels{order:2;flex:none;height:6.25rem;background:none;border-radius:0;overflow:visible}
  .rsm .ow-how .ow-tpanel{padding:0;min-height:0;gap:0}
  .rsm .ow-how .ow-tpanel__k{font-size:.8125rem;margin-bottom:.35rem}
  .rsm .ow-how .ow-tpanel .ow-h4{font-size:1.125rem;line-height:1.25}
  .rsm .ow-how .ow-tpanel__txt p,.rsm .ow-how .ow-tpanel__vis{display:none}
}
/* tall phones have room for the beat's paragraph under the headline; the
   stage is the size container, so this follows the real pinned height
   (URL bar and all) rather than the device */
@container (min-height:640px) and (max-width:899.98px){
  .rsm .ow-how .ow-tabs__panels{height:11.5rem}
  .rsm .ow-how .ow-tpanel__txt p{display:block;margin-top:.5rem;font-size:.875rem;line-height:1.4}
}

/* the burger box: poster and layers share it exactly, so the swap is invisible.
   On phones it sits left of centre to leave the labels room on the right. */
.rsm .ow-how__poster,.rsm .ow-how.is-scene .ow-burger{position:absolute;left:15%;top:15%;width:70%;height:70%}
@media (max-width:899.98px){
  .rsm .ow-how__poster,.rsm .ow-how.is-scene .ow-burger{left:7%;top:17%;width:66%;height:66%}
}
.rsm .ow-how__scene.is-layers .ow-how__poster{visibility:hidden}
.rsm .ow-how.is-scene .ow-burger{display:block;z-index:2;visibility:hidden}
.rsm .ow-how__scene.is-layers .ow-burger{visibility:visible}

/* per-layer geometry on the shared 1200 canvas (docs/how-scene-plan.md §1.2):
   --cy content centre, --x1 right edge, --w width, all in % of the box;
   --ry the exploded offset, spaced so the centres fall at equal intervals */
.ow-how [data-layer=top-bun],   .ow-how [data-layer-lbl=top-bun]   {--cy:25.5;--x1:83.7;--w:68;  --ry:-27;z-index:7}
.ow-how [data-layer=lettuce],   .ow-how [data-layer-lbl=lettuce]   {--cy:35.2;--x1:88.3;--w:77;  --ry:-20;z-index:6}
.ow-how [data-layer=tomato],    .ow-how [data-layer-lbl=tomato]    {--cy:42.8;--x1:81.1;--w:62.5;--ry:-11;z-index:5}
.ow-how [data-layer=cheddar],   .ow-how [data-layer-lbl=cheddar]   {--cy:54.1;--x1:83.7;--w:68;  --ry:-6; z-index:4}
.ow-how [data-layer=patty],     .ow-how [data-layer-lbl=patty]     {--cy:54.2;--x1:83;  --w:66.8;--ry:11; z-index:3}
.ow-how [data-layer=sauce],     .ow-how [data-layer-lbl=sauce]     {--cy:59.2;--x1:81.8;--w:61.8;--ry:22; z-index:2}
.ow-how [data-layer=bottom-bun],.ow-how [data-layer-lbl=bottom-bun]{--cy:68.4;--x1:83.5;--w:67.3;--ry:30; z-index:1}

/* Beat 1 explodes (--explode), beat 2 flies each layer into its bin
   (--toshelf; --tx/--ty/--ts are measured against the real bins by
   scene()). Scaling about the layer's own centre keeps the landing exact.
   Layers fade in the last stretch, as they drop into the tubs. */
.rsm .ow-how.is-scene .ow-layer{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  pointer-events:none;will-change:transform;transform-origin:50% calc(var(--cy)*1%);
  transform:
    translate(calc(var(--tx,0)*var(--toshelf,0)*1%),
              calc((var(--ry)*var(--explode,0) + (var(--ty,0) - var(--ry)*var(--explode,0))*var(--toshelf,0))*1%))
    scale(calc(1 - (1 - var(--ts,.3))*var(--toshelf,0)));
  opacity:calc(var(--dim,1)*clamp(0,(1 - var(--toshelf,0))*6.5,1));
  transition:translate .2s}   /* the hover lift only; scroll-driven values never transition */
.rsm .ow-how.is-scene .ow-layer[data-layer=sauce]{opacity:calc(var(--dim,1)*clamp(0,1 - var(--toshelf,0)*2,1))}
@media (min-width:900px){   /* seven re-rasterised shadows are too much for a phone GPU */
  .rsm .ow-how.is-scene.is-apart .ow-layer{filter:drop-shadow(0 18px 24px rgba(13,13,15,.16))}
}

/* the grams and cost of each layer, riding beside it once it is apart */
.ow-lbl{display:none}
.rsm .ow-how.is-scene .ow-lbl{display:flex;align-items:center;gap:.45rem;position:absolute;z-index:10;
  left:calc(var(--x1)*1% + 1%);top:calc((var(--cy) + var(--ry)*var(--explode,0))*1%);
  transform:translateY(-50%);opacity:var(--lbl,0);pointer-events:none;white-space:nowrap;
  font-size:.8125rem;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.rsm .ow-how.is-scene .ow-lbl::before{content:"";width:1.25rem;height:1px;background:var(--ow-mut-2)}
@media (max-width:899.98px){
  .rsm .ow-how.is-scene .ow-lbl{font-size:.6875rem;gap:.3rem}
  .rsm .ow-how.is-scene .ow-lbl::before{width:.625rem}
}

/* hover / tap / focus: the layer lifts, the rest dim, one tip follows */
.rsm .ow-how.is-scene .ow-burger.is-hovering .ow-layer{--dim:.6}
.rsm .ow-how.is-scene .ow-burger .ow-layer.is-hot{--dim:1;translate:0 -6px}
.rsm .ow-how.is-scene .ow-how__scene.is-pointing{cursor:pointer}
.rsm .ow-how.is-scene .ow-layer:focus{outline:none}
.rsm .ow-how.is-scene .ow-layer:focus-visible{--dim:1;translate:0 -6px}
.ow-layer__tip{position:absolute;z-index:20;left:0;top:0;transform:translateY(-50%);
  background:var(--ink);color:#fff;border-radius:.5rem;padding:.4rem .6rem;font-size:.8125rem;
  white-space:nowrap;pointer-events:none;font-variant-numeric:tabular-nums}
.ow-layer__tip[hidden]{display:none}
.ow-layer__tip b{font-weight:600}
.ow-layer__tip span{color:rgba(255,255,255,.72)}

/* Beat 2: the shelf rises into place, then parks small in the corner (--park)
   when the crate needs the room. The fill bars drop from par to on-hand as the
   layers land (--drop); lettuce ends at a quarter of par and goes red. The
   row rests a little above centre-bottom and drops into the corner as it
   parks (cqh: the scene is a size container). */
.rsm .ow-how.is-scene .ow-bins{display:flex;position:absolute;z-index:1;left:5%;right:5%;bottom:24%;
  gap:2.5%;align-items:flex-end;transform-origin:100% 100%;
  transform:translateY(calc((1 - var(--toshelf,0))*40% + var(--park,0)*19cqh)) scale(calc(1 - var(--park,0)*.5));
  opacity:var(--toshelf,0)}
.ow-bin{position:relative;flex:1;margin:0}
.ow-bin img{display:block;width:100%;height:auto}
.ow-bin__bar{display:block;height:4px;margin-top:.5rem;border-radius:2px;background:rgba(13,13,15,.1);overflow:hidden}
.ow-bin__fill{display:block;height:100%;background:var(--ink);transform-origin:left;
  transform:scaleX(calc(1 - (1 - var(--ratio,1))*var(--drop,0)))}
.ow-bin__low{position:absolute;left:50%;top:0;transform:translate(-50%,-50%);opacity:0;
  font-size:.6875rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:#fff;background:var(--red-aa);border-radius:999px;padding:.2rem .55rem;transition:opacity .25s}
.rsm .ow-how.is-low .ow-bin--low .ow-bin__fill{background:var(--red)}
.rsm .ow-how.is-low .ow-bin__low{opacity:1}
.rsm .ow-how.is-scene[data-beat="2"] .ow-bin--low img{animation:m-pulse .8s cubic-bezier(.22,.61,.36,1) 1}
@keyframes m-pulse{0%,100%{transform:none}40%{transform:scale(1.08)}}

/* Beat 3: the crate rises in (--crate-in), then its frames scrub (canvas,
   js/motion.js sequence()). The mask hides the clip's faint vignette. The
   chip rises out of the box from frame 60 (--chip). */
.rsm .ow-how.is-scene .ow-crate{display:block;position:absolute;z-index:3;left:-14%;right:-14%;top:0;
  aspect-ratio:16/9;transform:translateY(calc((1 - var(--crate-in,0))*120%));opacity:var(--crate-in,0);
  -webkit-mask-image:radial-gradient(120% 100% at 50% 60%,#000 62%,transparent 100%);
          mask-image:radial-gradient(120% 100% at 50% 60%,#000 62%,transparent 100%)}
.ow-crate__poster,.ow-crate__seq{position:absolute;inset:0;width:100%;height:100%}
.ow-crate__seq{opacity:0}
.ow-crate.is-ready .ow-crate__seq{opacity:1}
.ow-crate.is-ready .ow-crate__poster{opacity:0;transition:opacity .12s}
.ow-crate__chip{position:absolute;left:50%;top:16%;z-index:2;opacity:var(--chip,0);
  transform:translate(-50%,calc((1 - var(--chip,0))*1.25rem));background:#fff;border-radius:999px;
  padding:.45rem .9rem;font-size:.875rem;font-weight:600;white-space:nowrap;
  box-shadow:0 .5rem 1.5rem rgba(13,13,15,.12)}
.ow-seqdebug{position:absolute;right:.5rem;bottom:.5rem;z-index:5;font:600 .75rem/1 monospace;
  background:var(--ink);color:#fff;padding:.25rem .4rem;border-radius:.25rem}

/* Corner readout: label and value per beat (js/motion.js meter()) */
.rsm .ow-how.is-scene .ow-how__meter{display:flex;flex-direction:column;gap:.2rem;position:absolute;
  z-index:5;left:1.5rem;top:1.25rem}
.ow-how__meter-k{font-size:.6875rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--ow-mut-2)}
.ow-how__meter-v{font-size:2rem;font-weight:600;letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums}
@media (max-width:899.98px){
  /* top-right: the exploded top bun needs the left corner on a phone */
  .rsm .ow-how.is-scene .ow-how__meter{left:auto;right:.875rem;top:.75rem;align-items:flex-end;text-align:right}
  .ow-how__meter-k{font-size:.5625rem}
  .ow-how__meter-v{font-size:1.125rem}
  .ow-crate__chip{font-size:.75rem;padding:.35rem .7rem}
  .ow-bin__low{font-size:.5625rem;padding:.15rem .4rem}
}

/* Beat 4: the picture steps back so the cost table reads */
.rsm .ow-how.is-scene[data-beat="3"] .ow-how__scene{opacity:calc(1 - var(--cost,0)*.3)}

/* ============================================================
   PHASES 2–3 — inner pages (pos, food-cost, inventory,
   purchasing, recipes, clock, resources). Same contract as above:
   everything lives under html.rsm; the resting page is the page. */

/* ---------- cinematic hero entrance ----------
   Eyebrow → headline lines → sub → CTAs → note cascade on load; the
   hand-drawn underline draws itself last. The h1 stands still and lets its
   two .ln lines rise individually. */
.rsm .hero--cine .hero__inner>*{animation:m-rise .9s cubic-bezier(.22,.61,.36,1) both}
.rsm .hero--cine .hero__inner>.hero__h1{animation:none}
.rsm .hero--cine .hero__h1 .ln{display:block;
  animation:m-rise .85s cubic-bezier(.22,.61,.36,1) both}
.rsm .hero--cine .hero__h1 .ln:nth-child(1){animation-delay:.16s}
.rsm .hero--cine .hero__h1 .ln:nth-child(2){animation-delay:.3s}
.rsm .hero--cine .hero__inner>:nth-child(3){animation-delay:.48s}
.rsm .hero--cine .hero__inner>:nth-child(4){animation-delay:.6s}
.rsm .hero--cine .hero__inner>:nth-child(5){animation-delay:.72s}
.rsm .hero--cine .uline__svg path{stroke-dasharray:320;stroke-dashoffset:320;
  animation:m-draw .9s cubic-bezier(.22,.61,.36,1) forwards;animation-delay:1s}
@keyframes m-draw{to{stroke-dashoffset:0}}

/* ---------- parallax consumers (inner pages) ----------
   Hero: the photo drifts down and settles deeper while the copy column exits
   faster — same two-depth exit as the homepage hero. Screenshot media and the
   hardware scenes get a gentle clip-parallax drift through their section. */
.rsm .hero--cine[data-parallax] .hero__bg img{
  transform:translateY(calc(var(--p,0)*3.5rem)) scale(calc(1.06 + var(--p,0)*.05));
  will-change:transform}
.rsm .hero--cine[data-parallax] .hero__inner{transform:translateY(calc(var(--p,0)*-3rem))}
.rsm .split__media--shot[data-parallax] img{
  transform:scale(1.08) translateY(calc((var(--p,.5) - .5)*-3rem));
  will-change:transform}
.rsm .pc[data-parallax] .pc__scene svg{
  transform:translateY(calc((var(--p,.5) - .5)*-1.6rem))}

/* ---------- POS flow: the sale travels the chain ----------
   The dashed connector marches toward the outputs while it is on screen; the
   input node, arrow and output tiles pop in sequence via data-reveal-group. */
.rsm .pos__flow[data-parallax] .pos__arrow path:first-child{
  animation:m-march 1.1s linear infinite}
@keyframes m-march{to{stroke-dashoffset:-17}}

/* ---------- food cost: growing cost bars ----------
   Bars stand at scaleX(0) until the block arrives, then grow left-to-right,
   staggered by a hand-stamped --i on each <i>. */
.rsm .mcbars[data-reveal]:not(.is-in) .mcbar__track i{transform:scaleX(0)}
.rsm .mcbars[data-reveal].is-in .mcbar__track i{
  transition:transform 1.1s cubic-bezier(.22,.61,.36,1);
  transition-delay:calc(.25s + var(--i,0)*.16s)}

/* ---------- purchasing: invoice fills itself in ----------
   Header first, then each line slides in one after another (--i from the
   reveal group on the <ul>), then the total lands as the amounts count up. */
.rsm .minv[data-reveal].is-in .minv__head{animation:m-rise .5s both}
.rsm .minv[data-reveal].is-in li{animation:m-row .45s cubic-bezier(.22,.61,.36,1) both;
  animation-delay:calc(.2s + var(--i,0)*.22s)}
.rsm .minv[data-reveal].is-in .minv__tot{animation:m-rise .5s both;
  animation-delay:.9s}

/* ---------- inventory hardware: live readouts ----------
   The Scale's weighed pour and Therm-iQ's drifting walk-in pop in after the
   card has landed; their numbers tick up via [data-mcount]. */
.rsm .pc[data-reveal] .mchip{opacity:0;transform:translateY(.5rem)}
.rsm .pc[data-reveal].is-in .mchip{
  animation:m-chip .55s cubic-bezier(.22,.61,.36,1) both;animation-delay:1.05s}
@keyframes m-chip{from{opacity:0;transform:translateY(.5rem)}to{opacity:1;transform:none}}

/* ---------- clock: labour gauge ----------
   The arc rests full in the markup (finished state); under .rsm it starts
   empty and eases to its attribute value once the block arrives. */
.rsm .mgauge[data-reveal]:not(.is-in) .mgauge__fill{stroke-dashoffset:327}
.rsm .mgauge[data-reveal].is-in .mgauge__fill{
  transition:stroke-dashoffset 1.5s cubic-bezier(.22,.61,.36,1) .25s}

/* ---------- belt and suspenders ----------
   js/motion.js never adds .rsm under reduced motion, but a preference flipped
   mid-session shouldn't leave a half-animated page behind either. */
@media (prefers-reduced-motion:reduce){
  .rsm [data-reveal],.rsm [data-reveal].is-in,
  .rsm .ow-hero__in>*,.rsm .ow-hero__h1 .lead .wi,
  .rsm .ow-tpanel.is-on .ow-tpanel__txt>*,.rsm .ow-tpanel.is-on .card,
  .rsm .ow-tpanel.is-on .recipe li,.rsm .ow-tpanel.is-on .orders li,
  .rsm .ow-tpanel.is-on .tbl tbody tr,.rsm .ow-tpanel.is-on .kpi{
    animation:none!important;opacity:1;transform:none}
  .rsm .ow-hero__bg,.rsm .ow-hero__in,
  .rsm .ow-wall__rings g,.rsm .ow-bcard__img img,.rsm .ow-cta__bg img{
    transform:none!important}

  .rsm .hero--cine .hero__inner>*,.rsm .hero--cine .hero__h1 .ln,
  .rsm .minv .minv__head,.rsm .minv li,.rsm .minv .minv__tot,
  .rsm .pc .mchip{
    animation:none!important;opacity:1;transform:none}
  .rsm .hero--cine .uline__svg path{animation:none!important;stroke-dashoffset:0}
  .rsm .pos__flow .pos__arrow path:first-child{animation:none!important}
  .rsm .hero--cine[data-parallax] .hero__bg img,
  .rsm .hero--cine[data-parallax] .hero__inner,
  .rsm .split__media--shot[data-parallax] img,
  .rsm .pc[data-parallax] .pc__scene svg{transform:none!important}
  .rsm .mcbars .mcbar__track i{transform:none!important;transition:none!important}
  .rsm .mgauge .mgauge__fill{transition:none!important;stroke-dashoffset:245.5!important}
  /* #how: a preference flipped mid-session unpins the scene and stops the lift */
  .rsm .ow-how__track{height:auto!important}
  .rsm .ow-how__stage{position:static!important}
  .rsm .ow-how .ow-layer,.rsm .ow-how .ow-bin--low img{transition:none!important;animation:none!important}
}

/* ---------- product pages (Phase 2) ---------- */

/* the hero mock drifts up and settles as the page starts moving */
.rsm .ow-phero[data-parallax] .ow-phero__frame{
  transform:translateY(calc(var(--p,0) * -2.5rem))}

/* classic clip parallax: the square is oversized inside its frame so it can
   travel without ever showing an edge */
.rsm .ow-bens__img[data-parallax] img{
  transform:scale(1.14) translateY(calc((var(--p,0) - .5) * 3rem))}

/* the bento screenshot lifts slightly slower than the card it sits in */
.rsm .ow-fb__heroMedia[data-parallax] img{
  transform:translateY(calc((var(--p,0) - .5) * -2rem))}

/* benefit rows arrive one after another rather than as a block */
.rsm .ow-bens__list[data-reveal-group] li:not(.is-in){opacity:0;transform:translateY(1.25rem)}
.rsm .ow-bens__list[data-reveal-group] li.is-in{
  animation:m-reveal .7s cubic-bezier(.22,.61,.36,1) both;
  animation-delay:calc(var(--i,0) * 110ms)}

/* cross-link cards cascade across the row */
.rsm .ow-more__grid[data-reveal-group] .ow-mcard:not(.is-in){opacity:0;transform:translateY(1.25rem)}
.rsm .ow-more__grid[data-reveal-group] .ow-mcard.is-in{
  animation:m-reveal .6s cubic-bezier(.22,.61,.36,1) both;
  animation-delay:calc(var(--i,0) * 70ms)}

/* rows inside any product-page card mock stagger in as the card arrives, the
   same treatment the homepage tab panels already use */
.rsm [data-reveal].is-in .recipe li,
.rsm [data-reveal].is-in .orders li,
.rsm [data-reveal].is-in .tbl tbody tr,
.rsm [data-reveal].is-in .kpi{
  animation:m-row .5s cubic-bezier(.22,.61,.36,1) both;
  animation-delay:calc(.18s + var(--i,0) * 70ms)}
