/*
 * Paytrack product site (kirbyservice.net): Book's component (round 3,
 * plan.md). Two floating cards of the app, the team calendar and a phone
 * with the AI's text chat; Ai, the business's own AI ("Local Ai" on his
 * belly), floats above the calendar with his line beside him. Markup in
 * obj/part_book.php, the thread and its typing in js/parts/book.js, the
 * runner in js/parts/part.js. Keep this file ASCII. (The calendar's classes
 * are bk-diary, bk-d*: its first name.)
 *
 * Five steps: 0 clash (a booking dragged onto a booked time flashes the
 * clash and snaps to the next open one), 1 near (the days tagged with where
 * the team will be, the times in Tom's area lit, the rest dimmed), 2 addr
 * (the AI has the address confirmed, then offers those times), 3 take (Take
 * over: Maria joins, Ai steps back), 4 stop (Kim's chat: STOP, locked at
 * once).
 *
 * 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). One layout (Ai and his line top left,
 * the calendar under them, the phone on the right) in four cuts: wide
 * (desktop and tablet, 35 x 21.25 em), short phones (25.6 x 17.7 em at
 * 12.5px: with the layer's copy above, 375x667 leaves 259 px for the whole
 * component clear of the arrow, measured 02/10/2026), very short phones
 * (25.6 x 16.5 em: 360x640, where the heading takes three lines, leaves
 * 235) and tall phones (25.6 x 22.6 em). 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, keyframes and the bb-* classes (book.js).
 * Elements marked .bk-mv take the quick and snap modes at the end of this
 * file; every one-shot effect also says :not(.bk-quick) or hangs on a beat
 * class.
 *
 * Colours say what a thing is, as in Campaign manager: sand a place (the
 * postcodes), dusk the AI (his texts, the times he can offer), sage done
 * and booked (a tick, every booked time: Dimitar, 02/10/2026, "booked tint
 * in green"), clay the clash. Open times are quiet, a dashed outline.
 *
 * 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 Ai's lean towards the pointer 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-book { container-type: inline-size; }
.pt-part-book .pt-part-stage { position: relative; font-size: 14px;
  font-size: max(12.5px, min(16px, calc(100cqw / 35), 2vh));
  perspective: 1100px; perspective-origin: 50% 40%; }
.pt-part-book .pt-part-tilt { transform-style: preserve-3d; transition: transform .6s cubic-bezier(.2, .8, .3, 1); }
.pt-part-book .bk-set { position: relative; width: 35em; height: 21.25em; margin: 0 auto; transform-style: preserve-3d; line-height: 1.3; }
.pt-part-book .bk-set i { display: block; font-style: normal; }

/* The light in the room: a dusk pool under the calendar, a cool one under the
   phone and a small one by Ai. No surface edges anywhere (the layers are
   invisible). A pseudo-element, so no check counts it as an object. */
.pt-part-book .bk-set::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(34% 30% at 31% 82%, rgba(180, 167, 207, .10), rgba(180, 167, 207, 0) 72%),
    radial-gradient(18% 36% at 83% 62%, rgba(147, 183, 198, .10), rgba(147, 183, 198, 0) 72%),
    radial-gradient(12% 16% at 8% 18%, rgba(147, 183, 198, .08), rgba(147, 183, 198, 0) 72%);
  transform: translateZ(-3em); }

/* ---------- Ai, the business's own AI, and his line ------------------------ */
/* He floats top left, over the calendar, a little in front. His own bob is
   5 px here (not site.css's 12), so the calendar under him keeps its air. */
.pt-part-book .bk-ai { position: absolute; left: .3em; top: .15em; width: 5.1em; transform: translateZ(1.2em); transform-style: preserve-3d; pointer-events: none; }
.pt-part-book .bk-ai .pt-char { width: 100%; }
.pt-part-book .bk-ai .pt-char-ai { animation-name: bk-hover; }
@keyframes bk-hover { 0%, 100% { translate: 0 0; } 50% { translate: 0 -5px; } }
.pt-part-book .bk-ai-in { transform-origin: 50% 100%; transition: transform .8s var(--pt-spring), opacity .45s ease; }
/* A person takes over the chat (3): he steps back, smaller and dimmer (and a
   little up, never nearer the calendar), and comes forward again for the
   next chat (4). */
.pt-part-book[data-step="3"] .bk-ai-in { transform: translate3d(-.15em, -.3em, -3.2em) scale(.84); opacity: .45; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-ai-in { transition-delay: 1.3s; }

/* His line, beside him, its tail at his face. */
.pt-part-book .bk-say { position: absolute; left: 6.45em; top: .9em; width: 11.6em; transform: translateZ(.9em); }
.pt-part-book .bk-say .pt-bubble { max-width: none; margin: 0; padding: .72em .95em; font-size: .86em; line-height: 1.4;
  border-radius: .45em 1.3em 1.3em 1.3em; transform-origin: 0 30%; }
.pt-part-book .bk-say .pt-bubble::before { left: -6px; right: auto; bottom: auto; top: calc(1.5em - 6px); clip-path: polygon(0 0, 0 100%, 100% 100%); }
html:not(.js) .pt-part-book .pt-bubble { opacity: 1; transform: none; }

/* ---------- the parts both cards use ----------------------------------------- */
/* Chips: a pill, its words in their own span (above the shine). */
.pt-part-book .bk-chip { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; gap: .4em; padding: .3em .7em; border-radius: 999px;
  font: 600 .8em/1.2 var(--pt-text); white-space: nowrap; }
.pt-part-book .bk-chip > span { position: relative; }
.pt-part-book .bk-chip b { font-weight: 700; }
.pt-part-book .bk-sand { background: rgba(217, 197, 154, .16); color: var(--pt-sand); }
.pt-part-book .bk-dusk { background: rgba(180, 167, 207, .17); color: var(--pt-dusk); }
.pt-part-book .bk-mute { background: rgba(167, 175, 164, .13); color: var(--pt-lichen); }
.pt-part-book .bk-clay { background: rgba(208, 154, 124, .2); color: var(--pt-clay); }
.pt-part-book .bk-pers { background: rgba(236, 230, 218, .09); color: var(--pt-bone); }
/* Pops: a ring that spreads and fades, a shine clipped to the chip (the
   chips of llm.php). */
.pt-part-book .bk-pop::before { content: ""; position: absolute; inset: -.24em; border-radius: inherit; border: .12em solid currentColor;
  opacity: 0; pointer-events: none; }
.pt-part-book .bk-shine { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; }
.pt-part-book .bk-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 bk-ring { 0% { opacity: .85; transform: scale(.94); } 100% { opacity: 0; transform: scale(1.18, 1.6); } }
@keyframes bk-ring-wide { 0% { opacity: .9; transform: scale(.98); } 100% { opacity: 0; transform: scale(1.07, 1.45); } }
@keyframes bk-shine { 0% { transform: translateX(-120%); } 100% { transform: translateX(300%); } }
@keyframes bk-press { 0%, 100% { transform: none; } 35% { transform: scale(.92); } }
/* Initials in a round badge, each person in their own colour (as in Grow and
   Campaign manager): Tom mist, Kim grey, Maria dusk. In a chip the letter
   takes the chip's size, never under 10px. */
.pt-part-book .bk-av { grid-area: av; display: flex; align-items: center; justify-content: center; width: 2.4em; height: 2.4em; border-radius: 50%;
  font: 600 .8em/1 var(--pt-head); color: var(--pt-night); background: var(--pt-mist); }
.pt-part-book .bk-av-kim { background: rgba(167, 175, 164, .3); color: var(--pt-bone); }
.pt-part-book .bk-av-m { background: var(--pt-dusk); }
.pt-part-book .bk-chip .bk-av { flex: 0 0 auto; width: 1.45em; height: 1.45em; margin-left: -.3em; font-size: 1em; }
/* The sage tick, a pin, a lock and a led, drawn in CSS (sized in their own em). */
.pt-part-book .bk-tick { position: relative; flex: 0 0 auto; width: 1.1em; height: 1.1em; border-radius: 50%; background: var(--pt-sage); }
.pt-part-book .bk-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); }
.pt-part-book .bk-tick::before { content: ""; position: absolute; inset: -.24em; border-radius: 50%; border: .12em solid var(--pt-sage);
  opacity: 0; pointer-events: none; }
.pt-part-book .bk-pin { position: relative; flex: 0 0 auto; width: .66em; height: .66em; margin: .02em .1em 0; border-radius: 50% 50% 50% 0;
  background: currentColor; transform: rotate(-45deg); }
.pt-part-book .bk-pin::after { content: ""; position: absolute; left: 50%; top: 50%; width: .24em; height: .24em; margin: -.12em 0 0 -.12em;
  border-radius: 50%; background: var(--pt-raised); }
.pt-part-book .bk-lock { position: relative; flex: 0 0 auto; width: .8em; height: .64em; margin-top: .34em; border-radius: .14em; background: currentColor; }
.pt-part-book .bk-lock::before { content: ""; position: absolute; left: .14em; right: .14em; bottom: 100%; height: .38em; margin-bottom: -.05em;
  border: .12em solid currentColor; border-bottom: 0; border-radius: .3em .3em 0 0; }
.pt-part-book .bk-led { position: relative; flex: 0 0 auto; width: .55em; height: .55em; border-radius: 50%; background: currentColor; }
@keyframes bk-led { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.7); } }
/* Buttons: dusk for the action. */
.pt-part-book .bk-btn { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; padding: .48em 1.3em;
  border-radius: .7em; background: var(--pt-dusk); color: var(--pt-night); font: 600 .82em/1.2 var(--pt-text); white-space: nowrap; }
.pt-part-book .bk-btn > span { position: relative; }

/* The cards float, each on its own clock; their shadows on the floor shrink
   as they rise (pseudo-elements, so no check counts them as objects). */
@keyframes bk-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-.32em); } }
@keyframes bk-shadow { 0%, 100% { opacity: 1; transform: translateZ(-.6em) scale(1); } 50% { opacity: .72; transform: translateZ(-.6em) scale(.9); } }

/* ---------- the team calendar ---------------------------------------------- */
/* Two days, four times. The card: raised, a thin dusk band along the top
   (the layer's tone), turned towards the phone. Flat inside. Its measures
   are named, so the booking dragged in step 0 can work out the way from the
   header to its slot whatever the composition. */
.pt-part-book .bk-diary { position: absolute; left: 0; top: 7.6em; width: 21.6em; height: 13.6em; transform-style: preserve-3d; }
.pt-part-book .bk-diary::after { content: ""; position: absolute; left: 7%; right: 7%; top: calc(100% - .9em); height: 1.4em; pointer-events: none;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)); animation: bk-shadow 6s ease-in-out infinite; }
.pt-part-book .bk-dfloat { position: absolute; inset: 0; transform-style: preserve-3d; animation: bk-bob 6s ease-in-out infinite; }
.pt-part-book .bk-dcard { --pt: .72em; --px: .85em; --hd: 1.85em; --hm: .42em; --dh: 2.65em; --tc: 2.4em; --cg: .35em; --rh: 1.55em; --rg: .26em;
  position: absolute; inset: 0; padding: var(--pt) var(--px) .7em; border-radius: .95em; color: var(--pt-bone);
  background:
    linear-gradient(var(--pt-dusk), var(--pt-dusk)) 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(7deg) rotateX(3deg); }
/* The header: the title, and on the right the customer the times are for (1). */
.pt-part-book .bk-dhd { position: relative; display: flex; align-items: center; justify-content: space-between; gap: .6em;
  height: var(--hd); padding-bottom: .45em; margin-bottom: var(--hm); box-shadow: 0 1px 0 rgba(236, 230, 218, .08); }
.pt-part-book .bk-dhd-t { font: 500 .92em/1.2 var(--pt-head); letter-spacing: -.01em; color: var(--pt-bone); white-space: nowrap; }
.pt-part-book .bk-year { color: var(--pt-lichen); }   /* the year, quieter */
.pt-part-book .bk-dbody { transition: opacity .35s ease; }
/* The grid: the times down the side, a column a day. */
.pt-part-book .bk-grid { display: grid; grid-template-columns: var(--tc) minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: var(--dh) repeat(4, var(--rh));
  column-gap: var(--cg); row-gap: var(--rg); }
.pt-part-book .bk-dh { display: flex; flex-direction: column; align-items: flex-start; gap: .24em; min-width: 0; }
.pt-part-book .bk-dl { display: flex; align-items: center; gap: .35em; min-width: 0; }
.pt-part-book .bk-date { font: 500 .8em/1.2 var(--pt-head); letter-spacing: -.01em; color: var(--pt-bone); white-space: nowrap; }
/* Tom's badge on his day: phones only (on wide screens his chip is in the header). */
.pt-part-book .bk-sam { position: relative; display: none; width: 1.75em; height: 1.75em; }
.pt-part-book .bk-sam::before { border-color: var(--pt-mist); }
.pt-part-book .bk-pcw { display: block; transition: opacity .5s ease; }
.pt-part-book .bk-t { align-self: center; justify-self: end; padding-right: .1em; font: 500 .8em/1.2 var(--pt-text); color: var(--pt-lichen);
  white-space: nowrap; font-variant-numeric: tabular-nums; }
/* A slot: Booked (a sage tint, sage words: every booking reads the same), or
   Open (quiet words in a dashed outline). */
.pt-part-book .bk-slot { position: relative; display: flex; align-items: center; min-width: 0; padding: 0 .6em; border-radius: .5em; }
.pt-part-book .bk-slot-t { position: relative; font: 600 .8em/1.2 var(--pt-text); white-space: nowrap; }
.pt-part-book .bk-job,
.pt-part-book .bk-clash { background: rgba(157, 184, 159, .12); box-shadow: inset 0 0 0 1px rgba(157, 184, 159, .22); }
.pt-part-book .bk-job .bk-slot-t,
.pt-part-book .bk-clash .bk-slot-t { color: var(--pt-sage); }
.pt-part-book .bk-offer,
.pt-part-book .bk-far,
.pt-part-book .bk-new { border: 1px dashed rgba(236, 230, 218, .16); }
.pt-part-book .bk-open { color: var(--pt-bone); opacity: .42; }

/* ---------- step 0: a booking made by hand, the clash, the next open time ---- */
/* Kim's booking, a block the size of a slot, lives in the open time it ends
   in. It pops up over the calendar's right half, just above the card (on
   phones, with no room there, over Wednesday's open 11 AM), and the pointer
   takes it across onto the booked time above its slot: the clash flashes
   (clay, the slot rings, a Clash chip, the block shakes its head), then it
   snaps down to the next open time and is booked: the tick, and the block
   turns sage like every booked time (a sage layer that fades in). One clock
   for every part of it: each keyframe of 3 s from .3 s, so the beats line
   up. */
.pt-part-book .bk-new { z-index: 2; }
.pt-part-book .bk-kim { position: absolute; inset: -1px; z-index: 1;
  --kx: calc(100% + var(--cg));
  --ky: calc(-1 * (var(--pt) + var(--hd) + var(--hm) + var(--dh) + 3 * var(--rg) + 2 * var(--rh)) - 1.85em);
  --k1: calc(-1 * (var(--rh) + var(--rg)));
  opacity: 0; transition: opacity .3s ease; }
.pt-part-book.pt-s0 .bk-kim { opacity: 1; }
.pt-part-book .bk-kim-in { position: absolute; inset: 0; display: flex; align-items: center; justify-content: space-between; gap: .4em;
  padding: 0 .3em 0 .6em; border-radius: .5em;
  background: linear-gradient(rgba(236, 230, 218, .11), rgba(236, 230, 218, .11)), var(--pt-raised);
  box-shadow: inset 0 0 0 1px rgba(236, 230, 218, .16); }
.pt-part-book .bk-kim-n { position: relative; font: 600 .8em/1.2 var(--pt-text); color: var(--pt-bone); white-space: nowrap; }
.pt-part-book .bk-kst { position: relative; display: grid; justify-items: end; align-items: center; }
.pt-part-book .bk-kst > * { grid-area: 1 / 1; }
.pt-part-book .bk-clashc { padding: .2em .55em; opacity: 0; }
/* Its shadow while it is lifted, and its clay outline in the clash. */
.pt-part-book .bk-kim-in::before,
.pt-part-book .bk-kim-in::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; }
.pt-part-book .bk-kim-in::before { box-shadow: 0 .7em 1.3em rgba(0, 0, 0, .55); }
.pt-part-book .bk-kim-in::after { box-shadow: inset 0 0 0 .12em var(--pt-clay), 0 0 .9em rgba(208, 154, 124, .45); }
/* Booked: the sage tick lands as it drops, and the sage of a booked time
   (solid, so the block reads exactly like the slots booked before it). The
   slot's own Open goes as the block lands on it. */
.pt-part-book .bk-ktick { opacity: 0; transform: scale(.3); transition: opacity .2s ease, transform .5s var(--pt-spring); }
.pt-part-book.pt-s0 .bk-ktick { opacity: 1; transform: none; }
.pt-part-book .bk-kim-ok { position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(rgba(157, 184, 159, .12), rgba(157, 184, 159, .12)), var(--pt-raised);
  box-shadow: inset 0 0 0 1px rgba(157, 184, 159, .22); opacity: 0; transition: opacity .45s ease; }
.pt-part-book.pt-s0 .bk-kim-ok { opacity: 1; }
.pt-part-book .bk-new > .bk-open { transition: opacity .2s ease; }
.pt-part-book.pt-s0 .bk-new > .bk-open { opacity: 0; }
/* The pointer that drags it: it holds the block left of where the Clash chip
   and the tick show, low, so it never covers them. */
.pt-part-book .bk-cur { position: absolute; left: 2.4em; top: 56%; width: 1.05em; height: 1.43em; overflow: visible; opacity: 0;
  fill: var(--pt-bone); stroke: var(--pt-night); stroke-width: 1.1; stroke-linejoin: round; transform-origin: 15% 10%; }
/* The taken time it is dropped on first: a clay ring. */
.pt-part-book .bk-clash::after { content: ""; position: absolute; inset: -.14em; border-radius: .6em; border: .12em solid var(--pt-clay);
  opacity: 0; pointer-events: none; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-kim { animation: bk-drag 3s linear .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-kim-in { animation: bk-lift 3s ease-in-out .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-kim-in::before { animation: bk-lifted 3s linear .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-kim-in::after { animation: bk-clashed 3s linear .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-clashc { animation: bk-clashc 3s linear .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-kim .bk-cur { animation: bk-cur 3s linear .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-clash::after { animation: bk-clashcell 3s linear .3s both; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-ktick,
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-kim-ok { transition-delay: 3.05s; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-new > .bk-open { transition-delay: 2.92s; }
.pt-part-book:not(.bk-quick)[data-step="0"] .bk-ktick::before { animation: bk-ring .7s ease-out 3.1s forwards; }
/* The way: it pops up at the header (0 to 10%), is taken (22%), crosses on a
   curve onto the taken time (52%), stays for the clash (to 75%), snaps down
   one slot with a small overshoot (88%). */
@keyframes bk-drag {
  0% { opacity: 0; transform: translate(var(--kx), var(--ky)) scale(.7); animation-timing-function: cubic-bezier(.2, 1.3, .4, 1); }
  10% { opacity: 1; transform: translate(var(--kx), var(--ky)); }
  22% { opacity: 1; transform: translate(var(--kx), var(--ky)); animation-timing-function: cubic-bezier(.45, 0, .75, .5); }
  37% { transform: translate(calc(var(--kx) * .52), calc(var(--ky) * .36 + var(--k1) * .64)); animation-timing-function: cubic-bezier(.2, .55, .35, 1); }
  52% { transform: translate(0, var(--k1)); }
  75% { transform: translate(0, var(--k1)); animation-timing-function: cubic-bezier(.35, 0, .3, 1.4); }
  88% { transform: translate(0, 0); }
  100% { opacity: 1; transform: none; }
}
/* Lifted while it travels; set down on the taken time, it shakes its head,
   lifts again for the snap, and settles. */
@keyframes bk-lift {
  0%, 21% { transform: none; }
  26%, 51% { transform: scale(1.07); }
  54% { transform: scale(1.01); }
  57% { transform: translateX(-.3em) scale(1.01); }
  61% { transform: translateX(.25em) scale(1.01); }
  65% { transform: translateX(-.15em) scale(1.01); }
  69% { transform: translateX(.06em) scale(1.03); }
  73%, 86% { transform: scale(1.07); }
  91% { transform: scale(.97); }
  100% { transform: none; }
}
@keyframes bk-lifted { 0%, 21% { opacity: 0; } 26%, 51% { opacity: 1; } 55%, 68% { opacity: .35; } 73%, 86% { opacity: 1; } 94%, 100% { opacity: 0; } }
@keyframes bk-clashed { 0%, 52% { opacity: 0; } 55%, 73% { opacity: 1; } 82%, 100% { opacity: 0; } }
@keyframes bk-clashc {
  0%, 53% { opacity: 0; transform: scale(.5); }
  57% { opacity: 1; transform: scale(1.12); }
  61%, 74% { opacity: 1; transform: none; }
  81%, 100% { opacity: 0; transform: scale(.85); }
}
@keyframes bk-clashcell { 0%, 52% { opacity: 0; transform: none; } 55% { opacity: 1; transform: scale(1.03); } 70% { opacity: .9; transform: none; } 82%, 100% { opacity: 0; transform: scale(1.05); } }
/* The pointer comes in, presses to take the block, carries it, lets go. */
@keyframes bk-cur {
  0%, 9% { opacity: 0; transform: translate(.7em, .6em); }
  16% { opacity: 1; transform: none; }
  21% { opacity: 1; transform: none; }
  24% { opacity: 1; transform: scale(.82); }
  27%, 86% { opacity: 1; transform: scale(.9); }
  90% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translate(.5em, .5em); }
}

/* ---------- step 1: only the times near the customer ------------------------- */
/* Tom texts (book.js); the calendar shows who the times are for (his
   postcode), each day takes the postcode the team will be in, and only
   Tuesday's open times, in Tom's area, light up in dusk as offers, their
   Open turning bone; Wednesday, elsewhere, dims. */
.pt-part-book .bk-cust { opacity: 0; transform: scale(.55); transform-origin: 100% 50%; transition: opacity .25s ease, transform .55s var(--pt-spring); }
.pt-part-book.pt-s1 .bk-cust { opacity: 1; transform: none; }
.pt-part-book .bk-sam { opacity: 0; transform: scale(.4); transition: opacity .25s ease, transform .55s var(--pt-spring); }
.pt-part-book.pt-s1 .bk-sam { opacity: 1; transform: none; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-sam { transition-delay: 2.25s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-sam::before { animation: bk-ring .7s ease-out 2.35s forwards; }
.pt-part-book .bk-pc { opacity: 0; transform: translateY(-.25em) scale(1.4); transform-origin: 0 50%;
  transition: opacity .18s ease, transform .42s cubic-bezier(.3, 1.5, .5, 1); }
.pt-part-book.pt-s1 .bk-pc { opacity: 1; transform: none; }
.pt-part-book .bk-lit { position: absolute; inset: -1px; border-radius: inherit; background: rgba(180, 167, 207, .22);
  box-shadow: inset 0 0 0 1px rgba(180, 167, 207, .55), 0 .3em .9em rgba(180, 167, 207, .12); opacity: 0; transition: opacity .35s ease; }
.pt-part-book .bk-lit::after { content: ""; position: absolute; inset: -.2em; border-radius: .62em; border: .12em solid var(--pt-dusk); opacity: 0; pointer-events: none; }
.pt-part-book .bk-offer .bk-slot-t { transition: opacity .35s ease; }
.pt-part-book.pt-s1 .bk-lit,
.pt-part-book.pt-s1 .bk-offer .bk-slot-t { opacity: 1; }
.pt-part-book .bk-c-wed { transition: opacity .5s ease; }
.pt-part-book.pt-s1 .bk-c-wed { opacity: .32; }
.pt-part-book.pt-s1 .bk-dh-wed .bk-pcw { opacity: .5; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-cust { transition-delay: 1s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-cust::before { animation: bk-ring .7s ease-out 1.1s forwards; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-cust .bk-shine::after { animation: bk-shine .9s ease-in-out 1.25s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-dh-tue .bk-pc { transition-delay: 1.65s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-dh-wed .bk-pc { transition-delay: 1.9s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-dh-tue .bk-pc::before { animation: bk-ring .7s ease-out 2.45s forwards; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-dh-tue .bk-shine::after { animation: bk-shine .9s ease-in-out 2.5s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-offer.bk-r0 .bk-lit,
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-offer.bk-r0 .bk-slot-t { transition-delay: 2.6s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-offer.bk-r3 .bk-lit,
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-offer.bk-r3 .bk-slot-t { transition-delay: 2.78s; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-offer.bk-r0 .bk-lit::after { animation: bk-ring-wide .8s ease-out 2.7s forwards; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-offer.bk-r3 .bk-lit::after { animation: bk-ring-wide .8s ease-out 2.88s forwards; }
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-c-wed,
.pt-part-book:not(.bk-quick)[data-step="1"] .bk-dh-wed .bk-pcw { transition-delay: 2.65s; }
/* As the AI offers them in the chat (2), the two times ring again (book.js). */
.pt-part-book.bb-offer:not(.bk-quick) .bk-offer .bk-lit::after { animation: bk-ring-wide .8s ease-out forwards; }
.pt-part-book.bb-offer:not(.bk-quick) .bk-offer.bk-r3 .bk-lit::after { animation-delay: .15s; }

/* ---------- the phone -------------------------------------------------------- */
/* The staff's phone, turned towards the calendar, with its thickness at the
   edge that comes forward. Its screen holds two chats as pages: Tom's, then
   Kim's (4). */
.pt-part-book .bk-phone { position: absolute; left: 23.2em; top: .15em; width: 11.7em; height: 21em; transform-style: preserve-3d; }
.pt-part-book .bk-phone::after { content: ""; position: absolute; left: 10%; right: 10%; top: calc(100% - .8em); height: 1.3em; pointer-events: none;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)); animation: bk-shadow 5.6s ease-in-out -2s infinite; }
.pt-part-book .bk-pfloat { position: absolute; inset: 0; transform-style: preserve-3d; animation: bk-bob 5.6s ease-in-out -2s infinite; }
.pt-part-book .bk-pdev { position: absolute; inset: 0; transform-style: preserve-3d; transform: rotateY(-13deg) rotateX(3deg); }
.pt-part-book .bk-pside { position: absolute; left: 100%; top: 1.5em; bottom: 1.5em; width: .6em; margin-left: -.06em; border-radius: .3em;
  background: linear-gradient(180deg, #2E3A34, #1C2420 50%, #2A3530); transform-origin: 0 50%; transform: rotateY(90deg); }
.pt-part-book .bk-pbody { position: absolute; inset: 0; border-radius: 1.6em;
  background: linear-gradient(160deg, #2A3530, #18201C 38%, #151C19);
  box-shadow: inset 0 0 0 1px rgba(236, 230, 218, .09), inset 0 1px 0 rgba(236, 230, 218, .16), 0 1.4em 2.6em rgba(0, 0, 0, .45); }
.pt-part-book .bk-screen { position: absolute; inset: .34em; overflow: hidden; border-radius: 1.3em;
  background: radial-gradient(120% 60% at 30% 0%, rgba(180, 167, 207, .07), rgba(180, 167, 207, 0) 60%), #0A0E0C; }
.pt-part-book .bk-island { position: absolute; z-index: 3; top: .55em; left: 50%; width: 2.7em; height: .78em; margin-left: -1.35em; border-radius: 1em; background: #000; }
/* The pages, stacked in one cell: Tom's is up, Kim's waits below until it
   turns up in front (4). */
.pt-part-book .bk-pages { position: absolute; inset: 0; display: grid; grid-template: minmax(0, 1fr) / minmax(0, 1fr); perspective: 40em; transition: opacity .35s ease; }
.pt-part-book .bk-pg { grid-area: 1 / 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; padding-top: 1.75em;
  transition: opacity .3s ease, transform .6s var(--pt-spring); }
.pt-part-book .bk-pg-kim { opacity: 0; transform: translate3d(0, .9em, 0) rotateX(-20deg); }
.pt-part-book.pt-s4 .bk-pg-sam { opacity: 0; transform: translate3d(0, -.7em, 0) rotateX(20deg); }
.pt-part-book.pt-s4 .bk-pg-kim { opacity: 1; transform: none; }

/* The chat's header: who, who is answering (the AI's chip, or the person
   who took over) on the right, and under them the customer's address, the
   whole width (the phone is narrow: beside the badge it was cut). */
.pt-part-book .bk-chd { flex: 0 0 auto; display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; grid-template-areas: "av name . who" "addr addr addr addr";
  column-gap: .4em; row-gap: .2em; align-items: center; align-content: center; height: 3.4em; padding: 0 .6em .5em; box-shadow: 0 1px 0 rgba(236, 230, 218, .08); }
.pt-part-book .bk-chd-kim { grid-template-areas: "av name . who"; }
.pt-part-book .bk-chd > .bk-av { width: 2.1em; height: 2.1em; }
.pt-part-book .bk-name { grid-area: name; font: 500 .84em/1.2 var(--pt-head); letter-spacing: -.01em; color: var(--pt-bone); white-space: nowrap; }
.pt-part-book .bk-who { grid-area: who; display: grid; justify-items: end; align-items: center; perspective: 9em; }
.pt-part-book .bk-who > * { grid-area: 1 / 1; }
.pt-part-book .bk-who .bk-chip { padding: .24em .6em; }
.pt-part-book .bk-lai,
.pt-part-book .bk-maria { transition: transform .5s var(--pt-spring), opacity .25s ease; }
.pt-part-book .bk-maria { opacity: 0; transform: rotateX(-90deg); }
.pt-part-book .bk-addr { grid-area: addr; display: flex; align-items: center; gap: .3em; min-width: 0; font: 500 .8em/1.25 var(--pt-text); color: var(--pt-lichen); white-space: nowrap; }
.pt-part-book .bk-mark { position: relative; flex: 0 0 auto; display: grid; place-items: center; width: 1.05em; height: 1.05em; }
.pt-part-book .bk-mark > * { grid-area: 1 / 1; }

/* The thread's window: whatever goes over its top has faded already. */
.pt-part-book .bk-win { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.pt-part-book .bk-feed { position: relative; display: flex; flex-direction: column; gap: .42em; padding: .5em .55em 0;
  transition: transform .5s cubic-bezier(.25, .75, .3, 1); }
/* An item: in the thread (is-in) takes its place, arrived (is-on) shows,
   gone over the top (is-gone) fades out. */
.pt-part-book .bk-it { display: none; position: relative; max-width: 88%;
  opacity: 0; transform: translateY(.7em) scale(.94); transition: opacity .3s ease, transform .5s var(--pt-spring); }
.pt-part-book .bk-it.is-in { display: block; }
.pt-part-book .bk-it.is-on { opacity: 1; transform: none; }
.pt-part-book .bk-it.is-gone { opacity: 0; transition-duration: .18s, .5s; }   /* out before the climb takes it under the edge */
.pt-part-book .bk-out,
.pt-part-book .bk-in { padding: .48em .72em .52em; border-radius: 1em; font: 500 .82em/1.32 var(--pt-text); color: var(--pt-bone); }
.pt-part-book .bk-out { align-self: flex-end; border-bottom-right-radius: .3em; background: rgba(180, 167, 207, .2); transform-origin: 100% 100%; }
.pt-part-book .bk-in { align-self: flex-start; border-bottom-left-radius: .3em; background: rgba(236, 230, 218, .09); transform-origin: 0 100%; }
.pt-part-book .bk-sys { align-self: center; max-width: none; transform-origin: 50% 50%; }
.pt-part-book .bk-tx { display: block; }
.pt-part-book .bk-ty { position: absolute; inset: .48em .72em .52em; }
.pt-part-book .bk-out.is-ty .bk-tx { visibility: hidden; }
/* A person's line (Maria, once she has taken over): outgoing like the AI's,
   but in a warm neutral with her name over it in her dusk, so it reads
   apart from his. Its text is typed over the finished one the same way. */
.pt-part-book .bk-staff { background: rgba(236, 230, 218, .13); }
.pt-part-book .bk-by { display: block; margin-bottom: .22em; font-weight: 700; color: var(--pt-dusk); white-space: nowrap; }   /* the air under it holds through the phone's tilt at every zoom */
.pt-part-book .bk-txw { position: relative; display: block; }
.pt-part-book .bk-txw .bk-ty { inset: 0; }
/* A typing caret (the line being typed only). */
.pt-part-book .bk-ty.is-typing::after { content: ""; display: inline-block; width: 2px; height: 1.05em; margin-left: 1px; vertical-align: -.17em;
  background: var(--pt-dusk); animation: bk-caret .9s linear infinite; }
@keyframes bk-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
/* The AI thinking: three dusk dots on its side, its chip's light pulsing. */
.pt-part-book .bk-think { display: none; align-self: flex-end; align-items: center; gap: .3em; padding: .62em .86em; border-radius: 1em; border-bottom-right-radius: .3em;
  background: rgba(180, 167, 207, .14); opacity: 0; transform: translateY(.5em) scale(.9); transform-origin: 100% 100%;
  transition: opacity .25s ease, transform .45s var(--pt-spring); }
.pt-part-book .bk-think.is-in { display: flex; }
.pt-part-book .bk-think.is-on { opacity: 1; transform: none; }
.pt-part-book .bk-think i { width: .42em; height: .42em; border-radius: 50%; background: var(--pt-dusk); opacity: .45; }
.pt-part-book .bk-think.is-on i { animation: bk-dot 1s ease-in-out infinite; }
.pt-part-book .bk-think.is-staff { background: rgba(236, 230, 218, .1); }   /* a person typing: neutral dots */
.pt-part-book .bk-think.is-staff i { background: var(--pt-bone); }
.pt-part-book .bk-think i:nth-child(2) { animation-delay: .15s; }
.pt-part-book .bk-think i:nth-child(3) { animation-delay: .3s; }
@keyframes bk-dot { 0%, 60%, 100% { opacity: .45; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-.22em); } }
.pt-part-book.bb-think .bk-pg-sam .bk-lai .bk-led { animation: bk-led .8s ease-in-out infinite; }

/* The foot of the chat: Take over while the AI answers; once taken, a box to
   write in; locked once the customer has opted out. */
.pt-part-book .bk-cmp { position: relative; flex: 0 0 auto; display: grid; align-items: center; justify-items: center; height: 2.85em; padding: .3em .6em .55em; }
.pt-part-book .bk-cmp > * { grid-area: 1 / 1; }
.pt-part-book .bk-take { transition: opacity .25s ease, transform .3s ease; }
.pt-part-book .bk-input { justify-self: stretch; display: flex; align-items: center; justify-content: space-between; gap: .4em; height: 2em; padding: 0 .28em 0 .8em;
  border-radius: 999px; background: rgba(236, 230, 218, .06); box-shadow: inset 0 0 0 1px rgba(236, 230, 218, .1);
  opacity: 0; transform: translateY(.4em); transition: opacity .3s ease, transform .45s var(--pt-spring); }
.pt-part-book .bk-input > span { font: 500 .8em/1.2 var(--pt-text); color: var(--pt-lichen); white-space: nowrap; }
.pt-part-book .bk-send { position: relative; flex: 0 0 auto; width: 1.45em; height: 1.45em; border-radius: 50%; background: var(--pt-dusk); }
.pt-part-book .bk-send::after { content: ""; position: absolute; left: 50%; top: 50%; width: .42em; height: .42em; margin: -.1em 0 0 -.21em;
  border: solid var(--pt-night); border-width: .13em 0 0 .13em; transform: rotate(45deg); }
.pt-part-book .bk-lockc { padding: .42em .95em; opacity: 0; transform: scale(.55); transition: opacity .25s ease, transform .55s var(--pt-spring); }

/* ---------- step 2: the address first, then the times ------------------------ */
/* The AI asks Tom to confirm his address (typed, book.js), he says yes, the
   pin by the address in the header turns into a sage tick (book.js holds it
   with bb-ask until then), and only then are the times offered. */
.pt-part-book .bk-addr .bk-pin { transition: opacity .25s ease, transform .35s ease; }
.pt-part-book .bk-atick { width: 1em; height: 1em; opacity: 0; transform: scale(.3); transition: opacity .2s ease, transform .5s var(--pt-spring); }
.pt-part-book .bk-atick::after { left: .35em; top: .18em; width: .25em; height: .48em; border-width: 0 .12em .12em 0; }
.pt-part-book.pt-s2:not(.bb-ask) .bk-addr .bk-pin { opacity: 0; transform: rotate(-45deg) scale(.5); }
.pt-part-book.pt-s2:not(.bb-ask) .bk-atick { opacity: 1; transform: none; }
.pt-part-book[data-step="2"]:not(.bb-ask):not(.bk-quick) .bk-atick::before { animation: bk-ring .7s ease-out .15s forwards; }

/* ---------- step 3: a person takes over ---------------------------------------- */
/* Dimitar, 02/10/2026: "visual click on the take over -> then 'Manager:
   ...'", then "not a pointer but a radiating out circle". Take over is
   tapped like a phone screen: the button squeezes, a filled circle blooms
   at its centre and three rings radiate out from it and fade; the box to
   write in comes up, the chip turns over from the AI to Maria, she joins in
   the thread and writes to Tom (book.js), Ai steps back. */
.pt-part-book.pt-s3 .bk-pg-sam .bk-take { opacity: 0; transform: scale(.85); }
.pt-part-book.pt-s3 .bk-pg-sam .bk-input { opacity: 1; transform: none; }
.pt-part-book.pt-s3 .bk-pg-sam .bk-lai { opacity: 0; transform: rotateX(90deg); }
.pt-part-book.pt-s3 .bk-pg-sam .bk-maria { opacity: 1; transform: none; }
/* The tap: centred on the button (a point in the foot's one cell, centred
   like the button), round circles of 2.6 em, the rings ending at .95 of it:
   1.24 em from the centre, inside the screen's foot (1.37 em below the
   centre on a phone, 1.55 on desktop), so the screen never cuts them.
   Siblings of the button, so they keep spreading as it fades. */
.pt-part-book .bk-taps { position: relative; align-self: center; justify-self: center; width: 0; height: 0; pointer-events: none; }
.pt-part-book .bk-taps i { position: absolute; left: -1.3em; top: -1.3em; width: 2.6em; height: 2.6em; border-radius: 50%; opacity: 0; }
.pt-part-book .bk-tapf { background: rgba(236, 230, 218, .5); }
.pt-part-book .bk-rip { border: .17em solid var(--pt-bone); }
@keyframes bk-tapf { 0% { opacity: 1; transform: scale(.25); } 100% { opacity: 0; transform: scale(.8); } }
@keyframes bk-rip { 0% { opacity: 1; transform: scale(.3); } 60% { opacity: .75; } 100% { opacity: 0; transform: scale(.95); } }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-pg-sam .bk-take { animation: bk-press .4s ease-out .62s; transition-delay: 1.05s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-tapf { animation: bk-tapf .55s ease-out .68s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-rip1 { animation: bk-rip .75s ease-out .72s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-rip2 { animation: bk-rip .75s ease-out .88s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-rip3 { animation: bk-rip .75s ease-out 1.04s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-pg-sam .bk-input { transition-delay: 1.2s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-pg-sam .bk-lai { transition-delay: 1.1s; }
.pt-part-book:not(.bk-quick)[data-step="3"] .bk-pg-sam .bk-maria { transition-delay: 1.25s; }
.pt-part-book:not(.bk-quick) .bk-sys.is-on .bk-chip::before { animation: bk-ring .7s ease-out .15s forwards; }
.pt-part-book:not(.bk-quick) .bk-sys.is-on .bk-shine::after { animation: bk-shine .9s ease-in-out .3s; }

/* ---------- step 4: STOP, honoured at once ------------------------------------ */
/* The page turns to Kim's chat (the phone swings a little); her STOP comes
   in and at once the chat locks: Take over goes, Opted out lands, the AI's
   chip goes dim. Nothing more is sent. */
.pt-part-book .bk-stop { font-weight: 700; letter-spacing: .08em;
  opacity: 0; transform: translateY(.7em) scale(.94); transition: opacity .3s ease, transform .5s var(--pt-spring); }
.pt-part-book.pt-s4 .bk-stop { opacity: 1; transform: none; }
.pt-part-book .bk-pg-kim .bk-take { transition: opacity .2s ease, transform .3s ease; }
.pt-part-book.pt-s4 .bk-pg-kim .bk-take { opacity: 0; transform: scale(.85); }
.pt-part-book.pt-s4 .bk-lockc { opacity: 1; transform: none; }
.pt-part-book .bk-pg-kim .bk-lai { transition: opacity .35s ease; }
.pt-part-book.pt-s4 .bk-pg-kim .bk-lai { opacity: .4; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-pg-kim { transition-delay: .2s; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-pdev { animation: bk-swing 1s ease-in-out; }
@keyframes bk-swing { 40% { transform: rotateY(-19deg) rotateX(4.5deg) translateZ(-.3em); } }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-stop { transition-delay: 1.1s; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-pg-kim .bk-take { transition-delay: 1.35s; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-lockc { transition-delay: 1.4s; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-lockc::before { animation: bk-ring .7s ease-out 1.5s forwards; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-lockc .bk-shine::after { animation: bk-shine .9s ease-in-out 1.65s; }
.pt-part-book:not(.bk-quick)[data-step="4"] .bk-pg-kim .bk-lai { transition-delay: 1.45s; }

/* ---------- the rewind: the pages and the calendar's contents fade, the set stays */
.pt-part-book.is-rewind .bk-pages,
.pt-part-book.is-rewind .bk-dbody,
.pt-part-book.is-rewind .bk-cust { opacity: 0; }

/* ---------- the steps under the scene ---------------------------------------- */
/* Desktop: small floating pills in a compact wrap; the one in play is lit in
   dusk, the layer's tone. */
.pt-part-book .pt-part-steps { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 12px 0 0; padding: 0; list-style: none; }
.pt-part-book .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: bk-pill 6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -1.2s); }
.pt-part-book .pt-part-steps li::before { content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--tone, var(--pt-dusk)); 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-book .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(180, 167, 207, .55), rgba(180, 167, 207, 0) 15px), rgba(236, 230, 218, .07);
  opacity: 0; transition: opacity .35s ease; }
.pt-part-book .pt-part-steps li > span { opacity: .7; transition: opacity .3s ease; }
.pt-part-book .pt-part-steps li.is-on::before { opacity: 1; transform: scale(1.2); }
.pt-part-book .pt-part-steps li.is-on::after,
.pt-part-book .pt-part-steps li.is-on > span { opacity: 1; }
.pt-part-book .pt-part-steps li:focus-visible { outline: 2px solid var(--pt-sand); outline-offset: 3px; }
@keyframes bk-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-book .bk-dfloat,
.pt-layer:not(.is-current) .pt-part-book .bk-pfloat,
.pt-layer:not(.is-current) .pt-part-book .bk-diary::after,
.pt-layer:not(.is-current) .pt-part-book .bk-phone::after,
.pt-layer:not(.is-current) .pt-part-book .bk-led,
.pt-layer:not(.is-current) .pt-part-book .bk-think i,
.pt-layer:not(.is-current) .pt-part-book .bk-ty::after,
.pt-layer:not(.is-current) .pt-part-book .pt-part-steps li { animation-play-state: paused; }

/* ---------- the lg column (992 to 1199, 444 wide): the steps as dots ---------- */
/* Five pills would stack four deep here; as in Control, 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-book .pt-part-steps { position: relative; flex-wrap: nowrap; justify-content: center; gap: 0; height: 50px; margin-top: 12px; }
  html.js .pt-part-book .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-book .pt-part-steps li::after { display: none; }
  html.js .pt-part-book .pt-part-steps li.is-on::before { transform: scale(1.45); }
  html.js .pt-part-book .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-book .pt-part-steps li.is-on > span { opacity: 1; transform: none; pointer-events: auto; }
  html.js .pt-part-book[data-step="-1"] .pt-part-steps li:first-child > span { opacity: .5; transform: none; }
}

/* ---------- phones: short ones (360x640, 375x667) -------------------------- */
/* With the layer's copy above (228 px), 259 px are left for the whole
   component, clear of the arrow (measured: 264 at 360x640, 259 at 375x667).
   So the same layout at a fixed 12.5px unit, 221 px tall, 246 with the
   caption: a copy a few px taller on a real phone still clears the arrow.
   Smaller Ai, the calendar and the phone tightened, the months and suburbs
   gone (the postcodes say it), Tom's chip in the header (no room beside the
   title) traded for his badge on his day, the cards turned less (a rising
   layer is wider at its foot). The steps become one line: five dots and the
   caption of the one in play. */
@media (max-width: 575.98px) {
  .pt-part-book .pt-part-stage { font-size: 12.5px; perspective: 900px; perspective-origin: 50% 40%; }
  .pt-part-book .bk-set { width: 25.6em; height: 17.7em; }
  .pt-part-book .bk-set::before { background:
      radial-gradient(40% 30% at 29% 80%, rgba(180, 167, 207, .10), rgba(180, 167, 207, 0) 72%),
      radial-gradient(22% 34% at 80% 60%, rgba(147, 183, 198, .10), rgba(147, 183, 198, 0) 72%); }
  .pt-part-book .bk-ai { left: .1em; top: .1em; width: 3.55em; transform: translateZ(.7em); }
  .pt-part-book .bk-ai .pt-char-ai { animation-name: bk-hover-sm; }
  .pt-part-book .bk-say { left: 4.15em; top: .2em; width: 10.45em; transform: translateZ(.5em); }
  .pt-part-book .bk-say .pt-bubble { padding: .58em .78em; font-size: .82em; }
  .pt-part-book .bk-say .pt-bubble::before { top: calc(1.15em - 6px); }
  .pt-part-book .bk-diary { top: 5.3em; width: 14.6em; height: 12.3em; }
  .pt-part-book .bk-diary::after { top: calc(100% - .7em); height: 1em; }
  .pt-part-book .bk-dfloat,
  .pt-part-book .bk-pfloat { animation-name: bk-bob-sm; }   /* a smaller rise: Ai's air above the calendar holds */
  .pt-part-book .bk-dcard { --pt: .55em; --px: .6em; --hd: 1.65em; --hm: .3em; --dh: 2.55em; --tc: 2.3em; --cg: .28em; --rh: 1.42em; --rg: .2em;
    padding-bottom: .5em; border-radius: .85em; transform: rotateY(4deg) rotateX(3deg); }
  .pt-part-book .bk-dhd-t { font-size: .84em; }
  .pt-part-book .bk-cust { display: none; }
  .pt-part-book .bk-sam { display: flex; }
  .pt-part-book .bk-kim { --ky: var(--k1); }
  .pt-part-book .bk-date { font-size: .8em; }
  .pt-part-book .bk-dh { gap: .18em; }
  .pt-part-book .bk-mon,
  .pt-part-book .bk-sub { display: none; }
  .pt-part-book .bk-slot { padding: 0 .45em; border-radius: .45em; }
  .pt-part-book .bk-chip { padding: .25em .62em; }
  .pt-part-book .bk-kim-in { padding: 0 .24em 0 .45em; }
  .pt-part-book .bk-cur { left: 1.75em; }
  .pt-part-book .bk-clashc { padding: .16em .45em; }
  .pt-part-book .bk-phone { left: 15.2em; top: .1em; width: 10.4em; height: 17.5em; }
  .pt-part-book .bk-phone::after { top: calc(100% - .6em); height: 1em; }
  .pt-part-book .bk-pdev { transform: rotateY(-8deg) rotateX(3deg); }
  .pt-part-book .bk-pbody { border-radius: 1.45em; }
  .pt-part-book .bk-screen { inset: .3em; border-radius: 1.2em; }
  .pt-part-book .bk-island { top: .45em; width: 2.4em; height: .7em; margin-left: -1.2em; }
  .pt-part-book .bk-pg { padding-top: 1.45em; }
  .pt-part-book .bk-chd { height: 3.05em; padding: 0 .45em .42em; column-gap: .25em; row-gap: .1em; }
  .pt-part-book .bk-chd > .bk-av { width: 1.9em; height: 1.9em; }
  .pt-part-book .bk-name { font-size: .8em; }
  .pt-part-book .bk-who .bk-chip { padding: .2em .5em; }
  .pt-part-book .bk-who .bk-led { display: none; }   /* no room beside the name: the chip's words and colour say it */
  .pt-part-book .bk-feed { gap: .36em; padding: .42em .42em 0; }
  .pt-part-book .bk-it { max-width: 95%; }   /* so the offer holds two lines in any month ("Tue 28 May" is the widest) */
  .pt-part-book .bk-out,
  .pt-part-book .bk-in { padding: .42em .56em .46em; font-size: .8em; }
  .pt-part-book .bk-ty { inset: .42em .56em .46em; }
  .pt-part-book .bk-cmp { height: 2.5em; padding: .22em .45em .45em; }
  .pt-part-book .bk-btn { padding: .42em 1.1em; }
  .pt-part-book .bk-input { height: 1.85em; }
  .pt-part-book .bk-lockc { padding: .36em .8em; }
}
@keyframes bk-hover-sm { 0%, 100% { translate: 0 0; } 50% { translate: 0 -4px; } }
@keyframes bk-bob-sm { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-.2em); } }
/* 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-book .pt-part-steps { position: relative; flex-wrap: nowrap; justify-content: flex-start; gap: 0; height: 22px; margin-top: 3px; }
  html.js .pt-part-book .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-book .pt-part-steps li::after { display: none; }
  html.js .pt-part-book .pt-part-steps li::before { width: 6px; height: 6px; }
  html.js .pt-part-book .pt-part-steps li.is-on::before { transform: scale(1.5); }
  html.js .pt-part-book .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-book .pt-part-steps li.is-on > span { opacity: 1; transform: none; pointer-events: auto; }
  html.js .pt-part-book[data-step="-1"] .pt-part-steps li:first-child > span { opacity: .5; transform: none; }
}
/* Very short phones (360x640): the heading takes three lines there, so the
   copy is 257 px and 235 px are left for the whole component clear of the
   arrow (measured 02/10/2026 with "Bookings, automated by AI or by staff.").
   A tighter cut of the same layout, 228 px with the caption: Ai a little
   smaller, the slots a little lower, the phone without its notch and its
   thread packed closer, so the end of step 2 still shows the question, the
   yes and the offer. */
@media (max-width: 575.98px) and (max-height: 660px) {
  .pt-part-book .bk-set { height: 16.5em; }
  .pt-part-book .bk-ai { top: 0; width: 3.15em; }
  .pt-part-book .bk-say { left: 3.85em; top: .1em; width: 10.75em; }
  .pt-part-book .bk-say .pt-bubble::before { top: calc(1.35em - 6px); }
  .pt-part-book .bk-diary { top: 4.7em; height: 11.75em; }
  .pt-part-book .bk-dcard { --rh: 1.34em; }
  .pt-part-book .bk-phone { height: 16.35em; }
  .pt-part-book .bk-island { display: none; }
  .pt-part-book .bk-pg { padding-top: .95em; }
  .pt-part-book .bk-cmp { height: 2.4em; }
  .pt-part-book .bk-feed { gap: .3em; padding-top: .3em; }
  .pt-part-book .bk-out,
  .pt-part-book .bk-in { padding-top: .38em; padding-bottom: .42em; }
  .pt-part-book .bk-ty { inset: .38em .56em .42em; }
  html.js .pt-part-book .pt-part-steps { height: 20px; margin-top: 2px; }
  html.js .pt-part-book .pt-part-steps li { height: 20px; }
  html.js .pt-part-book .pt-part-steps li > span { line-height: 20px; }
}
/* Tall phones (390x844 leaves about 416 px below the copy): the same layout
   with the unit from the column's width, a bigger Ai, roomier slots and a
   taller phone, so the whole of Tom's thread shows. After the phone rules,
   which it overrides. */
@media (max-width: 575.98px) and (min-height: 760px) {
  .pt-part-book .pt-part-stage { font-size: max(12.5px, min(13.6px, calc(100cqw / 25.6))); }
  .pt-part-book .bk-set { height: 22.6em; }
  .pt-part-book .bk-ai { width: 4.3em; }
  .pt-part-book .bk-say { left: 4.95em; top: .45em; width: 9.65em; }
  .pt-part-book .bk-say .pt-bubble { font-size: .86em; padding: .62em .82em; }
  .pt-part-book .bk-say .pt-bubble::before { top: calc(1.4em - 6px); }
  .pt-part-book .bk-diary { top: 6.5em; height: 15.9em; }
  .pt-part-book .bk-dcard { --pt: .7em; --hd: 1.85em; --hm: .4em; --dh: 2.75em; --rh: 1.95em; --rg: .32em; }
  .pt-part-book .bk-phone { height: 22.4em; }
  .pt-part-book .bk-pg { padding-top: 1.6em; }
  .pt-part-book .bk-chd { height: 3em; }
}

/* ---------- instant draws (book.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. Ai's wrapper is not a
   .bk-mv (the snap would stop his own bob inside it): it has its own. */
.pt-part-book.bk-quick .bk-mv { transition-duration: .3s; transition-delay: 0s; animation: none; }
.pt-part-book.bk-quick .bk-mv > *,
.pt-part-book.bk-quick .bk-mv::before,
.pt-part-book.bk-quick .bk-mv::after { transition-delay: 0s; animation: none; }
.pt-part-book.bk-quick .bk-it,
.pt-part-book.bk-quick .bk-think { transition-duration: .3s; transition-delay: 0s; }
.pt-part-book.bk-quick .bk-ai-in { transition-duration: .3s; transition-delay: 0s; }
.pt-part-book.bk-snap .bk-mv,
.pt-part-book.bk-snap .bk-mv *,
.pt-part-book.bk-snap .bk-mv::before,
.pt-part-book.bk-snap .bk-mv::after,
.pt-part-book.bk-snap .bk-ai-in { transition: none; animation: none; }
