/*
 * Paytrack product site (kirbyservice.net): Run's component (round 3,
 * plan.md). The job card of job 1043 floats on the right, turned towards
 * Ai, who stands on its left with his line above him; its page turns as the
 * story moves. Markup in obj/part_run.php, the counts and Ai's moves in
 * js/parts/run.js, the runner in js/parts/part.js. Keep this file ASCII.
 *
 * Five steps, four pages: 0 and 1 quote (the parts that fit drop in, then
 * the labour from their fitting time), 2 status (a text at every step),
 * 3 labels (the job tag prints, the part gets its label, the tag is
 * scanned), 4 plan (the monthly service plan: $49 per month, 1 free service
 * a year, the next service; Dimitar's figures, 02/10/2026).
 *
 * The whole scene is sized in em: .pt-part-stage takes the unit from the
 * column's width (container units) and the screen's height, so every part
 * keeps its place at every size and no text drops below 10px (the smallest
 * text is .8em of at least 12.5px). Three compositions: wide (desktop and
 * tablet, 35 x 21 em: the bubble and Ai on the left, the card), phones
 * (25.6 x 19.8 em: Ai small at the left, the card; no bubble) and tall
 * phones (25.6 x 25.7 em: Ai and his line on top, the card under them).
 * In step 2 Tom's phone is held in front of the card's right side, a
 * deliberate overlap (it is the only one).
 * Motion is transform and opacity only; the steps are the pt-sN classes and
 * data-step (part.js), the beats inside a step are transition delays and
 * keyframes, and the rb-* classes (run.js). Elements marked .rn-mv take the
 * quick and snap modes at the end of this file; every one-shot effect also
 * says :not(.rn-quick).
 *
 * Colours say what a thing is: clay the job (Run's tone: the card's band,
 * the page names, the plan), sand time (the fitting minutes, the ball that
 * runs the statuses, the next service), mist a text to the customer, sage
 * done or included (a tick, a part that fits, a status reached, the free
 * service).
 *
 * Spacing (Dimitar, 02/10/2026, on Get paid: "things overlap"): the objects
 * never touch, with at least 8 px of air on desktop and 6 on phones, the
 * bobs and the hop included; every text fits its box inside its padding.
 * Checked with tools/browser/paytrack_overlap_check.js.
 */

/* ---------- the stage: the unit, the depth ------------------------------- */
.pt-part-run { container-type: inline-size; }
.pt-part-run .pt-part-stage { position: relative; font-size: 14px;
  font-size: max(12.5px, min(16px, calc(100cqw / 35), 2vh));
  perspective: 1100px; perspective-origin: 58% 42%; }
.pt-part-run .pt-part-tilt { transform-style: preserve-3d; transition: transform .6s cubic-bezier(.2, .8, .3, 1); }
.pt-part-run .rn-set { position: relative; width: 35em; height: 21em; margin: 0 auto; transform-style: preserve-3d; line-height: 1.3;
  /* the quote's grid: the minutes and the amount columns, their gap, the
     line's side padding, a line's height; and a status row's height (the
     big ticks are 1.9em) */
  --c2: 4.6em; --c3: 4.8em; --cg: .4em; --lp: .5em; --ln: 1.72em; --row: 2em; }
.pt-part-run .rn-set i { display: block; font-style: normal; }

/* The light in the room: a clay pool under the card, a cool one under Ai.
   No surface edges anywhere (the layers are invisible). Pseudo-elements, so
   no check counts them as objects of the scene. The card's own shadow on the
   floor shrinks as it rises (its bob's clock). */
.pt-part-run .rn-set::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(36% 34% at 66% 82%, rgba(208, 154, 124, .10), rgba(208, 154, 124, 0) 72%),
    radial-gradient(18% 20% at 24% 90%, rgba(147, 183, 198, .10), rgba(147, 183, 198, 0) 72%);
  transform: translateZ(-3em); }
.pt-part-run .rn-set::after { content: ""; position: absolute; left: 13.8em; width: 19.8em; top: 19.6em; height: 1.3em; pointer-events: none;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));
  transform: translateZ(-.6em); animation: rn-shadow 6s ease-in-out infinite; }
@keyframes rn-shadow { 0%, 100% { opacity: 1; transform: translateZ(-.6em) scale(1); } 50% { opacity: .72; transform: translateZ(-.6em) scale(.9); } }

/* ---------- Ai and his line ------------------------------------------------ */
/* He stands left of the card, a little in front of it. His own bob is 6 px
   here (not site.css's 12), so his line above keeps its air. */
.pt-part-run .rn-ai { position: absolute; left: 4.8em; bottom: .5em; width: 6.2em; transform: translateZ(1.4em); pointer-events: none; }
.pt-part-run .rn-ai .pt-char { width: 100%; }
.pt-part-run .rn-ai .pt-char-ai { animation-name: rn-hover; }
@keyframes rn-hover { 0%, 100% { translate: 0 0; } 50% { translate: 0 -6px; } }
.pt-part-run .rn-ai-in { transform-origin: 50% 100%; }
/* A hop when the plan is on (run.js; site.css also swells him with .is-hop). */
.pt-part-run.rb-hop:not(.rn-quick) .rn-ai-in { animation: rn-hop .62s cubic-bezier(.3, .7, .4, 1); }
@keyframes rn-hop { 0%, 62%, 100% { transform: translateY(0); } 35% { transform: translateY(-1em); } 78% { transform: translateY(-.22em); } }

/* His line, above him, its tail down between his antennae (his middle is
   7.9 em from the set's left, the bubble's right edge 10.8, so 3.37 of the
   bubble's own em). Air kept for his bob and his lean towards the pointer
   (up to 13 px sideways and 9 up, js/stage.js): about 2.8 em above him,
   1.5 em to the card. */
.pt-part-run .rn-say { position: absolute; left: .4em; top: 6.3em; width: 10.4em; transform: translateZ(1em); }
.pt-part-run .rn-say .pt-bubble { max-width: none; margin: 0; padding: .72em .95em; font-size: .86em; line-height: 1.4;
  border-radius: 1.3em 1.3em .45em 1.3em; transform-origin: 75% 100%; }
.pt-part-run .rn-say .pt-bubble::before { left: auto; right: calc(3.37em - 6px); bottom: -6px; clip-path: polygon(100% 0, 100% 100%, 0 100%); }
html:not(.js) .pt-part-run .pt-bubble { opacity: 1; transform: none; }

/* ---------- the job card: floats, turned towards Ai ------------------------- */
.pt-part-run .rn-float { position: absolute; left: 12.5em; top: .3em; width: 22.3em; height: 20em; transform-style: preserve-3d;
  animation: rn-bob 6s ease-in-out infinite; }
@keyframes rn-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-.35em); } }
/* The card: raised, a thin clay band along the top (Run's tone; a
   background, so it follows the rounded corners), a soft static shadow.
   Flat inside: its pages turn in their own perspective, drawn on the card. */
.pt-part-run .rn-card { position: absolute; inset: 0; border-radius: .95em; color: var(--pt-bone);
  background:
    linear-gradient(var(--pt-clay), var(--pt-clay)) 0 0 / 100% .3em no-repeat,
    linear-gradient(180deg, rgba(236, 230, 218, .05), rgba(236, 230, 218, 0) 45%),
    var(--pt-raised);
  box-shadow: 0 1.8em 2.6em -1.2em rgba(0, 0, 0, .75), 0 .2em .5em rgba(0, 0, 0, .25), inset 0 0 0 1px rgba(236, 230, 218, .07);
  transform: rotateY(-9deg) rotateX(3deg); }
/* At every page turn it swings a little (two names in turn, so the swing
   starts again each time; from and to are its own pose). */
.pt-part-run[data-step="0"]:not(.rn-quick) .rn-card,
.pt-part-run[data-step="3"]:not(.rn-quick) .rn-card { animation: rn-swing-a 1s ease-in-out; }
.pt-part-run[data-step="2"]:not(.rn-quick) .rn-card,
.pt-part-run[data-step="4"]:not(.rn-quick) .rn-card { animation: rn-swing-b 1s ease-in-out; }
@keyframes rn-swing-a { 40% { transform: rotateY(-14deg) rotateX(4.5deg) translateZ(-.3em); } }
@keyframes rn-swing-b { 40% { transform: rotateY(-14deg) rotateX(4.5deg) translateZ(-.3em); } }

/* The job, on every page: its number, the customer, the machine. */
.pt-part-run .rn-head { position: absolute; left: 1em; right: 1em; top: 1.05em; height: 3.2em; display: grid;
  grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; align-content: start; column-gap: .6em; row-gap: .32em;
  box-shadow: 0 1px 0 rgba(236, 230, 218, .08); }
.pt-part-run .rn-job { grid-area: 1 / 1; justify-self: start; position: relative; font: 500 .95em/1.2 var(--pt-head); letter-spacing: -.01em;
  color: var(--pt-bone); white-space: nowrap; }
.pt-part-run .rn-job > span { position: relative; }
/* The job opens when its tag is scanned (step 3): a clay ring around its number. */
.pt-part-run .rn-open { position: absolute; left: -.45em; right: -.45em; top: -.3em; bottom: -.3em; border-radius: .6em;
  border: .12em solid var(--pt-clay); opacity: 0; pointer-events: none; }
.pt-part-run .rn-who { grid-area: 1 / 2; display: flex; align-items: center; gap: .45em; white-space: nowrap; }
.pt-part-run .rn-who > span { font: 600 .84em/1.2 var(--pt-text); color: var(--pt-bone); }
.pt-part-run .rn-av { display: flex; align-items: center; justify-content: center; width: 2.25em; height: 2.25em; border-radius: 50%;
  font: 600 .8em/1 var(--pt-head); color: var(--pt-night); background: var(--pt-mist); }
.pt-part-run .rn-unit { grid-area: 2 / 1 / 3 / 3; display: flex; align-items: baseline; gap: .55em; min-width: 0; white-space: nowrap; }
.pt-part-run .rn-model { font: 600 .84em/1.2 var(--pt-text); color: var(--pt-bone); }
.pt-part-run .rn-sn-l { font: 500 .8em/1.2 var(--pt-text); color: var(--pt-lichen); }

/* The pages, stacked in one cell under the job: the one in play is up, the
   ones before it turned away above, the ones after it waiting below. */
.pt-part-run .rn-pages { position: absolute; left: 1em; right: 1em; top: 4.6em; bottom: .9em; display: grid; grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  perspective: 40em; transition: opacity .35s ease; }
.pt-part-run .rn-page { grid-area: 1 / 1; display: flex; flex-direction: column; min-width: 0; min-height: 0;
  opacity: 0; transform: translate3d(0, .9em, 0) rotateX(-20deg); transition: opacity .3s ease, transform .6s var(--pt-spring); }
.pt-part-run[data-step="-1"] .rn-pg-quote,
.pt-part-run[data-step="0"] .rn-pg-quote,
.pt-part-run[data-step="1"] .rn-pg-quote,
.pt-part-run[data-step="2"] .rn-pg-status,
.pt-part-run[data-step="3"] .rn-pg-tags,
.pt-part-run[data-step="4"] .rn-pg-plan { opacity: 1; transform: none; }
.pt-part-run.pt-s2 .rn-pg-quote,
.pt-part-run.pt-s3 .rn-pg-status,
.pt-part-run.pt-s4 .rn-pg-tags { transform: translate3d(0, -.7em, 0) rotateX(20deg); }
/* The new page comes up just after the old one has gone. */
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-pg-status,
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-pg-tags,
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-pg-plan { transition-delay: .2s; }

/* Every page: its name in the job's clay, a chip or a note on the right. */
.pt-part-run .rn-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: .6em;
  height: 2.1em; padding-bottom: .5em; margin-bottom: .3em; box-shadow: 0 1px 0 rgba(236, 230, 218, .06); }
.pt-part-run .rn-t { font: 700 .8em/1.2 var(--pt-text); letter-spacing: .1em; text-transform: uppercase; color: var(--pt-clay); white-space: nowrap; }
.pt-part-run .rn-note { font: 500 .8em/1.2 var(--pt-text); color: var(--pt-lichen); white-space: nowrap; }

/* ---------- the parts every page uses -------------------------------------- */
/* Chips: a pill, its words in their own span (above the shine). */
.pt-part-run .rn-chip { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; gap: .42em; padding: .34em .78em; border-radius: 999px;
  font: 600 .8em/1.2 var(--pt-text); white-space: nowrap; }
.pt-part-run .rn-chip > span { position: relative; }
.pt-part-run .rn-chip b { font-weight: 700; }
.pt-part-run .rn-sage { background: rgba(157, 184, 159, .17); color: var(--pt-sage); }
.pt-part-run .rn-clay { background: rgba(208, 154, 124, .17); color: var(--pt-clay); }
/* Pops: a ring that spreads and fades, a shine clipped to the chip (the
   chips of llm.php). */
.pt-part-run .rn-pop::before { content: ""; position: absolute; inset: -.24em; border-radius: inherit; border: .12em solid currentColor;
  opacity: 0; pointer-events: none; }
.pt-part-run .rn-shine { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; }
.pt-part-run .rn-shine::after { content: ""; position: absolute; top: -20%; bottom: -20%; left: 0; width: 45%;
  background: linear-gradient(105deg, rgba(236, 230, 218, 0), rgba(236, 230, 218, .42) 50%, rgba(236, 230, 218, 0));
  transform: translateX(-120%); }
@keyframes rn-ring { 0% { opacity: .85; transform: scale(.94); } 100% { opacity: 0; transform: scale(1.18, 1.6); } }
@keyframes rn-ring-sq { 0% { opacity: .85; transform: scale(.97); } 100% { opacity: 0; transform: scale(1.06, 1.35); } }
@keyframes rn-shine { 0% { transform: translateX(-120%); } 100% { transform: translateX(300%); } }
/* The sage tick, drawn in CSS (sized in its chip's em). */
.pt-part-run .rn-tick { position: relative; flex: 0 0 auto; width: 1.1em; height: 1.1em; border-radius: 50%; background: var(--pt-sage); }
.pt-part-run .rn-tick::after { content: ""; position: absolute; left: .39em; top: .2em; width: .28em; height: .52em;
  border: solid var(--pt-night); border-width: 0 .13em .13em 0; transform: rotate(45deg); }

/* ---------- steps 0 and 1, page quote ------------------------------------- */
/* The quote's lines on one grid: the part, its fitting minutes, its amount.
   Slot j of the page is j lines down (--ln), so the catalogue's rows and
   the lines they turn into share their places. */
.pt-part-run .rn-lines { position: relative; flex: 0 0 auto; perspective: 30em; }
.pt-part-run .rn-ln { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) var(--c2) var(--c3); column-gap: var(--cg); align-items: center;
  height: var(--ln); padding: 0 var(--lp); box-shadow: inset 0 -1px 0 rgba(236, 230, 218, .05); }
.pt-part-run .rn-n { grid-column: 1; min-width: 0; font: 500 .86em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap; }
.pt-part-run .rn-amt { grid-column: 3; justify-self: end; font: 600 .86em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.pt-part-run .rn-ln-gst .rn-n { color: var(--pt-lichen); }
.pt-part-run .rn-ln-tot { height: 2.1em; margin-top: .2em; border-radius: .55em; box-shadow: inset 0 1px 0 rgba(236, 230, 218, .14); color: var(--pt-clay); }
.pt-part-run .rn-ln-tot .rn-n { font-weight: 700; }
.pt-part-run .rn-ln-tot .rn-amt { font: 500 .92em/1.2 var(--pt-head); letter-spacing: -.01em; }
/* The fitting minutes: a sand chip in the middle column. */
.pt-part-run .rn-min { position: relative; grid-column: 2; justify-self: center; display: inline-flex; align-items: center; padding: .22em .62em .24em; border-radius: 999px;
  background: rgba(217, 197, 154, .15); color: var(--pt-sand); font: 600 .8em/1.2 var(--pt-text); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pt-part-run .rn-min > span { position: relative; }
.pt-part-run .rn-min-sum { background: rgba(217, 197, 154, .24); }

/* Step 0: the catalogue opens over the empty lines, a filter to the job's
   model pops, the parts that do not fit dim and fall away, Belt slides up
   under Bracket Cam, and the two drop into the quote with their prices.
   Keyframes from the step's start; the end of each one is its resting
   state (hidden), so a jump or the next step lands the same. */
.pt-part-run .rn-cat { position: absolute; left: 0; right: 0; top: var(--ln); height: calc(var(--ln) * 5); pointer-events: none; transform-style: preserve-3d; }
.pt-part-run .rn-cat::before { content: ""; position: absolute; inset: -.18em -.22em; border-radius: .65em; background: #1D2722;
  box-shadow: 0 .9em 1.8em rgba(0, 0, 0, .5), inset 0 0 0 1px rgba(236, 230, 218, .08); opacity: 0; transform-origin: 50% 0; }
.pt-part-run .rn-o { position: absolute; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; gap: .5em;
  height: var(--ln); padding: 0 var(--lp); border-radius: .45em; opacity: 0; }
.pt-part-run .rn-o::before { content: ""; position: absolute; inset: .14em 0; border-radius: inherit; background: rgba(157, 184, 159, .16); opacity: 0; }
.pt-part-run .rn-o b { position: relative; font: 600 .86em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap; }
.pt-part-run .rn-o .rn-tick { font-size: .8em; opacity: 0; }
.pt-part-run .rn-o1 { top: 0; --d: .3s; }
.pt-part-run .rn-o2 { top: var(--ln); --d: .36s; }
.pt-part-run .rn-o3 { top: calc(var(--ln) * 2); --d: .42s; }
.pt-part-run .rn-o4 { top: calc(var(--ln) * 3); --d: .48s; }
.pt-part-run .rn-o5 { top: calc(var(--ln) * 4); --d: .54s; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-cat::before { animation: rn-cat 2.9s linear both; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-o-no { animation: rn-o-out 1.6s linear var(--d) both; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-o1 { animation: rn-o-cam 2.55s linear var(--d) both; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-o3 { animation: rn-o-belt 2.45s linear var(--d) both; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-o-fit::before { animation: rn-fade-in .35s ease 1.85s both; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-o-fit .rn-tick { animation: rn-pop-in .45s var(--pt-spring) 1.85s both; }
/* The card behind the rows: open by .5 s, gone by 2.85 s. */
@keyframes rn-cat { 0%, 8% { opacity: 0; transform: scaleY(.94); } 17%, 87% { opacity: 1; transform: none; } 98%, 100% { opacity: 0; transform: none; } }
/* A part that does not fit: in by its delay plus .3 s, dims and falls from 1.1 s after it. */
@keyframes rn-o-out {
  0% { opacity: 0; transform: translateY(-.4em); animation-timing-function: ease-out; }
  19%, 68% { opacity: 1; transform: none; animation-timing-function: ease-in-out; }
  78% { opacity: .45; transform: translateY(.1em); animation-timing-function: cubic-bezier(.5, 0, .9, .6); }
  100% { opacity: 0; transform: translateY(1.6em) rotateX(-70deg); }
}
/* Bracket Cam: in, ticked, then it fades as its line takes its place (2.6 s). */
@keyframes rn-o-cam {
  0% { opacity: 0; transform: translateY(-.4em); animation-timing-function: ease-out; }
  12%, 89% { opacity: 1; transform: none; }
  98%, 100% { opacity: 0; transform: none; }
}
/* Belt: in, ticked, slides up a line under Bracket Cam (1.6 to 1.9 s after
   its delay), then fades as its line takes its place. */
@keyframes rn-o-belt {
  0% { opacity: 0; transform: translateY(-.4em); animation-timing-function: ease-out; }
  12.5%, 64% { opacity: 1; transform: none; animation-timing-function: cubic-bezier(.3, .7, .3, 1); }
  77%, 89% { opacity: 1; transform: translateY(calc(var(--ln) * -1)); }
  98%, 100% { opacity: 0; transform: translateY(calc(var(--ln) * -1)); }
}
@keyframes rn-fade-in { 0% { opacity: 0; } 100% { opacity: 1; } }
@keyframes rn-pop-in { 0% { opacity: 0; transform: scale(.3); } 100% { opacity: 1; transform: none; } }

/* The filter: a sage chip, the job's model in it. */
.pt-part-run .rn-filter { opacity: 0; transform: scale(.55); transform-origin: 100% 50%; transition: opacity .25s ease, transform .55s var(--pt-spring); }
.pt-part-run.pt-s0 .rn-filter { opacity: 1; transform: none; }
.pt-part-run .rn-filter .rn-tick { width: 1.05em; height: 1.05em; }
.pt-part-run .rn-filter .rn-tick::after { left: .37em; top: .19em; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-filter { transition-delay: 1.1s; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-filter::before { animation: rn-ring .7s ease-out 1.2s forwards; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-filter .rn-shine::after { animation: rn-shine .9s ease-in-out 1.35s; }

/* The two parts' lines: in at 2.6 s, where their rows were; the amounts slide in after. */
.pt-part-run .rn-ln-cam,
.pt-part-run .rn-ln-belt { opacity: 0; transition: opacity .3s ease; }
.pt-part-run.pt-s0 .rn-ln-cam,
.pt-part-run.pt-s0 .rn-ln-belt { opacity: 1; }
.pt-part-run .rn-ln-cam .rn-amt,
.pt-part-run .rn-ln-belt .rn-amt { opacity: 0; transform: translateX(.7em); transition: opacity .3s ease, transform .5s var(--pt-spring); }
.pt-part-run.pt-s0 .rn-ln-cam .rn-amt,
.pt-part-run.pt-s0 .rn-ln-belt .rn-amt { opacity: 1; transform: none; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-ln-cam,
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-ln-belt { transition-delay: 2.55s; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-ln-cam .rn-amt { transition-delay: 2.75s; }
.pt-part-run:not(.rn-quick)[data-step="0"] .rn-ln-belt .rn-amt { transition-delay: 2.85s; }

/* Step 1: each part's fitting minutes pop, two drops carry them down into
   the labour line, whose minutes and amount roll up (run.js), then GST and
   the total land. */
.pt-part-run .rn-min-cam,
.pt-part-run .rn-min-belt { opacity: 0; transform: scale(.5); transition: opacity .25s ease, transform .5s var(--pt-spring); }
.pt-part-run.pt-s1 .rn-min-cam,
.pt-part-run.pt-s1 .rn-min-belt { opacity: 1; transform: none; }
.pt-part-run .rn-ln-lab,
.pt-part-run .rn-ln-gst,
.pt-part-run .rn-ln-tot { opacity: 0; transform: translateY(.45em); transition: opacity .3s ease, transform .5s var(--pt-spring); }
.pt-part-run.pt-s1 .rn-ln-lab,
.pt-part-run.pt-s1 .rn-ln-gst,
.pt-part-run.pt-s1 .rn-ln-tot { opacity: 1; transform: none; }
.pt-part-run .rn-min-sum { transform: scale(.6); transition: transform .5s var(--pt-spring); }
.pt-part-run.pt-s1 .rn-min-sum { transform: none; }
/* The drops: from the middle of each minutes chip to the labour chip's. */
.pt-part-run .rn-fly { position: absolute; right: calc(var(--lp) + var(--c3) + var(--cg) + var(--c2) / 2 - .3em); top: calc(var(--ln) * 1.5 - .3em);
  width: .6em; height: .6em; border-radius: 50%; background: var(--pt-sand); box-shadow: 0 0 .6em rgba(217, 197, 154, .8); opacity: 0; pointer-events: none; }
.pt-part-run .rn-fly2 { top: calc(var(--ln) * 2.5 - .3em); }
@keyframes rn-drop1 {
  0% { opacity: 0; transform: scale(.4); }
  20% { opacity: 1; transform: translate3d(.5em, calc(var(--ln) * .4), .5em) scale(1); }
  85% { opacity: 1; }
  100% { opacity: 0; transform: translate3d(0, calc(var(--ln) * 2), 0) scale(.5); }
}
@keyframes rn-drop2 {
  0% { opacity: 0; transform: scale(.4); }
  25% { opacity: 1; transform: translate3d(.4em, calc(var(--ln) * .25), .4em) scale(1); }
  85% { opacity: 1; }
  100% { opacity: 0; transform: translate3d(0, var(--ln), 0) scale(.5); }
}
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-min-cam { transition-delay: .35s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-min-belt { transition-delay: .6s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-ln-lab { transition-delay: .95s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-fly1 { animation: rn-drop1 .6s cubic-bezier(.45, .05, .55, .95) 1.05s both; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-fly2 { animation: rn-drop2 .5s cubic-bezier(.45, .05, .55, .95) 1.15s both; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-min-sum { transition-delay: 1.55s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-min-sum::before { animation: rn-ring .7s ease-out 1.6s forwards; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-min-sum .rn-shine::after { animation: rn-shine .9s ease-in-out 1.75s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-ln-gst { transition-delay: 2.15s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-ln-tot { transition-delay: 2.45s; }
.pt-part-run:not(.rn-quick)[data-step="1"] .rn-ln-tot::before { animation: rn-ring-sq .8s ease-out 2.6s forwards; }

/* ---------- step 2, page status: a text at every step ---------------------- */
/* The job's statuses down a rail; a sand ball runs it and each status
   lights as the ball reaches it (row k at .5 + .72k s, --k below, in step
   with the ball's keyframes). A big sage tick lands on the quote given
   (Quoted) and on its approval (Approved); a text leaves the card for Tom's
   phone when the quote is given and when the service is done (Ready): a
   small SMS pill pops by the status and arcs into the phone, where the text
   lands and the phone buzzes (Dimitar, 02/10/2026: "make a big tick on the
   quote given - and accepted - animate sms to customer", "sms on quote
   given and service completed"). */
.pt-part-run .rn-rows { position: relative; flex: 0 0 auto; display: flex; flex-direction: column; }
.pt-part-run .rn-row { position: relative; display: grid; grid-template-columns: 1.1em 5.1em 2.1em auto; column-gap: .45em; align-items: center; justify-content: start;
  height: var(--row); --t: calc(.5s + .72s * var(--k, 0)); }
.pt-part-run .rn-r2 { --k: 1; }
.pt-part-run .rn-r3 { --k: 2; }
.pt-part-run .rn-r4 { --k: 3; }
.pt-part-run .rn-r5 { --k: 4; }
.pt-part-run .rn-r6 { --k: 5; }
/* The rail through the dots' middles, and its lit part, which grows with the ball. */
.pt-part-run .rn-track,
.pt-part-run .rn-trail { position: absolute; left: .49em; top: calc(var(--row) / 2); width: .12em; height: calc(var(--row) * 5); border-radius: .06em; }
.pt-part-run .rn-track { background: rgba(236, 230, 218, .12); }
.pt-part-run .rn-trail { background: var(--pt-sage); transform: scaleY(0); transform-origin: 50% 0; }
.pt-part-run.pt-s2 .rn-trail { transform: none; }
.pt-part-run .rn-dot { position: relative; justify-self: center; width: .8em; height: .8em; border-radius: 50%; background: var(--pt-raised);
  box-shadow: inset 0 0 0 .14em rgba(236, 230, 218, .28); }
.pt-part-run .rn-dot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--pt-sage); box-shadow: 0 0 .5em rgba(157, 184, 159, .6);
  opacity: 0; transform: scale(.4); transition: opacity .25s ease, transform .45s var(--pt-spring); }
.pt-part-run.pt-s2 .rn-dot::after { opacity: 1; transform: none; }
.pt-part-run .rn-st { font: 600 .84em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap; opacity: .42; transition: opacity .3s ease; }
.pt-part-run.pt-s2 .rn-st { opacity: 1; }
/* The big tick: the quote given, the quote accepted. It lands spinning a
   little, and a ring spreads from it. */
.pt-part-run .rn-big { position: relative; grid-column: 3; justify-self: center; width: 1.9em; height: 1.9em; border-radius: 50%; background: var(--pt-sage);
  box-shadow: 0 0 .9em rgba(157, 184, 159, .45);
  opacity: 0; transform: scale(.3) rotate(-30deg); transition: opacity .2s ease, transform .6s var(--pt-spring); }
.pt-part-run .rn-big::after { content: ""; position: absolute; left: .7em; top: .34em; width: .5em; height: .92em;
  border: solid var(--pt-night); border-width: 0 .22em .22em 0; transform: rotate(45deg); }
.pt-part-run .rn-big::before { content: ""; position: absolute; inset: -.3em; border-radius: 50%; border: .13em solid var(--pt-sage); opacity: 0; pointer-events: none; }
.pt-part-run.pt-s2 .rn-big { opacity: 1; transform: none; }
/* Where an SMS pops: the fourth column of its status, a pill's room (the
   pill itself is in front of the card, with the phone: see below). */
.pt-part-run .rn-sms-at { grid-column: 4; width: 3.6em; height: 1.4em; }
/* The ball: on the first dot, then dot to dot, each move ending as that row lights. */
.pt-part-run .rn-ball { position: absolute; left: .1em; top: calc(var(--row) / 2 - .45em); width: .9em; height: .9em; border-radius: 50%;
  background: radial-gradient(circle at 35% 32%, #FFF6E2, var(--pt-sand) 55%, #A88E5F); box-shadow: 0 0 .7em rgba(217, 197, 154, .55);
  opacity: 0; transform: scale(.4); }
.pt-part-run.pt-s2 .rn-ball { opacity: 1; transform: translateY(calc(var(--row) * 5)); }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-dot::after,
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-st { transition-delay: var(--t); }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-big { transition-delay: calc(var(--t) + .06s); }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-big::before { animation: rn-ring-o .75s ease-out calc(var(--t) + .16s) forwards; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-ball { animation: rn-ball 3.95s ease-in-out .15s both; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-trail { animation: rn-trail 3.95s ease-in-out .15s both; }
/* (t - .15 s) / 3.95 s: in at .5 s, then moves of .35 s ending at 1.22, 1.94, 2.66, 3.38, 4.1 s. */
@keyframes rn-ball {
  0% { opacity: 0; transform: scale(.4); }
  8.86%, 18.23% { opacity: 1; transform: none; }
  27.09%, 36.46% { opacity: 1; transform: translateY(var(--row)); }
  45.32%, 54.68% { opacity: 1; transform: translateY(calc(var(--row) * 2)); }
  63.54%, 72.91% { opacity: 1; transform: translateY(calc(var(--row) * 3)); }
  81.77%, 91.14% { opacity: 1; transform: translateY(calc(var(--row) * 4)); }
  100% { opacity: 1; transform: translateY(calc(var(--row) * 5)); }
}
@keyframes rn-trail {
  0%, 18.23% { transform: scaleY(0); }
  27.09%, 36.46% { transform: scaleY(.2); }
  45.32%, 54.68% { transform: scaleY(.4); }
  63.54%, 72.91% { transform: scaleY(.6); }
  81.77%, 91.14% { transform: scaleY(.8); }
  100% { transform: none; }
}
@keyframes rn-ring-o { 0% { opacity: .85; transform: scale(.9); } 100% { opacity: 0; transform: scale(1.55); } }

/* Tom's phone: held in front of the card's empty right side while the
   statuses play (step 2 only), clear of the card's surface in depth; it
   comes in from the right and goes the same way. The texts land in it in
   order (the first as the quote's SMS arrives, the second as the Ready
   one does), and it buzzes at each. */
.pt-part-run .rn-phone { position: absolute; right: 1.1em; top: 7.3em; width: 6.8em; height: 11.2em; pointer-events: none;
  opacity: 0; transform: translate3d(2.4em, .6em, 4.6em) rotateY(-38deg) rotateX(4deg); transition: opacity .35s ease, transform .8s var(--pt-spring); }
.pt-part-run[data-step="2"] .rn-phone { opacity: 1; transform: translateZ(2.2em) rotateY(-14deg) rotateX(4deg); }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-phone { transition-delay: .25s; }
.pt-part-run .rn-phone-body { position: absolute; inset: 0; padding: .3em; border-radius: 1.15em;
  background: linear-gradient(160deg, #2A3530, #18201C 38%, #151C19);
  box-shadow: inset 0 0 0 1px rgba(236, 230, 218, .1), inset 0 1px 0 rgba(236, 230, 218, .16), 0 1.2em 2.2em -.4em rgba(0, 0, 0, .7); }
.pt-part-run .rn-phone-in { position: relative; height: 100%; overflow: hidden; border-radius: .9em; background: #0A0E0C; }
.pt-part-run .rn-notch { position: absolute; left: 50%; top: .45em; width: 2em; height: .55em; margin-left: -1em; border-radius: 1em; background: #000; }
.pt-part-run .rn-thread { position: absolute; left: .32em; right: .32em; top: 1.55em; display: flex; flex-direction: column; align-items: flex-start; gap: .42em; }
.pt-part-run .rn-in { max-width: 100%; padding: .32em .6em .36em; border-radius: .85em .85em .85em .28em; background: rgba(147, 183, 198, .22);
  font: 500 .8em/1.25 var(--pt-text); color: var(--pt-bone);
  opacity: 0; transform: translateY(.5em) scale(.8); transform-origin: 0 100%; transition: opacity .25s ease, transform .5s var(--pt-spring); }
.pt-part-run.pt-s2 .rn-in { opacity: 1; transform: none; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-in1 { transition-delay: 3.3s; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-in2 { transition-delay: 4.75s; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-phone-body { animation: rn-buzz 1.85s linear 3.25s; }
/* The SMS: a mist pill that pops by its status (Quoted at 2.14 s, Ready at
   3.58 s), then arcs out of the card and into the phone, rising in front of
   it, and fades as its text lands there. run.js puts it on its status
   (left, top) and sets the way to its text (--tx, --ty), in the pill's own
   em, at the step's start; without that it waits, unseen, by the card. */
.pt-part-run .rn-sms { position: absolute; left: 11.6em; top: 12em; display: inline-flex; align-items: center; gap: .42em; padding: .26em .66em .28em .5em;
  border-radius: 999px; background: rgba(147, 183, 198, .26); box-shadow: 0 0 .9em rgba(147, 183, 198, .4); color: var(--pt-mist);
  font: 700 .8em/1.2 var(--pt-text); letter-spacing: .06em; white-space: nowrap; opacity: 0; pointer-events: none; }
.pt-part-run .rn-sms-i { position: relative; flex: 0 0 auto; width: 1em; height: .78em; border-radius: .26em; background: currentColor; }
.pt-part-run .rn-sms-i::after { content: ""; position: absolute; left: .16em; top: 100%; border: .15em solid transparent; border-top-color: currentColor; border-left-color: currentColor; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-sms1 { animation: rn-sms 1.25s linear 2.14s both; }
.pt-part-run:not(.rn-quick)[data-step="2"] .rn-sms2 { animation: rn-sms 1.25s linear 3.58s both; }
@keyframes rn-sms {
  0% { opacity: 0; transform: translate3d(-.6em, 0, .8em) scale(.6); }
  14%, 38% { opacity: 1; transform: translate3d(0, 0, .8em); animation-timing-function: cubic-bezier(.45, .05, .55, .95); }
  70% { opacity: 1; transform: translate3d(calc(var(--tx, 9em) * .55), calc(var(--ty, 0em) * .5 - 1.6em), 4em) scale(1.1); animation-timing-function: cubic-bezier(.4, 0, .7, .4); }
  100% { opacity: 0; transform: translate3d(var(--tx, 9em), var(--ty, 0em), 3.2em) scale(.7); }
}
/* Two buzzes, at 3.25 and 4.7 s. */
@keyframes rn-buzz {
  0%, 21.6%, 78.4%, 100% { transform: none; }
  4.3%, 82.7% { transform: translateX(-.08em) rotate(-1.2deg); }
  8.6%, 87% { transform: translateX(.08em) rotate(1.2deg); }
  13%, 91.3% { transform: translateX(-.06em) rotate(-.8deg); }
  17.3%, 95.7% { transform: translateX(.04em) rotate(.5deg); }
}

/* ---------- step 3, page labels: QR job tags and part labels --------------- */
/* The job tag prints (its paper revealed from the top down, a print head's
   light at the edge), drops onto its string and swings; the same code goes
   on the part as a small label; a band of light sweeps the tag's code, and
   the job opens (the ring round its number in the head). */
.pt-part-run .rn-labels { position: relative; flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: space-evenly; gap: 1em; }
.pt-part-run .rn-tagpos { position: relative; flex: 0 0 auto; padding-top: 1em; }
.pt-part-run .rn-string { position: absolute; left: 50%; top: -.2em; width: .1em; height: 1.75em; margin-left: -.05em; border-radius: .05em;
  background: linear-gradient(180deg, rgba(217, 197, 154, 0), rgba(217, 197, 154, .75)); opacity: 0; transition: opacity .3s ease; }
.pt-part-run.pt-s3 .rn-string { opacity: 1; }
.pt-part-run .rn-swing { transform-origin: 50% .85em; }
/* The print: a window that slides down over the paper while the paper
   inside it slides the other way, so the paper stays put and shows from
   the top down. */
.pt-part-run .rn-print { position: relative; overflow: hidden; border-radius: .55em; transform: translateY(-100%); transition: transform 1s cubic-bezier(.4, 0, .4, 1); }
.pt-part-run .rn-print-in { transform: translateY(100%); transition: transform 1s cubic-bezier(.4, 0, .4, 1); }
.pt-part-run.pt-s3 .rn-print,
.pt-part-run.pt-s3 .rn-print-in { transform: none; }
.pt-part-run .rn-head-line { position: absolute; left: 0; right: 0; bottom: 0; height: .22em; border-radius: .11em; background: var(--pt-mist);
  box-shadow: 0 0 .6em .1em rgba(147, 183, 198, .7); opacity: 0; }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-print,
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-print-in { transition-delay: .35s; }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-head-line { animation: rn-headline 1.1s linear .3s both; }
@keyframes rn-headline { 0% { opacity: 0; } 10%, 85% { opacity: 1; } 100% { opacity: 0; } }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-string { transition-delay: 1.3s; }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-swing { animation: rn-swing 1.7s ease-in-out 1.35s; }
@keyframes rn-swing { 0%, 100% { transform: none; } 18% { transform: rotate(7deg); } 42% { transform: rotate(-4.5deg); } 64% { transform: rotate(2.5deg); } 84% { transform: rotate(-1deg); } }
/* The tag: paper, its corners cut, an eyelet at the top. */
.pt-part-run .rn-tag { position: relative; display: flex; flex-direction: column; align-items: center; width: 7.4em; padding: 1.25em .6em .62em;
  border-radius: .55em; background: linear-gradient(180deg, #F1EBDF, #E2DACA); color: #18201C;
  clip-path: polygon(20% 0, 80% 0, 100% 11%, 100% 100%, 0 100%, 0 11%); }
.pt-part-run .rn-hole { position: absolute; left: 50%; top: .5em; width: .7em; height: .7em; margin-left: -.35em; border-radius: 50%;
  background: var(--pt-raised); box-shadow: 0 0 0 .14em #B9A57C; }
.pt-part-run .rn-tag-qr { position: relative; width: 5.6em; height: 5.6em; overflow: hidden; border-radius: .2em; }
.pt-part-run .rn-tag-qr svg,
.pt-part-run .rn-lbl-qr svg { display: block; width: 100%; height: 100%; }
.pt-part-run .rn-tag-t { margin-top: .4em; font: 600 .8em/1.25 var(--pt-head); letter-spacing: -.01em; white-space: nowrap; }
.pt-part-run .rn-tag-s { margin-top: .2em; font: 600 .8em/1.25 var(--pt-text); color: #46524C; white-space: nowrap; }   /* air between the two lines: the card's turn slants their boxes into each other */
/* The light that sweeps the code as it is scanned: an overlay over the
   modules, never a change of them. */
.pt-part-run .rn-band { position: absolute; left: 0; right: 0; top: 0; height: 38%; opacity: 0; transform: translateY(-110%);
  background: linear-gradient(180deg, rgba(147, 183, 198, 0), rgba(147, 183, 198, .5) 50%, rgba(147, 183, 198, 0)); }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-band { animation: rn-band 1s cubic-bezier(.45, .05, .55, .95) 2.75s both; }
@keyframes rn-band { 0% { opacity: 0; transform: translateY(-110%); } 12%, 88% { opacity: 1; } 100% { opacity: 0; transform: translateY(270%); } }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-open { animation: rn-ring-sq .9s ease-out 3.55s forwards; }
/* The part: a parts bag, its zip along the top, its name, the label. */
.pt-part-run .rn-part { position: relative; flex: 0 0 auto; }
.pt-part-run .rn-bag { position: relative; display: flex; flex-direction: column; align-items: center; width: 7.9em; padding: 1.15em .5em .9em;
  border-radius: .45em .45em .9em .9em;
  background:
    repeating-linear-gradient(90deg, rgba(236, 230, 218, .16) 0 .14em, rgba(236, 230, 218, 0) .14em .36em) 0 .42em / 100% .16em no-repeat,
    linear-gradient(170deg, #2E3A33, #1F2924 70%);
  box-shadow: inset 0 1px 0 rgba(236, 230, 218, .12), inset 0 0 0 1px rgba(236, 230, 218, .06), 0 1em 1.6em -.8em rgba(0, 0, 0, .7); }
.pt-part-run .rn-bag-t { font: 600 .84em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap; }
/* The label: the same code, small, stuck on a little askew. */
.pt-part-run .rn-lbl { position: relative; display: flex; flex-direction: column; align-items: center; gap: .2em; margin-top: .55em; padding: .38em .42em .32em;
  border-radius: .35em; background: linear-gradient(180deg, #F1EBDF, #E2DACA); color: #18201C; box-shadow: 0 .3em .6em rgba(0, 0, 0, .35);
  opacity: 0; transform: translateY(-1.2em) rotate(-12deg) scale(1.25); transition: opacity .25s ease, transform .6s var(--pt-spring); }
.pt-part-run.pt-s3 .rn-lbl { opacity: 1; transform: rotate(-4deg); }
.pt-part-run .rn-lbl::after { content: ""; position: absolute; inset: -.3em; border-radius: .55em; border: .12em solid var(--pt-sage); opacity: 0; pointer-events: none; }
.pt-part-run .rn-lbl-qr { width: 3.6em; height: 3.6em; }
.pt-part-run .rn-lbl-t { font: 600 .8em/1.2 var(--pt-text); white-space: nowrap; }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-lbl { transition-delay: 1.9s; }
.pt-part-run:not(.rn-quick)[data-step="3"] .rn-lbl::after { animation: rn-ring-sq .7s ease-out 2.25s forwards; }

/* ---------- step 4, page plan: monthly service plans ----------------------- */
/* Tom's plan, exactly as Dimitar put it (02/10/2026): $49 per month and one
   free service a year, and the one date kept, his next service. In turn:
   Monthly pops on the bar, the cost rises in, the free service slides in,
   then the next service drops in as a calendar leaf and gets a sand ring. */
.pt-part-run .rn-monthly { opacity: 0; transform: scale(.55); transform-origin: 100% 50%; transition: opacity .25s ease, transform .55s var(--pt-spring); }
.pt-part-run.pt-s4 .rn-monthly { opacity: 1; transform: none; }
.pt-part-run .rn-plan { flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: space-between; gap: 1.2em; padding: 0 .4em .5em; }
.pt-part-run .rn-price { display: flex; flex-direction: column; align-items: flex-start; gap: .85em; min-width: 0; }
.pt-part-run .rn-cost { display: flex; align-items: baseline; gap: .45em; white-space: nowrap;
  opacity: 0; transform: translateY(.6em); transition: opacity .3s ease, transform .55s var(--pt-spring); }
.pt-part-run .rn-cost b { font: 500 2.1em/1.1 var(--pt-head); letter-spacing: -.03em; color: var(--pt-bone); font-variant-numeric: tabular-nums; }
.pt-part-run .rn-cost small { font: 600 .84em/1.2 var(--pt-text); color: var(--pt-lichen); }
.pt-part-run .rn-free { display: flex; align-items: center; gap: .5em; padding: .42em .85em .44em .5em; border-radius: 999px; background: rgba(157, 184, 159, .14);
  font: 600 .84em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap;
  opacity: 0; transform: translateX(-.6em); transition: opacity .3s ease, transform .55s var(--pt-spring); }
.pt-part-run .rn-free .rn-tick { width: 1.15em; height: 1.15em; }
.pt-part-run .rn-free .rn-tick::after { left: .41em; top: .22em; }
.pt-part-run.pt-s4 .rn-cost,
.pt-part-run.pt-s4 .rn-free { opacity: 1; transform: none; }
.pt-part-run .rn-next { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: .55em; perspective: 22em; }
.pt-part-run .rn-lbl-n { font: 600 .8em/1.2 var(--pt-text); letter-spacing: .02em; color: var(--pt-lichen); white-space: nowrap;
  opacity: 0; transition: opacity .3s ease; }
.pt-part-run.pt-s4 .rn-lbl-n { opacity: 1; }
.pt-part-run .rn-date { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .18em;
  width: 5.6em; height: 6em; border-radius: .75em;
  background: linear-gradient(rgba(217, 197, 154, .5), rgba(217, 197, 154, .5)) 0 0 / 100% .22em no-repeat, rgba(236, 230, 218, .055);
  box-shadow: inset 0 0 0 1px rgba(236, 230, 218, .08);
  opacity: 0; transform: rotateX(-80deg); transform-origin: 50% 0; transition: opacity .3s ease, transform .6s var(--pt-spring); }
.pt-part-run.pt-s4 .rn-date { opacity: 1; transform: none; }
.pt-part-run .rn-date small { font: 600 .8em/1.15 var(--pt-text); color: var(--pt-lichen); white-space: nowrap; }
.pt-part-run .rn-date small:first-child { letter-spacing: .08em; text-transform: uppercase; color: var(--pt-sand); }
.pt-part-run .rn-date b { font: 500 1.45em/1.1 var(--pt-head); letter-spacing: -.02em; color: var(--pt-bone); }
.pt-part-run .rn-date::after { content: ""; position: absolute; inset: -.3em; border-radius: .95em; border: .13em solid var(--pt-sand); opacity: 0; transform: scale(.9);
  transition: opacity .3s ease, transform .5s var(--pt-spring); pointer-events: none; }
.pt-part-run.pt-s4 .rn-date::after { opacity: 1; transform: none; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-monthly { transition-delay: .5s; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-monthly::before { animation: rn-ring .7s ease-out .6s forwards; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-monthly .rn-shine::after { animation: rn-shine .9s ease-in-out .75s; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-cost { transition-delay: .9s; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-free { transition-delay: 1.25s; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-lbl-n,
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-date { transition-delay: 1.6s; }
.pt-part-run:not(.rn-quick)[data-step="4"] .rn-date::after { transition-delay: 2.15s; }

/* ---------- the rewind: the pages fade, the set stays ----------------------- */
.pt-part-run.is-rewind .rn-pages { opacity: 0; }

/* ---------- the steps under the scene ---------------------------------------- */
/* Desktop: small floating pills in a compact wrap; the one in play is lit in
   clay, the layer's tone. */
.pt-part-run .pt-part-steps { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 12px 0 0; padding: 0; list-style: none; }
.pt-part-run .pt-part-steps li { position: relative; isolation: isolate; display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px 6px 9px; border-radius: 999px; background: rgba(236, 230, 218, .06); color: var(--pt-bone);
  font: 500 var(--pt-fs-say)/1.3 var(--pt-text); cursor: default;
  animation: rn-pill 6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -1.2s); }
.pt-part-run .pt-part-steps li::before { content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--tone, var(--pt-clay)); opacity: .45; transform: scale(.85); transition: opacity .3s ease, transform .4s var(--pt-spring); }
/* The lit state: a brighter ground and the dot's glow, one layer that fades in. */
.pt-part-run .pt-part-steps li::after { content: ""; position: absolute; z-index: -1; inset: 0; border-radius: inherit;
  background: radial-gradient(circle at 12.5px 50%, rgba(208, 154, 124, .55), rgba(208, 154, 124, 0) 15px), rgba(236, 230, 218, .07);
  opacity: 0; transition: opacity .35s ease; }
.pt-part-run .pt-part-steps li > span { opacity: .7; transition: opacity .3s ease; }
.pt-part-run .pt-part-steps li.is-on::before { opacity: 1; transform: scale(1.2); }
.pt-part-run .pt-part-steps li.is-on::after,
.pt-part-run .pt-part-steps li.is-on > span { opacity: 1; }
.pt-part-run .pt-part-steps li:focus-visible { outline: 2px solid var(--pt-sand); outline-offset: 3px; }
@keyframes rn-pill { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }

/* Nothing moves in a layer that is not the one in front (Ai's own loops are
   paused by site.css). */
.pt-layer:not(.is-current) .pt-part-run .rn-float,
.pt-layer:not(.is-current) .pt-part-run .rn-set::after,
.pt-layer:not(.is-current) .pt-part-run .pt-part-steps li { animation-play-state: paused; }

/* ---------- the lg column (992 to 1199, 444 wide): the steps as dots ---------- */
/* Five pills would stack three deep here; as in Control and Campaign
   manager, five dots and the lit step's pill centred under them. Only with
   JS (it lights the step). */
@media (min-width: 992px) and (max-width: 1199.98px) {
  html.js .pt-part-run .pt-part-steps { position: relative; flex-wrap: nowrap; justify-content: center; gap: 0; height: 50px; margin-top: 12px; }
  html.js .pt-part-run .pt-part-steps li { position: static; isolation: auto; justify-content: center; align-items: flex-start;
    width: 22px; height: 14px; padding: 4px 0 0; background: none; animation: none; }
  html.js .pt-part-run .pt-part-steps li::after { display: none; }
  html.js .pt-part-run .pt-part-steps li.is-on::before { transform: scale(1.45); }
  html.js .pt-part-run .pt-part-steps li > span { position: absolute; left: 0; right: 0; top: 21px; width: max-content; margin: 0 auto;
    padding: .4em 1em .45em; border-radius: 999px; background: rgba(236, 230, 218, .08); line-height: 1.3; white-space: nowrap;
    opacity: 0; transform: translateY(5px); pointer-events: none; transition: opacity .3s ease, transform .45s var(--pt-spring); }
  html.js .pt-part-run .pt-part-steps li.is-on > span { opacity: 1; transform: none; pointer-events: auto; }
  html.js .pt-part-run[data-step="-1"] .pt-part-steps li:first-child > span { opacity: .5; transform: none; }
}

/* ---------- phones ------------------------------------------------------------- */
/* Ai small at the left, the card the rest of the width, no line (there is
   no room for it above the card on a short phone); the card's pages keep
   their layout, a little narrower. The steps become one line: five dots and
   the caption of the one in play. */
@media (max-width: 575.98px) {
  .pt-part-run .pt-part-stage { font-size: 12.5px; font-size: max(12.5px, min(13.6px, calc(100cqw / 25.6))); perspective: 820px; perspective-origin: 60% 45%; }
  .pt-part-run .rn-set { width: 25.6em; height: 19.8em; --c2: 4.2em; --c3: 4.4em; --cg: .35em; --lp: .4em; }
  .pt-part-run .rn-set::before { background:
      radial-gradient(44% 34% at 62% 80%, rgba(208, 154, 124, .10), rgba(208, 154, 124, 0) 72%),
      radial-gradient(16% 22% at 8% 86%, rgba(147, 183, 198, .10), rgba(147, 183, 198, 0) 72%); }
  .pt-part-run .rn-set::after { left: 5.8em; width: 19em; top: 18.6em; height: 1.1em; }
  .pt-part-run .rn-say { display: none; }
  .pt-part-run .rn-ai { left: 0; bottom: .45em; width: 3.9em; transform: translateZ(.8em); }
  .pt-part-run .rn-ai .pt-char-ai { animation-name: rn-hover-sm; }
  .pt-part-run .rn-float { left: 4.95em; top: .25em; width: 20.65em; height: 19.3em; }
  .pt-part-run .rn-card { border-radius: .85em; transform: rotateY(-6deg) rotateX(2deg); }
  .pt-part-run .rn-head { left: .75em; right: .75em; top: .85em; height: 3.15em; }
  .pt-part-run .rn-pages { left: .72em; right: .72em; top: 4.3em; bottom: .5em; }
  .pt-part-run .rn-labels { gap: .6em; }
  .pt-part-run .rn-phone { right: .8em; top: 7.1em; width: 5.8em; height: 10em; transform: translate3d(2em, .6em, 4em) rotateY(-36deg) rotateX(3deg); }
  .pt-part-run[data-step="2"] .rn-phone { transform: translateZ(1.8em) rotateY(-12deg) rotateX(3deg); }
}
@keyframes rn-hover-sm { 0%, 100% { translate: 0 0; } 50% { translate: 0 -4px; } }
/* The phone caption: five dots and the lit step's line (with JS; without it
   the pills above stay, all five). */
@media (max-width: 575.98px) {
  html.js .pt-part-run .pt-part-steps { position: relative; flex-wrap: nowrap; justify-content: flex-start; gap: 0; height: 22px; margin-top: 6px; }
  html.js .pt-part-run .pt-part-steps li { position: static; isolation: auto; flex: 0 0 15px; justify-content: center; width: 15px; height: 22px; padding: 0;
    background: none; animation: none; }
  html.js .pt-part-run .pt-part-steps li::after { display: none; }
  html.js .pt-part-run .pt-part-steps li::before { width: 6px; height: 6px; }
  html.js .pt-part-run .pt-part-steps li.is-on::before { transform: scale(1.5); }
  html.js .pt-part-run .pt-part-steps li > span { position: absolute; left: 81px; top: 0; font-size: calc(var(--pt-fs-say) - 1px); line-height: 22px; white-space: nowrap;
    opacity: 0; transform: translateY(6px); pointer-events: none; transition: opacity .3s ease, transform .45s var(--pt-spring); }
  html.js .pt-part-run .pt-part-steps li.is-on > span { opacity: 1; transform: none; pointer-events: auto; }
  html.js .pt-part-run[data-step="-1"] .pt-part-steps li:first-child > span { opacity: .5; transform: none; }
}
/* Tall phones (390 x 844 leaves about 470 px below the copy): room for his
   line. Ai at the top left with it beside him, its tail at his head; the
   card below, the whole width. After the phone rules, which it overrides. */
@media (max-width: 575.98px) and (min-height: 760px) {
  .pt-part-run .rn-set { height: 25.7em; }
  .pt-part-run .rn-set::before { background:
      radial-gradient(46% 30% at 50% 80%, rgba(208, 154, 124, .10), rgba(208, 154, 124, 0) 72%),
      radial-gradient(14% 16% at 9% 12%, rgba(147, 183, 198, .10), rgba(147, 183, 198, 0) 72%); }
  .pt-part-run .rn-set::after { left: 1.6em; width: 22.4em; top: 24.5em; height: 1.2em; }
  .pt-part-run .rn-ai { left: .3em; top: 0; bottom: auto; }
  .pt-part-run .rn-say { display: block; left: 5.3em; top: .45em; width: 15.4em; transform: translateZ(.6em); }
  .pt-part-run .rn-say .pt-bubble { border-radius: .45em 1.3em 1.3em 1.3em; transform-origin: 0 30%; }
  .pt-part-run .rn-say .pt-bubble::before { left: -6px; right: auto; bottom: auto; top: calc(1.4em - 6px); clip-path: polygon(0 0, 0 100%, 100% 100%); }
  .pt-part-run .rn-float { left: .1em; top: 6.1em; width: 25.4em; height: 19.3em; }
  .pt-part-run .rn-card { transform: rotateY(-4deg) rotateX(2deg); }
  .pt-part-run .rn-phone { right: 1.4em; width: 6.8em; height: 10.4em; }
  .pt-part-run[data-step="2"] .rn-phone { transform: translateZ(1.6em) rotateY(-12deg) rotateX(3deg); }
}

/* ---------- instant draws (run.js) ------------------------------------------- */
/* A jump to a step (a hover, a tap, the test hook) glides there quickly with
   no delays; the reset snaps. Last, to win the ties. */
.pt-part-run.rn-quick .rn-mv { transition-duration: .3s; transition-delay: 0s; animation: none; }
.pt-part-run.rn-quick .rn-mv > *,
.pt-part-run.rn-quick .rn-mv::before,
.pt-part-run.rn-quick .rn-mv::after { transition-delay: 0s; animation: none; }
.pt-part-run.rn-snap .rn-mv,
.pt-part-run.rn-snap .rn-mv *,
.pt-part-run.rn-snap .rn-mv::before,
.pt-part-run.rn-snap .rn-mv::after { transition: none; animation: none; }
