/*
 * Paytrack product site (kirbyservice.net): Control's component (round 3,
 * plan.md). Tom Lee's customer card stands on the left with a stack of cards
 * behind it; Db, his line and the count on the right, and under them the desk
 * where the story is typed: the search, a new customer, the team. Markup in
 * obj/part_control.php, steps and typing in js/parts/control.js, the runner
 * in js/parts/part.js. Keep this file ASCII.
 *
 * The whole scene is sized in em: .pt-part-stage sets the unit from the
 * column's width (container units), so every part keeps its place at every
 * size and no text drops below 10px (the smallest is .82em of at least
 * 12.2px). Two compositions: wide (desktop and tablet, 34 x 15.9 em) and
 * narrow (phones, 26 x 11.9 em: no bubble, no last text on the card, the
 * count beside Db, the steps as dots and one caption line).
 *
 * Motion is transform and opacity only. The steps are the pt-sN classes and
 * data-step (part.js); the beats inside a step are the cb-* classes and the
 * data-hit attribute (control.js). Elements marked .ct-mv take the quick and
 * snap modes at the end of this file.
 *
 * Spacing (Dimitar, 02/10/2026, on Get paid: "spacing on the components in
 * pay not well done, things overlap"): the objects never touch, at least 8px
 * of air on desktop and 6px on phones with their bobs; every text fits its
 * box inside its padding. Checked with tools/browser/paytrack_overlap_check.js.
 */

/* ---------- the stage: the unit, the depth ---------------------------------- */
.pt-part-control { container-type: inline-size; }
.pt-part-control .pt-part-stage { position: relative; font-size: 14px;
  font-size: max(12.2px, min(17px, calc(100cqw / 34)));
  perspective: 1150px; perspective-origin: 50% 40%; }
.pt-part-control .pt-part-tilt { transform-style: preserve-3d; transition: transform .6s cubic-bezier(.2, .8, .3, 1); }
.pt-part-control .ct-set { position: relative; width: 34em; height: 15.9em; margin: 0 auto; transform-style: preserve-3d; line-height: 1.3;
  /* the file chip leaves from here and the rows land here (offsets from Db's mouth) */
  --fx: 7.4em; --fy: 3.1em; --rx: -8.2em; --ry: -3.75em; --arc: -1.7em; }
.pt-part-control .ct-set i { display: block; font-style: normal; }
.pt-part-control .ct-ico { flex: 0 0 auto; width: .95em; height: .95em; fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round; color: var(--pt-lichen); overflow: visible; }

/* The light in the room: a sage pool under the card, a mist one under the
   desk. No edges anywhere (the layers are invisible). A pseudo-element, so no
   check counts it as an object of the scene. */
.pt-part-control .ct-set::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(34% 40% at 20% 62%, rgba(157, 184, 159, .10), rgba(157, 184, 159, 0) 72%),
    radial-gradient(30% 34% at 72% 74%, rgba(147, 183, 198, .08), rgba(147, 183, 198, 0) 72%);
  transform: translateZ(-3em); }

/* ---------- the customer card --------------------------------------------- */
/* The group is drawn flat (the stack and the card in one plane, the card in
   front), so the card can turn over in 3D without cutting through the stack
   behind it; its own perspective gives the turn its depth. */
.pt-part-control .ct-cardpos { position: absolute; left: 0; top: 1.15em; width: 14em; transform-style: preserve-3d;
  transition: opacity .35s ease; }
.pt-part-control .ct-float { transform-style: preserve-3d; animation: ct-float 6.4s ease-in-out infinite; }
@keyframes ct-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-.22em); } }
.pt-part-control .ct-group { position: relative; perspective: 62em; transform: rotateY(9deg) rotateX(3deg); }

/* The stack: other customers' cards, behind Tom's, peeking above it. They
   come out one by one as the rows land (0). */
.pt-part-control .ct-stack { position: absolute; inset: 0; border-radius: 1em; transform-origin: 50% 0;
  background:
    linear-gradient(rgba(157, 184, 159, .55), rgba(157, 184, 159, .55)) 1.2em .32em / 2.6em .22em no-repeat,
    linear-gradient(rgba(236, 230, 218, .16), rgba(236, 230, 218, .16)) 4.3em .32em / 3.6em .22em no-repeat,
    linear-gradient(180deg, rgba(236, 230, 218, .08), rgba(236, 230, 218, .02) 1.6em),
    var(--pt-raised);
  box-shadow: inset 0 0 0 1px rgba(236, 230, 218, .07), 0 -.2em .8em rgba(0, 0, 0, .25);
  opacity: 0; transform: translateY(0) scale(1);
  transition: opacity .4s ease, transform .7s var(--pt-spring); }
.pt-part-control.pt-s0 .ct-k1 { opacity: 1; transform: translateY(-.4em) scale(.955); }
.pt-part-control.pt-s0 .ct-k2 { opacity: .85; transform: translateY(-.74em) scale(.91); }
.pt-part-control.pt-s0 .ct-k3 { opacity: .7; transform: translateY(-1.04em) scale(.865); }

.pt-part-control .ct-lift { position: relative; transform-style: preserve-3d; }
.pt-part-control .ct-card { position: relative; transform-style: preserve-3d; transform: rotateY(0deg);
  transition: transform 1.1s cubic-bezier(.65, 0, .35, 1); }
.pt-part-control.pt-s4 .ct-card { transform: rotateY(180deg); }
/* The faces: the front on top of the card's body, the back turned under it. */
.pt-part-control .ct-face { border-radius: 1em; color: var(--pt-bone); -webkit-backface-visibility: hidden; backface-visibility: hidden;
  background:
    linear-gradient(var(--pt-sage), var(--pt-sage)) 0 0 / 100% .28em no-repeat,
    linear-gradient(180deg, rgba(236, 230, 218, .06), rgba(236, 230, 218, 0) 42%),
    var(--pt-raised);
  box-shadow: 0 1.5em 2.4em -1.1em rgba(0, 0, 0, .75), 0 .2em .5em rgba(0, 0, 0, .25), inset 0 0 0 1px rgba(236, 230, 218, .08); }
.pt-part-control .ct-front { position: relative; padding: .8em .9em .75em; transform: translateZ(.14em);
  transition: opacity 0s linear .55s; }
.pt-part-control .ct-back { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .6em;
  padding: .8em; opacity: 0; transform: rotateY(180deg) translateZ(.14em); transition: opacity 0s linear .55s; }
/* The face turned away is also hidden, from the turn's middle on, so its
   texts are never counted where they cannot be seen. */
.pt-part-control.pt-s4 .ct-front { opacity: 0; }
.pt-part-control.pt-s4 .ct-back { opacity: 1; }
/* The card's thickness, between the two faces, seen at its edge in the turn. */
.pt-part-control .ct-slab { position: absolute; inset: .04em; border-radius: 1em;
  background: linear-gradient(rgba(236, 230, 218, .1), rgba(236, 230, 218, .1)), var(--pt-raised); }

/* The front: name, phones, address, the machine with its plan, the last text. */
.pt-part-control .ct-head { display: flex; align-items: center; gap: .55em; margin: 0 0 .45em; }
.pt-part-control .ct-ini { flex: 0 0 auto; display: grid; place-items: center; width: 2.2em; height: 2.2em; border-radius: 50%;
  background: var(--pt-sage); color: var(--pt-night); font: 600 .82em/1 var(--pt-head); letter-spacing: -.02em; }
.pt-part-control .ct-name { padding: 0 .38em; margin: 0 -.38em; font: 500 1.05em/1.25 var(--pt-head); letter-spacing: -.015em; color: var(--pt-bone); white-space: nowrap; }
.pt-part-control .ct-f { display: flex; align-items: center; gap: .45em; padding: .12em 0; margin: 0 0 .1em; }
.pt-part-control .ct-f > span { font: 500 .84em/1.3 var(--pt-text); color: var(--pt-bone); }
.pt-part-control .ct-f > span > span { white-space: nowrap; }
.pt-part-control .ct-f + .ct-m { margin-top: .35em; }
.pt-part-control .ct-m { display: flex; align-items: center; gap: .5em; padding: .42em .55em; margin: 0 0 .45em; border-radius: .6em;
  background: rgba(236, 230, 218, .05); }
.pt-part-control .ct-m-t { display: flex; flex-direction: column; min-width: 0; }
/* A cog for the machine: its teeth are a dashed ring (8 of them round r 6). */
.pt-part-control .ct-cog-t { stroke-width: 2; stroke-dasharray: 2.36 2.36; stroke-linecap: butt; }
.pt-part-control .ct-model { font: 600 .88em/1.25 var(--pt-text); color: var(--pt-bone); white-space: nowrap; }
.pt-part-control .ct-sn-l { font: 500 .84em/1.3 var(--pt-text); color: var(--pt-lichen); white-space: nowrap; }
.pt-part-control .ct-sn { color: var(--pt-bone); font-variant-numeric: tabular-nums; }
.pt-part-control .ct-plan { display: flex; width: max-content; align-items: center; gap: .45em; padding: .34em .75em .34em .6em; border-radius: 999px;
  background: rgba(157, 184, 159, .15); color: var(--pt-sage); font: 600 .82em/1.2 var(--pt-text); white-space: nowrap; }
.pt-part-control .ct-plan::before { content: ""; width: .5em; height: .5em; border-radius: 50%; background: currentColor; }
.pt-part-control .ct-msg { display: flex; margin: .45em 0 0; }
.pt-part-control .ct-msg span { display: block; padding: .38em .75em .4em; border-radius: .95em .95em .95em .3em;
  background: rgba(147, 183, 198, .15); color: var(--pt-bone); font: 500 .84em/1.3 var(--pt-text); white-space: nowrap; }

/* A field that answers the search: lit softly in sage, in sand for the
   duplicate (data-hit, control.js). A layer behind the words, so nothing moves. */
.pt-part-control .ct-hl { position: relative; isolation: isolate; }
.pt-part-control .ct-hl::before { content: ""; position: absolute; z-index: -1; inset: -.06em -.4em; border-radius: .5em;
  background: rgba(157, 184, 159, .2); box-shadow: inset 0 0 0 1px rgba(157, 184, 159, .55); opacity: 0; transition: opacity .3s ease; }
.pt-part-control .ct-name.ct-hl::before { inset: -.12em 0; }   /* inside its own padding: the box holds its light */
.pt-part-control .ct-m.ct-hl::before { inset: 0; border-radius: inherit; }
.pt-part-control[data-hit="name"] [data-hl="name"]::before,
.pt-part-control[data-hit="mob"] [data-hl="mob"]::before,
.pt-part-control[data-hit="id"] [data-hl="id"]::before,
.pt-part-control[data-hit="addr"] [data-hl="addr"]::before,
.pt-part-control[data-hit="dup"] [data-hl="addr"]::before { opacity: 1; }
.pt-part-control[data-hit="dup"] [data-hl="addr"]::before { background: rgba(217, 197, 154, .2); box-shadow: inset 0 0 0 1px rgba(217, 197, 154, .6); }
/* The card answers: a small pulse towards the viewer. */
.pt-part-control.cb-hit:not(.cb-quick) .ct-lift { animation: ct-pulse .5s ease-out; }
@keyframes ct-pulse { 0%, 100% { transform: none; } 35% { transform: translateZ(.9em) scale(1.012); } }

/* The back: Tom's real QR code (img/qr/card.svg, it opens the registration
   page), nearly face-on, and its caption. */
.pt-part-control .ct-qr { position: relative; flex: 0 0 auto; width: max(88px, 7.6em); height: max(88px, 7.6em); border-radius: .3em; overflow: hidden; }
.pt-part-control .ct-qr svg { display: block; width: 100%; height: 100%; }
.pt-part-control .ct-qr-shine { position: absolute; top: -20%; bottom: -20%; left: 0; width: 42%; pointer-events: none; opacity: 0;
  background: linear-gradient(100deg, rgba(236, 230, 218, 0), rgba(236, 230, 218, .55) 50%, rgba(236, 230, 218, 0));
  transform: translateX(-120%); }
.pt-part-control .ct-qr-t { font: 600 .84em/1.2 var(--pt-text); letter-spacing: .02em; color: var(--pt-lichen); white-space: nowrap; }

/* The count, under Db's line: 2,418 customers, rolled up as the rows land. */
.pt-part-control .ct-count { position: absolute; left: 22.9em; top: 5.65em; display: flex; align-items: baseline; gap: .45em; white-space: nowrap;
  opacity: 0; transform: translateY(.4em); transition: opacity .35s ease, transform .5s var(--pt-spring); }
.pt-part-control.pt-s0 .ct-count { opacity: 1; transform: none; }
/* As wide as 2,418 (1.87em in its tabular figures, measured): it lines up
   with the bubble at rest, and while it rolls the word beside it stays put. */
.pt-part-control .ct-num { display: inline-block; min-width: 1.9em; text-align: right; font: 500 1.3em/1 var(--pt-head); letter-spacing: -.02em;
  color: var(--pt-bone); font-variant-numeric: tabular-nums; transform-origin: 100% 70%; }
.pt-part-control .ct-count-t { font: 500 .9em/1.2 var(--pt-text); color: var(--pt-lichen); }

/* ---------- Db and his line --------------------------------------------------- */
.pt-part-control .ct-db { position: absolute; left: 15.4em; top: 0; width: 6.4em; transform: translateZ(.8em); pointer-events: none; }
.pt-part-control .ct-db .pt-char { width: 100%; animation-name: ct-bob; }   /* site.css's bob, 12px, made small here */
@keyframes ct-bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -.3em; } }
.pt-part-control .ct-db-in { transform-origin: 50% 100%; }
/* His shadow on the floor shrinks as he rises (his bob's clock, site.css). */
.pt-part-control .ct-db-shadow { position: absolute; left: 18%; right: 18%; bottom: .15em; height: .9em; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .55), rgba(0, 0, 0, 0)); animation: ct-dbshadow 5.1s ease-in-out -1.3s infinite; }
@keyframes ct-dbshadow { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .7; transform: scale(.84); } }
/* The hop at the end (control.js adds cb-hop, and is-hop on him for site.css's pop). */
.pt-part-control.cb-hop:not(.cb-quick) .ct-db-in { animation: ct-hop .62s cubic-bezier(.3, .7, .4, 1); }
@keyframes ct-hop { 0%, 62%, 100% { transform: translateY(0); } 35% { transform: translateY(-.9em); } 78% { transform: translateY(-.2em); } }

/* His line, beside his face, its tail towards him. */
.pt-part-control .ct-say { position: absolute; left: 22.9em; top: .95em; width: 10.9em; transform: translateZ(1em); }
.pt-part-control .ct-say .pt-bubble { margin: 0; max-width: none; padding: .7em .95em .72em; font-size: .9em; line-height: 1.38; }
html:not(.js) .pt-part-control .pt-bubble { opacity: 1; transform: none; }

/* The customer list, flying into Db's mouth (0). Anchored at the mouth. */
.pt-part-control .ct-file { position: absolute; left: 18.6em; top: 4.34em; display: inline-flex; align-items: center; gap: .4em;
  padding: .34em .65em .34em .45em; border-radius: .55em; white-space: nowrap; pointer-events: none;
  background: linear-gradient(rgba(147, 183, 198, .16), rgba(147, 183, 198, .16)), var(--pt-raised); color: var(--pt-bone);
  box-shadow: 0 .6em 1.2em rgba(0, 0, 0, .45), inset 0 0 0 1px rgba(147, 183, 198, .3);
  font: 600 .84em/1.2 var(--pt-text); opacity: 0; transform: translate(-50%, -50%) scale(.6); }
.pt-part-control .ct-file .ct-ico { color: var(--pt-mist); }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-file { animation: ct-file 1.05s cubic-bezier(.45, .1, .6, 1) .25s both; }
/* In front of Db (he stands .8em forward) all the way into his mouth. */
@keyframes ct-file {
  0% { opacity: 0; transform: translate3d(calc(-50% + var(--fx)), calc(-50% + var(--fy)), 1.6em) scale(.7); }
  16% { opacity: 1; transform: translate3d(calc(-50% + var(--fx)), calc(-50% + var(--fy)), 1.6em) scale(1); }
  70% { opacity: 1; transform: translate3d(calc(-50% + var(--fx) * .22), calc(-50% + var(--fy) * .1 - .4em), 1.5em) scale(.62); }
  100% { opacity: 0; transform: translate3d(-50%, -50%, 1.4em) scale(.2); }
}
/* The rows he sends out onto the stack: small sand records, one after another. */
.pt-part-control .ct-row { position: absolute; left: 18.6em; top: 4.34em; width: 2.6em; height: .62em; margin: -.31em 0 0 -1.3em;
  border-radius: .2em; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, var(--pt-sand) 0 28%, rgba(217, 197, 154, 0) 28% 33%, rgba(217, 197, 154, .75) 33% 68%, rgba(217, 197, 154, 0) 68% 73%, rgba(217, 197, 154, .5) 73%);
  box-shadow: 0 .2em .5em rgba(0, 0, 0, .35); }
.pt-part-control .ct-r2 { --dx: .9em; }
.pt-part-control .ct-r3 { --dx: -.8em; }
.pt-part-control .ct-r4 { --dx: 1.6em; }
.pt-part-control .ct-r5 { --dx: -1.5em; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-row { animation: ct-row .95s cubic-bezier(.35, .2, .45, 1) both; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-r1 { animation-delay: 1.2s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-r2 { animation-delay: 1.42s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-r3 { animation-delay: 1.64s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-r4 { animation-delay: 1.86s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-r5 { animation-delay: 2.08s; }
/* Out of his mouth (in front of him), over to the stack, down onto it. */
@keyframes ct-row {
  0% { opacity: 0; transform: translate3d(0, 0, 1.4em) scale(.3); }
  18% { opacity: 1; transform: translate3d(calc(var(--rx) * .16), calc(var(--arc) * .6), 1.4em) scale(1); }
  55% { opacity: 1; transform: translate3d(calc(var(--rx) * .62 + var(--dx, 0em) * .5), calc(var(--ry) * .5 + var(--arc)), .8em) scale(.9); }
  100% { opacity: 0; transform: translate3d(calc(var(--rx) + var(--dx, 0em)), var(--ry), 0) scale(.55); }
}
/* The stack fills as they land; the count lands with a small pop. */
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-k1 { transition-delay: 1.75s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-k2 { transition-delay: 2.15s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-k3 { transition-delay: 2.55s; }
.pt-part-control[data-step="0"]:not(.cb-quick) .ct-count { transition-delay: 1.05s; }
.pt-part-control.cb-landed:not(.cb-quick) .ct-num { animation: ct-land .5s var(--pt-spring); }
@keyframes ct-land { 0% { transform: scale(1); } 40% { transform: scale(1.14); } 100% { transform: scale(1); } }

/* ---------- the desk: the search, a new customer, the team ------------------ */
/* One at a time in the same place under Db: the search until the duplicate
   (2), the new customer for it, the team from the managers (3) on. */
.pt-part-control .ct-desk { position: absolute; left: 15.4em; width: 18.6em; color: var(--pt-bone);
  background: linear-gradient(180deg, rgba(236, 230, 218, .06), rgba(236, 230, 218, 0) 60%), var(--pt-raised);
  box-shadow: 0 1.2em 2em -1em rgba(0, 0, 0, .7), inset 0 0 0 1px rgba(236, 230, 218, .08);
  transition: opacity .4s ease, transform .6s var(--pt-spring); }

.pt-part-control .ct-search { top: 10.6em; height: 2.75em; display: flex; align-items: center; gap: .55em; padding: 0 1em;
  border-radius: 999px; transform: translateZ(.6em); }
.pt-part-control.pt-s2 .ct-search { opacity: 0; transform: translateZ(.6em) translateY(-.8em) scale(.96); }
.pt-part-control .ct-search::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(147, 183, 198, .75), 0 0 0 .2em rgba(147, 183, 198, .12); opacity: 0; transition: opacity .3s ease; }
.pt-part-control[data-step="1"] .ct-search::after { opacity: 1; }
.pt-part-control .ct-ico-q { width: 1.05em; height: 1.05em; color: var(--pt-mist); }
.pt-part-control .ct-q-wrap { position: relative; flex: 1 1 auto; min-width: 0; height: 1.3em; }
.pt-part-control .ct-q,
.pt-part-control .ct-ph { position: absolute; left: 0; top: 0; font: 500 .92em/1.41 var(--pt-text); white-space: nowrap; }
.pt-part-control .ct-q { color: var(--pt-bone); }
.pt-part-control .ct-ph { color: var(--pt-lichen); opacity: .8; }
.pt-part-control .ct-q:not(:empty) + .ct-ph { opacity: 0; }
/* The typing caret (the field in play only). */
.pt-part-control .ct-q.is-typing::after,
.pt-part-control .ct-in-v.is-typing::after { content: ""; display: inline-block; width: 2px; height: 1.1em; margin-left: 1px; vertical-align: -.2em;
  background: var(--pt-mist); animation: ct-caret .9s linear infinite; }
@keyframes ct-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
/* Found: a sage tick that pops at the end of the box. */
.pt-part-control .ct-ok { position: relative; flex: 0 0 auto; width: 1.25em; height: 1.25em; border-radius: 50%; background: var(--pt-sage);
  opacity: 0; transform: scale(.3); transition: opacity .2s ease, transform .4s var(--pt-spring); }
.pt-part-control .ct-ok::after { content: ""; position: absolute; left: .44em; top: .24em; width: .3em; height: .56em;
  border: solid var(--pt-night); border-width: 0 .14em .14em 0; transform: rotate(45deg); }
.pt-part-control.cb-hit .ct-ok { opacity: 1; transform: none; }

/* A new customer: the address typed, the duplicate flagged. */
.pt-part-control .ct-new { top: 8.4em; padding: .7em .85em .8em; border-radius: .9em;
  opacity: 0; transform: translateZ(.6em) translateY(.8em); }
.pt-part-control[data-step="2"] .ct-new { opacity: 1; transform: translateZ(.6em); }
.pt-part-control.pt-s3 .ct-new { transform: translateZ(.6em) translateY(-.8em) scale(.96); }
.pt-part-control .ct-desk-t { display: block; margin: 0 0 .5em .1em; font: 600 .84em/1.2 var(--pt-text); letter-spacing: .02em; color: var(--pt-lichen); }
.pt-part-control .ct-in { position: relative; display: flex; align-items: baseline; gap: .75em; padding: .38em .75em .42em; border-radius: .6em;
  background: rgba(236, 230, 218, .06); }
.pt-part-control .ct-in::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(147, 183, 198, .75); opacity: 0; transition: opacity .25s ease; }
.pt-part-control .ct-in:has(.is-typing)::after { opacity: 1; }
.pt-part-control.cb-dup .ct-in::after { box-shadow: inset 0 0 0 1px rgba(217, 197, 154, .7); opacity: 1; }
.pt-part-control .ct-in-l { flex: 0 0 auto; font: 500 .82em/1.2 var(--pt-text); color: var(--pt-lichen); }
.pt-part-control .ct-in-pin { display: none; align-self: center; color: var(--pt-lichen); }   /* the label's stand-in on phones */
.pt-part-control .ct-in-v { flex: 1 1 auto; min-width: 0; min-height: 1.41em; font: 600 .92em/1.41 var(--pt-text); color: var(--pt-bone); white-space: nowrap; }
/* The warning chip: sand, it pops with a ring and a shine (the chips of llm.php). */
.pt-part-control .ct-dup { position: relative; display: block; width: max-content; margin: .55em 0 0; opacity: 0;
  transform: translateY(-.5em) scale(.9); transform-origin: 0 0; transition: opacity .25s ease, transform .5s var(--pt-spring); }
.pt-part-control.cb-dup .ct-dup { opacity: 1; transform: none; }
.pt-part-control .ct-dup::before { content: ""; position: absolute; inset: -.22em; border-radius: 999px; border: .12em solid var(--pt-sand);
  opacity: 0; pointer-events: none; }
.pt-part-control .ct-dup-in { position: relative; overflow: hidden; display: flex; align-items: center; gap: .45em;
  padding: .36em .85em .36em .45em; border-radius: 999px; background: rgba(217, 197, 154, .17); color: var(--pt-sand); }
.pt-part-control .ct-dup-in > span { font: 600 .84em/1.25 var(--pt-text); white-space: nowrap; }
.pt-part-control .ct-dup-in b { font-weight: 700; color: var(--pt-bone); }
.pt-part-control .ct-dup-in::after { content: ""; position: absolute; top: -20%; bottom: -20%; left: 0; width: 45%; pointer-events: none;
  background: linear-gradient(105deg, rgba(236, 230, 218, 0), rgba(236, 230, 218, .45) 50%, rgba(236, 230, 218, 0)); transform: translateX(-120%); }
.pt-part-control .ct-warn { position: relative; flex: 0 0 auto; width: 1.2em; height: 1.2em; border-radius: 50%; background: var(--pt-sand); }
.pt-part-control .ct-warn::before { content: ""; position: absolute; left: 50%; top: .22em; width: .15em; height: .48em; margin-left: -.075em;
  border-radius: .1em; background: var(--pt-night); }
.pt-part-control .ct-warn::after { content: ""; position: absolute; left: 50%; bottom: .2em; width: .17em; height: .17em; margin-left: -.085em;
  border-radius: 50%; background: var(--pt-night); }
@keyframes ct-ring { 0% { opacity: .9; transform: scale(.92); } 100% { opacity: 0; transform: scale(1.18, 1.6); } }
@keyframes ct-shine { 0% { transform: translateX(-120%); } 100% { transform: translateX(260%); } }
.pt-part-control.cb-dup:not(.cb-quick) .ct-dup::before { animation: ct-ring .7s ease-out .12s forwards; }
.pt-part-control.cb-dup:not(.cb-quick) .ct-dup-in::after { animation: ct-shine .9s ease-in-out .3s; }

/* The team: Maria, the service manager, slides in; three rights switch on one
   by one, one stays off. */
.pt-part-control .ct-team { top: 8.4em; padding: .75em .85em .85em; border-radius: .9em;
  opacity: 0; transform: translateZ(.6em) translateX(1.6em); }
.pt-part-control.pt-s3 .ct-team { opacity: 1; transform: translateZ(.6em); }
.pt-part-control .ct-mgr { display: flex; align-items: center; gap: .55em; margin: 0 0 .65em; opacity: 0; transform: translateX(1.4em);
  transition: opacity .35s ease, transform .55s var(--pt-spring); }
.pt-part-control.pt-s3 .ct-mgr { opacity: 1; transform: none; }
.pt-part-control .ct-ini-mgr { background: var(--pt-mist); }
.pt-part-control .ct-mgr-t { font: 500 .9em/1.25 var(--pt-text); color: var(--pt-lichen); white-space: nowrap; }
.pt-part-control .ct-mgr-t b { font-weight: 700; color: var(--pt-bone); }
.pt-part-control .ct-rights { display: grid; grid-template-columns: 1fr 1fr; gap: .55em 1.2em; }
.pt-part-control .ct-sw { display: flex; align-items: center; gap: .5em; }
.pt-part-control .ct-sw > span { font: 500 .84em/1.25 var(--pt-text); color: var(--pt-bone); white-space: nowrap; opacity: .62; transition: opacity .3s ease; }
.pt-part-control .ct-tog { position: relative; flex: 0 0 auto; width: 1.8em; height: 1.04em; border-radius: 999px; background: rgba(236, 230, 218, .13); }
.pt-part-control .ct-tog-on { position: absolute; inset: 0; border-radius: inherit; background: var(--pt-sage); opacity: 0; transition: opacity .3s ease; }
.pt-part-control .ct-knob { position: absolute; left: .13em; top: .13em; width: .78em; height: .78em; border-radius: 50%; background: var(--pt-bone);
  box-shadow: 0 .08em .2em rgba(0, 0, 0, .35); transition: transform .45s var(--pt-spring); }
.pt-part-control.pt-s3 .ct-sw1 .ct-tog-on,
.pt-part-control.pt-s3 .ct-sw2 .ct-tog-on,
.pt-part-control.pt-s3 .ct-sw3 .ct-tog-on { opacity: 1; }
.pt-part-control.pt-s3 .ct-sw1 .ct-knob,
.pt-part-control.pt-s3 .ct-sw2 .ct-knob,
.pt-part-control.pt-s3 .ct-sw3 .ct-knob { transform: translateX(.76em); }
.pt-part-control.pt-s3 .ct-sw1 > span,
.pt-part-control.pt-s3 .ct-sw2 > span,
.pt-part-control.pt-s3 .ct-sw3 > span { opacity: 1; }
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-mgr { transition-delay: .3s; }
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-sw1 > *,
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-sw1 .ct-tog > * { transition-delay: .95s; }
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-sw2 > *,
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-sw2 .ct-tog > * { transition-delay: 1.35s; }
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-sw3 > *,
.pt-part-control[data-step="3"]:not(.cb-quick) .ct-sw3 .ct-tog > * { transition-delay: 1.75s; }

/* Each object floats a little on its own clock (the bobs are in the spacing). */
.pt-part-control .ct-desk { animation: ct-desk 5.8s ease-in-out -2s infinite; }
@keyframes ct-desk { 0%, 100% { translate: 0 0; } 50% { translate: 0 -.18em; } }

/* ---------- 4: the card turns over to its QR, Db hops ----------------------- */
.pt-part-control[data-step="4"]:not(.cb-quick) .ct-card { transition-delay: .2s; }
.pt-part-control[data-step="4"]:not(.cb-quick) .ct-front,
.pt-part-control[data-step="4"]:not(.cb-quick) .ct-back { transition-delay: .75s; }
.pt-part-control[data-step="4"]:not(.cb-quick) .ct-lift { animation: ct-lift 1.3s cubic-bezier(.4, 0, .3, 1) .15s; }
@keyframes ct-lift { 0%, 100% { transform: none; } 45% { transform: translateZ(3.2em); } 82% { transform: translateZ(-.2em); } }
.pt-part-control[data-step="4"]:not(.cb-quick) .ct-qr-shine { animation: ct-qrshine 1s ease-in-out 1.55s; }
@keyframes ct-qrshine { 0% { opacity: 1; transform: translateX(-120%); } 100% { opacity: 1; transform: translateX(300%); } }

/* ---------- the rewind: the moving parts fade, the set stays ---------------- */
/* The search stays out too until the rewind lifts, then fades in with the card. */
.pt-part-control.is-rewind .ct-cardpos,
.pt-part-control.is-rewind .ct-count,
.pt-part-control.is-rewind .ct-search,
.pt-part-control.is-rewind .ct-team { opacity: 0; transition: opacity .35s ease; }

/* ---------- the steps under the scene ----------------------------------------- */
/* Desktop: small floating pills in a compact wrap; the one in play is lit in
   the layer's sage. The size follows the type scale (--pt-fs-ui, 13px at 1440). */
.pt-part-control .pt-part-steps { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 16px 0 0; padding: 0; list-style: none; }
.pt-part-control .pt-part-steps li { position: relative; isolation: isolate; display: inline-flex; align-items: center; gap: .6em;
  padding: .52em 1.08em .52em .85em; border-radius: 999px; background: rgba(236, 230, 218, .06); color: var(--pt-bone);
  font: 500 calc(var(--pt-fs-ui) * .8125)/1.3 var(--pt-text); cursor: default;
  animation: ct-pill 6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -1.2s); }
.pt-part-control .pt-part-steps li::before { content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--tone, var(--pt-sage)); opacity: .5; 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-control .pt-part-steps li::after { content: ""; position: absolute; z-index: -1; inset: 0; border-radius: inherit;
  background: radial-gradient(circle at 1.17em 50%, rgba(157, 184, 159, .55), rgba(157, 184, 159, 0) 1.25em), rgba(236, 230, 218, .07);
  opacity: 0; transition: opacity .35s ease; }
.pt-part-control .pt-part-steps li > span { opacity: .68; transition: opacity .3s ease; }
.pt-part-control .pt-part-steps li.is-on::before { opacity: 1; transform: scale(1.2); }
.pt-part-control .pt-part-steps li.is-on::after,
.pt-part-control .pt-part-steps li.is-on > span { opacity: 1; }
.pt-part-control .pt-part-steps li:focus-visible { outline: 2px solid var(--pt-sand); outline-offset: 3px; }
@keyframes ct-pill { 0%, 100% { translate: 0 0; } 50% { translate: 0 -3px; } }

/* Nothing moves in a layer that is not the one in front. */
.pt-layer:not(.is-current) .pt-part-control .ct-float,
.pt-layer:not(.is-current) .pt-part-control .ct-db-shadow,
.pt-layer:not(.is-current) .pt-part-control .ct-desk,
.pt-layer:not(.is-current) .pt-part-control .ct-q::after,
.pt-layer:not(.is-current) .pt-part-control .ct-in-v::after,
.pt-layer:not(.is-current) .pt-part-control .pt-part-steps li { animation-play-state: paused; }

/* ---------- phones: the narrow composition ------------------------------------ */
/* The card on the left (no last text, the address on two lines); on the
   right Db with the count beside him, the desk under them. No bubble: no
   room for it with the air. The steps become five dots and one caption line
   (below). */
@media (max-width: 575.98px) {
  .pt-part-control .pt-part-stage { font-size: 12.2px; font-size: max(12.2px, min(13.6px, calc(100cqw / 26))); perspective: 820px; }
  .pt-part-control .ct-set { width: 26em; height: 11.9em; --fx: 5.6em; --fy: 2.3em; --rx: -6.3em; --ry: -2.5em; --arc: -1.2em; }
  .pt-part-control .ct-set::before { background:
    radial-gradient(40% 44% at 24% 60%, rgba(157, 184, 159, .10), rgba(157, 184, 159, 0) 72%),
    radial-gradient(34% 30% at 74% 72%, rgba(147, 183, 198, .08), rgba(147, 183, 198, 0) 72%); }
  .pt-part-control .ct-cardpos { top: .64em; width: 11.9em; }
  .pt-part-control .ct-group { transform: rotateY(8deg) rotateX(3deg); }
  .pt-part-control.pt-s0 .ct-k1 { transform: translateY(-.25em) scale(.955); }
  .pt-part-control.pt-s0 .ct-k2 { transform: translateY(-.46em) scale(.91); }
  .pt-part-control.pt-s0 .ct-k3 { transform: translateY(-.64em) scale(.865); }
  .pt-part-control .ct-front { padding: .52em .7em .54em; }
  .pt-part-control .ct-head { margin-bottom: .2em; }
  .pt-part-control .ct-ini { width: 1.85em; height: 1.85em; }
  .pt-part-control .ct-name { font-size: .98em; }
  .pt-part-control .ct-f { padding: 0; margin-bottom: .06em; }
  .pt-part-control .ct-f > span > span { display: block; }
  .pt-part-control .ct-f + .ct-m { margin-top: .22em; }
  .pt-part-control .ct-m { padding: .28em .5em; margin-bottom: .3em; gap: .4em; }
  .pt-part-control .ct-m .ct-ico { display: none; }
  .pt-part-control .ct-plan::before { display: none; }
  .pt-part-control .ct-plan { padding: .28em .7em; }
  .pt-part-control .ct-msg { display: none; }
  .pt-part-control .ct-qr { width: max(64px, 6.6em); height: max(64px, 6.6em); }
  .pt-part-control .ct-back { gap: .5em; }

  .pt-part-control .ct-db { left: 12.7em; top: 0; width: 4em; }   /* 4.57em tall: .73em above the desk */
  .pt-part-control .ct-file,
  .pt-part-control .ct-row { left: 14.7em; top: 2.72em; }
  .pt-part-control .ct-say { display: none; }
  .pt-part-control .ct-count { left: 17.6em; top: .95em; flex-direction: column; align-items: flex-start; gap: .2em; }
  .pt-part-control .ct-num { min-width: 0; text-align: left; transform-origin: 0 70%; font-size: 1.22em; }
  .pt-part-control .ct-count-t { font-size: .84em; }

  .pt-part-control .ct-desk { left: 12.6em; width: 13.4em; }
  .pt-part-control .ct-search { top: 7.25em; height: 2.6em; padding: 0 .8em; gap: .45em; }
  .pt-part-control .ct-new { top: 5.3em; padding: .5em .6em .55em; }
  .pt-part-control .ct-desk-t { display: none; }
  /* The pin for the word "Address": beside the word, "8 Production Road"
     (Dimitar's example address, 02/10/2026) had 85 px of the 96 it needs. */
  .pt-part-control .ct-in { gap: .45em; }
  .pt-part-control .ct-in-l { display: none; }
  .pt-part-control .ct-in-pin { display: block; }
  .pt-part-control .ct-dup-in { padding: .34em .7em .34em .4em; }
  .pt-part-control .ct-dup-in > span > span { display: block; }
  .pt-part-control .ct-team { top: 5.6em; padding: .6em .65em .7em; }
  .pt-part-control .ct-mgr { margin-bottom: .5em; }
  .pt-part-control .ct-rights { grid-template-columns: auto auto; justify-content: space-between; gap: .45em .6em; }
  .pt-part-control .ct-sw { gap: .38em; }
  .pt-part-control .ct-tog { width: 1.56em; height: .92em; }
  .pt-part-control .ct-knob { width: .68em; height: .68em; left: .12em; top: .12em; }
  .pt-part-control.pt-s3 .ct-sw1 .ct-knob,
  .pt-part-control.pt-s3 .ct-sw2 .ct-knob,
  .pt-part-control.pt-s3 .ct-sw3 .ct-knob { transform: translateX(.64em); }
  .pt-part-control .ct-mgr-t { font-size: .86em; }
}

/* Tall phones (390x844 and the like) have the room for Db's line: the bubble
   comes back above him, Db, the count and the desk move down under it, and
   the card stands in the middle of the taller scene. */
@media (max-width: 575.98px) and (min-height: 780px) {
  .pt-part-control .ct-set { height: 16.3em; --ry: -4.95em; }
  .pt-part-control .ct-cardpos { top: 2.6em; }
  .pt-part-control .ct-say { display: block; left: 12.6em; top: 0; width: 10.6em; }
  /* Its tail points down at Db, under it (he stands below, not beside). */
  .pt-part-control .ct-say .pt-bubble { padding: .62em .9em .64em; font-size: .86em; border-radius: 18px 18px 18px 6px; }
  .pt-part-control .ct-say .pt-bubble::before { left: 1.95em; bottom: -6px; clip-path: polygon(100% 0, 100% 100%, 0 100%); }   /* over his centre */
  .pt-part-control .ct-db { top: 4.45em; }
  .pt-part-control .ct-file,
  .pt-part-control .ct-row { top: 7.16em; }
  .pt-part-control .ct-count { top: 5.4em; }
  .pt-part-control .ct-search { top: 11.7em; }
  .pt-part-control .ct-new { top: 9.75em; }
  .pt-part-control .ct-team { top: 10.05em; }
}

/* ---------- the steps as dots and one caption: phones and the lg column -------- */
/* Five long pointers do not pair up in a 444px column (lg, 992 to 1199): they
   stacked as five rows of pills, as tall as the scene itself. There, as on
   phones, the steps become five dots in a row and the lit step's line under
   them, full width. Only with JS (it lights the step in play); without it the
   pills stay. */
@media (max-width: 575.98px), (min-width: 992px) and (max-width: 1199.98px) {
  html.js .pt-part-control .pt-part-steps { position: relative; flex-wrap: nowrap; justify-content: center; gap: 0; }
  html.js .pt-part-control .pt-part-steps li { position: static; isolation: auto; justify-content: center; align-items: flex-start;
    background: none; animation: none; }
  html.js .pt-part-control .pt-part-steps li::after { display: none; }
  html.js .pt-part-control .pt-part-steps li > span { position: absolute; left: 0; right: 0; text-align: center; white-space: nowrap;
    opacity: 0; transform: translateY(5px); pointer-events: none; transition: opacity .3s ease, transform .45s var(--pt-spring); }
  html.js .pt-part-control .pt-part-steps li.is-on > span { opacity: 1; transform: none; pointer-events: auto; }
  html.js .pt-part-control[data-step="-1"] .pt-part-steps li:first-child > span { opacity: .5; transform: none; }
}
/* Phones: small dots, the caption as plain text (every pixel counts here). */
@media (max-width: 575.98px) {
  html.js .pt-part-control .pt-part-steps { height: 34px; margin-top: 4px; }
  html.js .pt-part-control .pt-part-steps li { width: 20px; height: 12px; padding: 3px 0 0; }
  html.js .pt-part-control .pt-part-steps li::before { width: 6px; height: 6px; }
  html.js .pt-part-control .pt-part-steps li.is-on::before { transform: scale(1.5); }
  html.js .pt-part-control .pt-part-steps li > span { top: 15px; font-size: calc(var(--pt-fs-ui) - 1px); line-height: 19px; }
}
/* The lg column: the lit step keeps its pill, centred under the dots. */
@media (min-width: 992px) and (max-width: 1199.98px) {
  html.js .pt-part-control .pt-part-steps { height: 50px; margin-top: 14px; }
  html.js .pt-part-control .pt-part-steps li { width: 22px; height: 14px; padding: 4px 0 0; }
  html.js .pt-part-control .pt-part-steps li.is-on::before { transform: scale(1.45); }
  html.js .pt-part-control .pt-part-steps li > span { top: 21px; width: max-content; margin: 0 auto; padding: .45em 1.05em .5em;
    border-radius: 999px; background: rgba(236, 230, 218, .08); line-height: 1.3; }
}

/* ---------- instant draws (control.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. The one-shot effects
   (the flight, the rows, rings, shines, the lift) also say :not(.cb-quick)
   themselves. */
.pt-part-control.cb-quick .ct-mv { transition-duration: .3s; transition-delay: 0s; animation: none; }
.pt-part-control.cb-quick .ct-mv > *,
.pt-part-control.cb-quick .ct-mv::before,
.pt-part-control.cb-quick .ct-mv::after { transition-delay: 0s; }
.pt-part-control.cb-quick .ct-front,
.pt-part-control.cb-quick .ct-back { transition-duration: 0s; transition-delay: .15s; }
.pt-part-control.cb-snap .ct-mv,
.pt-part-control.cb-snap .ct-mv > *,
.pt-part-control.cb-snap .ct-mv::before,
.pt-part-control.cb-snap .ct-mv::after { transition: none; animation: none; }
/* The desk keeps its float through a jump: only its moves are quickened. On
   the reset it only fades (part.js finishes that at once, except after the
   rewind, where the search comes back in softly). */
.pt-part-control.cb-quick .ct-desk { transition-duration: .3s; transition-delay: 0s; }
.pt-part-control.cb-snap .ct-desk { transition: opacity .35s ease; }
