/* Sable Story: the eight product cards in motion (SAB-1253).
   cards.js plays one card at a time, only while it is the active feature and on screen.
   With no data attributes set, every card rests in a finished, readable state,
   which is also what reduced motion shows. Sizes are in em so cards scale with the stage. */

.ui[data-ui] { overflow: hidden; }

/* two labels in one place; data-alt="1" on the visual swaps them */
.swap { display: inline-grid; }
.swap b { grid-area: 1 / 1; font: inherit; color: inherit; transition: opacity .45s var(--ease), transform .55s var(--ease-out); }
.swap b + b { opacity: 0; transform: translateY(45%); }
[data-alt="1"] .swap b:first-child { opacity: 0; transform: translateY(-45%); }
[data-alt="1"] .swap b + b { opacity: 1; transform: none; }

/* a small segmented control; data-seg moves the thumb */
.seg { position: relative; display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; padding: .22em; border-radius: 99px; background: var(--muted); font-size: .8em; line-height: 1; }
.seg i { position: relative; z-index: 1; font-style: normal; font-weight: 500; text-align: center; padding: .5em .95em; color: var(--ink-3); transition: color .4s var(--ease); }
.seg u { position: absolute; top: .22em; bottom: .22em; left: .22em; width: calc((100% - .44em) / 2); border-radius: 99px; background: var(--card); box-shadow: 0 1px 3px rgba(8,15,8,.14); transition: transform .65s cubic-bezier(.65, 0, .2, 1); }
.seg--3 u { width: calc((100% - .44em) / 3); }
[data-seg="1"] .seg u { transform: translateX(100%); }
[data-seg="2"] .seg u { transform: translateX(200%); }
.fvis:not([data-seg]) .seg i:first-child, [data-seg="0"] .seg i:nth-child(1), [data-seg="1"] .seg i:nth-child(2), [data-seg="2"] .seg i:nth-child(3) { color: var(--ink); }

/* ───────── 1. appointments: the day opens out into the week ───────── */

.cal { position: relative; height: 17.7em; }
.cal__hours li { position: absolute; left: 0; top: var(--y); line-height: 1; transition: opacity .4s var(--ease); }
.cal__hours span { font-size: .82em; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.cal__days { position: absolute; left: 0; top: 0; display: grid; grid-template-columns: repeat(5, 4em); column-gap: .5em; opacity: 0; transform: translateY(-.5em); transition: opacity .5s var(--ease) .25s, transform .6s var(--ease-out) .25s; }
.cal__days li { font-size: .78em; line-height: 1; font-weight: 500; color: var(--ink-3); text-align: center; }
.cal__days li:nth-child(2) { color: var(--ink); }
.ap {
  position: absolute; left: var(--dx); top: var(--dy); width: var(--dw); height: var(--dh);
  border-radius: 1em; overflow: hidden;
  transition-property: left, top, width, height, border-radius, opacity, transform;
  transition-duration: .95s, .95s, .95s, .95s, .95s, .5s, .7s;
  transition-timing-function: cubic-bezier(.65, 0, .2, 1);
  transition-delay: calc(var(--n, 0) * 55ms);
}
.ap--a { background: var(--pistachio); }
.ap--b { background: var(--accent); }
.ap--c { background: var(--muted); }
.ap--open { background: none; box-shadow: inset 0 0 0 1.5px var(--line); color: var(--ink-3); }
.ap__full { position: absolute; inset: 0; padding: .8em 1em; display: grid; align-content: start; gap: .1em; white-space: nowrap; transition: opacity .3s var(--ease); }
.ap__full span { font-size: .88em; color: var(--ink-2); }
.ap--a .ap__full span { color: #1c3517; }
.ap__full .chip { position: absolute; right: .8em; top: .8em; }
.ap--open .ap__full { align-content: center; font-size: .9em; }
.ap__mini { position: absolute; left: .55em; top: .45em; font-size: .7em; line-height: 1; font-weight: 600; color: var(--ink); opacity: 0; transition: opacity .35s var(--ease); }
.ap--x { opacity: 0; transform: scale(.4); }
[data-alt="1"] .ap { left: var(--wx); top: var(--wy); width: var(--ww); height: var(--wh); border-radius: .55em; }
[data-alt="1"] .ap__full { opacity: 0; }
[data-alt="1"] .ap__mini { opacity: 1; transition-delay: .6s; }
[data-alt="1"] .ap--x { opacity: 1; transform: none; transition-delay: calc(.3s + var(--n) * 45ms); }
[data-alt="1"] .cal__hours li { opacity: 0; }
[data-alt="1"] .cal__days { opacity: 1; transform: none; }

/* ───────── 2. point of sale: ticket, sent to the reader, paid ─────────
   The card keeps one height through all three states. On the ticket the button sits at the foot
   of the card; the reader and the paid mark sit in the middle of it. */
.ui--pos { height: 24.4em; }
.pos__ticket { height: 100%; display: flex; flex-direction: column; transition: opacity .4s var(--ease), transform .6s var(--ease-out); }
.pos__slot { height: 3.2em; margin-top: auto; }
.pos__wait, .pos__paid { position: absolute; inset: 0; display: grid; justify-items: center; align-content: start; gap: .4em; opacity: 0; transform: translateY(.8em); transition: opacity .45s var(--ease), transform .6s var(--ease-out); pointer-events: none; }
.pos__wait { padding-top: 15.4em; }
.pos__paid { padding-top: 14em; }
.state-h { font: 700 1.5em/1 var(--font-ui-display); letter-spacing: -0.05em; color: var(--ink); }
.state-amt { font: 700 2.5em/1 var(--font-ui-display); letter-spacing: -0.05em; color: var(--ink); font-variant-numeric: tabular-nums; margin-top: .1em; }

/* the reader, breathing: the same three rings, scales, opacities and timing as the app's ReaderPulse */
.pulse { position: absolute; left: 50%; top: 9em; width: 0; height: 0; }
.pulse span { position: absolute; left: -3.7em; top: -3.7em; width: 7.4em; height: 7.4em; border-radius: 50%; background: var(--pistachio); opacity: 0; }
[data-phase="wait"] .pulse span { animation: reader-pulse 2.1s cubic-bezier(0, 0, .58, 1) infinite; animation-delay: var(--d); }
@keyframes reader-pulse { 0% { transform: scale(1); opacity: var(--o); } 100% { transform: scale(var(--s)); opacity: 0; } }

.pos__morph {
  position: absolute; left: var(--bx, 1.5em); top: var(--by, calc(100% - 4.7em)); width: var(--bw, 22em); height: var(--bh, 3.2em);
  border-radius: 1.6em; background: var(--ink); color: #fff;
  overflow: hidden;
  transition-property: left, top, width, height, border-radius, background-color, box-shadow, transform;
  transition-duration: .8s; transition-timing-function: cubic-bezier(.65, 0, .2, 1);
}
.pos__morph > * { position: absolute; left: 50%; top: 50%; translate: -50% -50%; transition: opacity .3s var(--ease), scale .5s var(--ease-out); }
.pos__label { display: inline-flex; align-items: center; gap: .6em; font-weight: 600; font-size: .95em; white-space: nowrap; }
.pos__label svg { width: 1.15em; height: 1.15em; }
.pos__morph img { height: 4.7em; width: auto; max-width: none; opacity: 0; scale: .7; }
.pos__ok { width: 2.7em; height: 2.7em; color: var(--on-pistachio); opacity: 0; }
.pos__ok svg { display: block; width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }

/* Coming back round from "paid": the paid words leave first, then the ticket and the button's label
   arrive, so the two never sit on top of each other. */
[data-phase="ticket"] .pos__ticket { transition-delay: .3s; }
[data-phase="ticket"] .pos__label { transition-delay: .55s; }
[data-phase="press"] .pos__morph { transform: scale(.97); transition-duration: .18s; }
[data-phase="wait"] .pos__ticket, [data-phase="paid"] .pos__ticket { opacity: 0; transform: translateY(-.8em); }
[data-phase="wait"] .pos__morph { left: calc(50% - 3.7em); top: 5.3em; width: 7.4em; height: 7.4em; border-radius: 3.7em; background: var(--card); box-shadow: 0 .3em 1em rgba(8,15,8,.1); }
[data-phase="wait"] .pos__label, [data-phase="paid"] .pos__label { opacity: 0; }
[data-phase="wait"] .pos__morph img { opacity: 1; scale: 1; transition-delay: .45s; }
[data-phase="wait"] .pos__wait { opacity: 1; transform: none; transition-delay: .35s; }
[data-phase="paid"] .pos__morph { left: calc(50% - 2.9em); top: 6.2em; width: 5.8em; height: 5.8em; border-radius: 2.9em; background: var(--pistachio); transition-duration: .6s; }
[data-phase="paid"] .pos__ok { opacity: 1; }
[data-phase="paid"] .pos__ok svg { stroke-dashoffset: 0; transition: stroke-dashoffset .45s var(--ease) .35s; }
[data-phase="paid"] .pos__paid { opacity: 1; transform: none; transition-delay: .25s; }

/* ───────── 3. invoices: the invoice folds into a paper plane and flies out of the frame ─────────
   The selectors start with .fvis.is-active so they outrank the page's own card rule
   (.fvis.is-active .ui sets transform and opacity); without that the plane can fold but never move. */
.ui--invoice { height: 22.6em; transform-origin: 50% 50%; }
.chip--draft { background: var(--muted); color: var(--ink-3); }
.inv__sheet, .inv__sent { transition: opacity .3s var(--ease); }
.inv__sheet { position: absolute; inset: 0; padding: inherit; opacity: 0; pointer-events: none; }
.inv__btn { display: flex; align-items: center; justify-content: center; gap: .6em; height: 3.2em; border-radius: 99px; background: var(--ink); color: #fff; font-weight: 600; font-size: .95em; transition: transform .18s var(--ease); }
.inv__btn svg { width: 1.15em; height: 1.15em; }
.inv__chip { display: inline-grid; }
.inv__chip b { grid-area: 1 / 1; font: inherit; color: inherit; transition: opacity .35s var(--ease); }
.inv__chip b:first-child { opacity: 0; }
.ui--invoice::after { content: ""; position: absolute; inset: 0; background: rgba(8,15,8,.2); clip-path: polygon(38% 60%, 100% 0, 52% 100%); opacity: 0; pointer-events: none; }
/* cards.js draws the trail's dots and times them to the plane */
.inv__trail { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; filter: drop-shadow(0 1px 2px rgba(8,15,8,.28)); }
.inv__trail circle { fill: #fff; opacity: 0; }

[data-phase="draft"] .inv__sheet, [data-phase="press"] .inv__sheet { opacity: 1; }
[data-phase="draft"] .inv__sent, [data-phase="press"] .inv__sent, [data-phase="fold"] .inv__sent, [data-phase="fly"] .inv__sent { opacity: 0; }
[data-phase="press"] .inv__btn { transform: scale(.97); }
/* A wide rectangle first, so the shadow survives until the fold begins. */
.fvis.is-active[data-phase="press"] .ui--invoice { clip-path: polygon(-30% -30%, 130% -30%, 130% 130%, -30% 130%); }
/* The folded pose. cards.js (REST) starts the flight from exactly this. */
.fvis.is-active[data-phase="fold"] .ui--invoice, .fvis.is-active[data-phase="fly"] .ui--invoice {
  clip-path: polygon(0 40%, 100% 0, 52% 100%, 38% 60%);
  box-shadow: none;
  transform: scale(.46) rotate(-6deg);
  transition: clip-path .7s cubic-bezier(.65, 0, .2, 1), transform .8s cubic-bezier(.65, 0, .2, 1), opacity .3s var(--ease);
  transition-delay: 0s;
}
[data-phase="fold"] .ui--invoice::after, [data-phase="fly"] .ui--invoice::after { opacity: 1; transition: opacity .3s var(--ease) .3s; }
.fvis.is-active[data-phase="sent"] .ui--invoice { transition: none; animation: card-in .7s var(--ease-out) both; }
@keyframes card-in { from { opacity: 0; transform: translateY(1.4em) scale(.96); } }
[data-phase="sent"] .trail li { opacity: 0; transform: translateY(.5em); transition: opacity .4s var(--ease), transform .5s var(--ease-out); }
[data-phase="sent"][data-step="1"] .trail li:nth-child(-n+1),
[data-phase="sent"][data-step="2"] .trail li:nth-child(-n+2),
[data-phase="sent"][data-step="3"] .trail li:nth-child(-n+3) { opacity: 1; transform: none; }
[data-phase="sent"] .trail li::before { background: #7ac26b; }
[data-phase="sent"] .trail b { color: var(--ink); }
[data-phase="sent"]:not([data-step="3"]) .inv__chip { background: var(--accent); }
[data-phase="sent"]:not([data-step="3"]) .inv__chip b:first-child { opacity: 1; }
[data-phase="sent"]:not([data-step="3"]) .inv__chip b:last-child { opacity: 0; }
.fvis:not([data-phase]) .trail li:last-child::before { background: #7ac26b; }
.fvis:not([data-phase]) .trail li:last-child b { color: var(--ink); }

/* ───────── 4. inventory: a restock is scanned in, the levels fill, then fall as product is used ───────── */

.stock u { display: block; height: .5em; border-radius: 99px; background: var(--muted); position: relative; overflow: hidden; }
.stock u::after { display: none; }
.stock u s { position: absolute; inset: 0; border-radius: inherit; background: #7ac26b; transform: translateX(calc((var(--v) - 1) * 100%)); transition: transform .9s cubic-bezier(.65, 0, .2, 1), background-color .5s var(--ease); }
.stock u.low s { background: #e0a526; }
.stock li span, .used b, [data-inv="chip"] { transition: opacity .25s var(--ease); }
.is-swapping { opacity: 0 !important; }
.chip--ok { background: var(--paid-bg); color: var(--paid-fg); }
.chip--calm { background: var(--muted); color: var(--ink-3); }
.used b { font-variant-numeric: tabular-nums; }

/* The barcode scanner, as the iOS app draws it (InventoryScannerView): a dark camera view, a frame
   with four white corners, a light green line passing up and down, and a pill naming what was
   found. It lies over the inventory card like a sheet, and drops away when the restock is
   submitted. cards.js moves it on by setting data-scan on the card's stage:
   0 aiming, 1 the first product found, 2 the next one brought into the frame, 3 it is found. */
.fvis[data-card="inventory"] > .ui, .fvis[data-card="inventory"] > .scan { grid-area: 1 / 1; }
.scan {
  --scan-drop: 100cqh; /* how far it drops: the height of the stage, so it leaves through the bottom */
  position: relative; font-size: clamp(10px, min(3.45cqw, 2.9cqh), 15.5px); width: 25em; height: 25.4em; border-radius: 1.7em; overflow: hidden;
  background: #0b0b0c; color: #fff; line-height: 1.2; letter-spacing: -0.01em;
  box-shadow: 0 2.4em 5em -1.4em rgba(8,15,8,.5), 0 0 0 1px rgba(8,15,8,.05);
  opacity: 0; transform: translateY(1.8em) scale(.965);
  transition: transform .8s var(--ease-out), opacity .5s var(--ease);
}
.fvis.is-active[data-phase="scan"] .scan { opacity: 1; transform: none; transition-delay: .08s; }
.fvis.is-active[data-phase="stock"] .scan { opacity: 1; transform: translateY(var(--scan-drop)); transition: transform .37s cubic-bezier(.5, 0, .9, .4); }
/* While the scanner is up the card waits underneath, a little small. It comes forward as the scanner leaves. */
.fvis.is-active[data-phase="scan"] .ui--inv { opacity: 0; transform: scale(.94); transition: opacity 0s .8s, transform 0s .8s; }
.fvis.is-active[data-phase="stock"] .ui--inv { transition: transform .53s cubic-bezier(.65, 0, .2, 1); }

.scan__cam { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: brightness(.42) saturate(.8); transform: scale(1.2); }
.scan::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 34%, rgba(0,0,0,0) 56%, rgba(0,0,0,.7) 100%); pointer-events: none; }
.scan > :not(.scan__cam) { z-index: 1; }
.scan__top { position: absolute; left: 1.4em; right: 1.4em; top: 1.3em; display: flex; align-items: center; justify-content: space-between; font-weight: 500; font-size: .95em; }
.scan__count { font-style: normal; font-size: .84em; line-height: 1; padding: .6em .9em; border-radius: 99px; background: rgba(255,255,255,.16); opacity: 0; transform: scale(.9); transition: opacity .2s var(--ease), transform .27s cubic-bezier(.3, 1.45, .45, 1); }
:is([data-scan="1"], [data-scan="2"], [data-scan="3"]) .scan__count { opacity: 1; transform: none; }
.scan__hint { position: absolute; left: 0; right: 0; top: 4.5em; margin: 0; text-align: center; font-size: .95em; color: rgba(255,255,255,.86); }
.scan__frame { position: absolute; left: 12%; right: 12%; top: 6.7em; aspect-ratio: 1.25; border-radius: .9em; box-shadow: inset 0 0 0 1px rgba(255,255,255,.25); color: #fff; }
/* the corners turn green for a moment each time a product is found */
:is([data-scan="1"], [data-scan="3"]) .scan__frame { animation: scan-found .4s linear; }
@keyframes scan-found { 25%, 60% { color: #c5e89c; } }
.scan__corner { position: absolute; width: 2.1em; height: 2.1em; border: .19em solid currentColor; border-radius: .9em 0 0 0; border-right: 0; border-bottom: 0; }
.scan__corner:nth-of-type(1) { left: 0; top: 0; }
.scan__corner:nth-of-type(2) { right: 0; top: 0; transform: rotate(90deg); }
.scan__corner:nth-of-type(3) { right: 0; bottom: 0; transform: rotate(180deg); }
.scan__corner:nth-of-type(4) { left: 0; bottom: 0; transform: rotate(270deg); }
/* The line passes twice as fast as the app's, so that two scans fit. The frame is 15.2em tall. */
.scan__line { position: absolute; left: 6%; right: 6%; top: 0; height: .125em; border-radius: .125em; background: #c5e89c; box-shadow: 0 0 .56em .09em rgba(197,232,156,.7); transform: translateY(1.52em); }
.fvis.is-active .scan__line { animation: scan-line 1.133s ease-in-out infinite alternate; }
@keyframes scan-line { from { transform: translateY(1.52em); } to { transform: translateY(13.68em); } }
.scan__labels { position: absolute; inset: 0; overflow: hidden; border-radius: .9em; }
/* what the camera sees: the product's own label, held a little off square */
.scan__label { position: absolute; left: 13%; right: 13%; top: 10%; bottom: 25%; border-radius: .5em; background: #f7f6f1; color: #151d14; transform: rotate(-3deg);
  display: grid; align-content: center; justify-items: center; gap: .16em; padding: .7em; box-shadow: 0 1em 2.4em rgba(0,0,0,.45);
  transition: transform .4s cubic-bezier(.65, 0, .2, 1); }
.scan__label:nth-child(2) { transform: translateX(130%) rotate(-3deg); }
:is([data-scan="2"], [data-scan="3"]) .scan__label:nth-child(1) { transform: translateX(-130%) rotate(-3deg); }
:is([data-scan="2"], [data-scan="3"]) .scan__label:nth-child(2) { transform: rotate(-3deg); }
.scan__label b { font: 700 1.05em/1 var(--font-ui-display); letter-spacing: -0.04em; color: inherit; }
.scan__label span { font-size: .6em; color: #6c746b; }
.scan__label em { font-style: normal; font-size: .58em; letter-spacing: .14em; font-variant-numeric: tabular-nums; color: #151d14; }
.barcode { display: flex; align-items: stretch; height: 3em; margin-top: .45em; }
.barcode u { display: block; background: #151d14; }
.scan__found { position: absolute; left: 50%; bottom: 5.5em; display: inline-flex; align-items: center; gap: .5em; height: 2.3em; padding: 0 1em 0 .7em; border-radius: 99px; white-space: nowrap;
  background: rgba(20,22,20,.78); box-shadow: inset 0 0 0 1px rgba(255,255,255,.18); font-size: .92em;
  opacity: 0; transform: translateX(-50%) translateY(.5em) scale(.9); transition: opacity .17s linear, transform .17s linear; }
:is([data-scan="1"], [data-scan="3"]) .scan__found { opacity: 1; transform: translateX(-50%); transition: opacity .15s linear, transform .3s cubic-bezier(.3, 1.45, .45, 1); }
.scan__found svg { width: 1.3em; height: 1.3em; padding: .22em; border-radius: 50%; background: #c5e89c; color: #0a0a0a; }
.scan__found b { font-weight: 500; color: inherit; }
.scan__submit { position: absolute; left: 1.4em; right: 1.4em; bottom: 1.4em; height: 3.2em; border-radius: .9em; display: grid; place-items: center; background: #c5e89c; color: #0a0a0a; font-weight: 600; font-size: .95em; transition: transform .18s var(--ease-out); }
[data-press="1"] .scan__submit { transform: scale(.97); }

/* ───────── 5. forms: answers typed, then signed ───────── */

/* An empty answer holds the height of a filled one, so the card is its full size from the start. */
.qa dd:not(.thumbs) { box-sizing: content-box; min-height: 1.35em; }
.qa dd.thumbs { box-sizing: content-box; min-height: 3.6em; }
.qa dd.is-typing::after { content: ""; display: inline-block; width: 1.5px; height: 1.05em; margin-left: 1px; vertical-align: -.14em; background: var(--ink); animation: caret .9s steps(1) infinite; }
@keyframes caret { 50% { opacity: 0; } }
.thumbs img, .sig span, .form__chip { transition: opacity .4s var(--ease), transform .5s var(--ease-out); }
.sig path { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 0; }
[data-card="form"][data-step] .thumbs img { opacity: 0; transform: scale(.6); }
[data-card="form"][data-step] .sig path { stroke-dashoffset: 1; opacity: 0; }
[data-card="form"][data-step] .sig span, [data-card="form"][data-step] .form__chip { opacity: 0; transform: translateY(.3em); }
[data-card="form"]:is([data-step="3"], [data-step="4"], [data-step="5"]) .thumbs img { opacity: 1; transform: none; }
[data-card="form"]:is([data-step="3"], [data-step="4"], [data-step="5"]) .thumbs img + img { transition-delay: .12s; }
[data-card="form"]:is([data-step="4"], [data-step="5"]) .sig path { stroke-dashoffset: 0; opacity: 1; transition: stroke-dashoffset .7s cubic-bezier(.4, 0, .3, 1); }
[data-card="form"][data-step="5"] .sig span, [data-card="form"][data-step="5"] .form__chip { opacity: 1; transform: none; }

/* ───────── 6. messaging: a real back and forth ───────── */
.ui--msg { height: 24.6em; }
.ui--msg .thread { height: 18.4em; justify-content: flex-end; overflow: hidden; -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 2.2em); mask-image: linear-gradient(180deg, transparent 0, #000 2.2em); }
.ui--msg .thread > * { flex: none; }
.thread .is-new { opacity: 0; transform: translateY(.9em) scale(.96); }
.thread .b, .thread .cap { transition: opacity .35s var(--ease), transform .45s var(--ease-out); }
.b--in { transform-origin: left bottom; }
.b--out { transform-origin: right bottom; }
.b--dots { display: inline-flex; gap: .35em; padding: .95em 1em; }
.b--dots i { width: .45em; height: .45em; border-radius: 50%; background: var(--ink-3); animation: typing 1.2s var(--ease) infinite; }
.b--dots i:nth-child(2) { animation-delay: .15s; }
.b--dots i:nth-child(3) { animation-delay: .3s; }

/* ───────── 7. team: a booth renter is added in three steps, then she is on the team ─────────
   Two layers share one card of one height: the steps (.tw) and the team (.tw__done).
   With no data-phase the team shows, which is the card at rest. */
.ui--team { height: 23em; }
.ui--team .ui__top { margin-bottom: .85em; }
.tw { position: absolute; inset: 0; padding: inherit; display: flex; flex-direction: column; opacity: 0; transform: translateY(-.6em); transition: opacity .4s var(--ease), transform .6s var(--ease-out); }
.tw__done { transition: opacity .45s var(--ease), transform .6s var(--ease-out); }
[data-phase="wizard"] .tw { opacity: 1; transform: none; transition-delay: .2s; }
[data-phase="wizard"] .tw__done { opacity: 0; transform: translateY(.8em); }
[data-phase="done"] .tw__done { transition-delay: .2s; }

.tw__bar { display: flex; gap: .4em; margin-bottom: 1.15em; }
.tw__bar i { flex: 1; height: .28em; border-radius: 99px; background: var(--line); position: relative; overflow: hidden; }
.tw__bar i::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--ink); transform: scaleX(0); transform-origin: left; transition: transform .55s cubic-bezier(.65, 0, .2, 1); }
[data-step="1"] .tw__bar i:nth-child(-n+1)::after,
[data-step="2"] .tw__bar i:nth-child(-n+2)::after,
[data-step="3"] .tw__bar i:nth-child(-n+3)::after { transform: scaleX(1); }

.tw__steps { position: relative; flex: 1 1 auto; min-height: 0; }
.tw__step { position: absolute; inset: 0; opacity: 0; transform: translateX(1.6em); transition: opacity .35s var(--ease), transform .55s var(--ease-out); }
[data-step="1"] .tw__step[data-at="1"], [data-step="2"] .tw__step[data-at="2"], [data-step="3"] .tw__step[data-at="3"] { opacity: 1; transform: none; transition-delay: .12s; }
[data-step="2"] .tw__step[data-at="1"], [data-step="3"] .tw__step[data-at="1"], [data-step="3"] .tw__step[data-at="2"] { transform: translateX(-1.6em); }
.tw__h { display: block; font-weight: 600; color: var(--ink); margin-bottom: .7em; }

.tw__roles { display: grid; gap: .5em; }
.tw__roles li { display: flex; align-items: center; gap: .8em; height: 2.9em; padding: 0 1em; border-radius: 99px; box-shadow: inset 0 0 0 1px var(--line); color: var(--ink); font-weight: 500; font-size: .95em; transition: background-color .35s var(--ease), box-shadow .35s var(--ease); }
.tw__roles i { flex: none; width: 1.3em; height: 1.3em; border-radius: 50%; display: grid; place-items: center; box-shadow: inset 0 0 0 1.5px var(--line); color: #fff; transition: background-color .3s var(--ease), box-shadow .3s var(--ease); }
.tw__roles svg { width: .85em; height: .85em; fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.tw__roles .is-pick { background: var(--accent); box-shadow: inset 0 0 0 1.5px var(--ink); }
.tw__roles .is-pick i { background: var(--ink); box-shadow: none; }
.tw__roles .is-pick svg { stroke-dashoffset: 0; transition: stroke-dashoffset .3s var(--ease) .12s; }

.tw__fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .8em; }
.tw__fields--rent { grid-template-columns: 8.2em minmax(0, 1fr); }
.tw__fields p { display: grid; gap: .35em; align-content: start; }
.tw__fields .is-wide { grid-column: 1 / -1; }
.tw__l { font-size: .82em; color: var(--ink-3); white-space: nowrap; }
.tw__in { display: flex; align-items: center; height: 2.6em; padding: 0 1em; border-radius: 99px; box-shadow: inset 0 0 0 1px var(--line); font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; transition: box-shadow .3s var(--ease); }
.tw__in u { text-decoration: none; color: var(--ink-3); margin-right: .15em; }
.tw__in em { font-style: normal; }
.tw__in.is-typing, .tw__in:has(.is-typing) { box-shadow: inset 0 0 0 1.5px var(--ink); }
.tw .is-typing::after { content: ""; display: inline-block; width: 1.5px; height: 1.05em; margin-left: 1px; vertical-align: -.14em; background: var(--ink); animation: caret .9s steps(1) infinite; }

.days { display: flex; justify-content: space-between; }
.days i { width: 2.3em; height: 2.3em; border-radius: 50%; display: grid; place-items: center; font-style: normal; font-weight: 600; font-size: 1em; line-height: 1; color: var(--ink-3); box-shadow: inset 0 0 0 1px var(--line); transition: background-color .3s var(--ease), color .3s var(--ease), box-shadow .3s var(--ease); }
.days i.is-on { background: var(--pistachio); color: var(--on-pistachio); box-shadow: none; }
.tw .days i.is-on { animation: day-on .45s var(--ease-out); }
@keyframes day-on { from { transform: scale(.7); } 55% { transform: scale(1.1); } }
.days--sm { justify-content: flex-end; gap: .3em; }
.days--sm i { width: 1.75em; height: 1.75em; font-size: .78em; }

.ui--team .seg { display: grid; font-size: .8em; }
.ui--team .seg i { padding: 1.02em .2em; white-space: nowrap; }

.tw__btn { margin-top: auto; display: flex; align-items: center; justify-content: center; height: 3.37em; border-radius: 99px; background: var(--ink); color: #fff; font-weight: 600; font-size: .95em; transition: transform .18s var(--ease); }
.tw__btn .swap b { display: inline-flex; align-items: center; justify-content: center; gap: .6em; white-space: nowrap; }
.tw__btn svg { width: 1.15em; height: 1.15em; }
[data-press="1"] .tw__btn { transform: scale(.97); }

/* the team */
.crew { gap: .35em; }
.crew li { display: block; padding: .75em .8em; margin: 0 -.8em; border: 0; border-radius: 1.1em; }
.crew li:first-child { padding-top: .75em; }
.crew li:last-child { padding-bottom: .75em; }
.crew__row { display: grid; grid-template-columns: 2.6em 1fr auto; align-items: center; gap: .85em; }
.crew__row > div { display: grid; line-height: 1.25; }
.crew .is-new { background: var(--muted); }
.crew .is-new .init { background: var(--ink); color: #fff; }
.chip--invited { background: var(--accent); color: #1c3517; }
.crew__facts { margin-top: .75em; border-top: 1px solid var(--line); }
.crew__facts p { display: flex; justify-content: space-between; align-items: center; min-height: 2.2em; padding-top: .55em; font-size: .9em; color: var(--ink-2); }
.crew__facts p > span:first-child { font-size: 1em; color: var(--ink-3); }
.crew__facts b { font-variant-numeric: tabular-nums; }
/* as the team arrives, the new person lands first and the rest follow */
[data-phase="done"] .crew li { animation: rise .6s var(--ease-out) both; animation-delay: calc(.25s + var(--n, 0) * 90ms); }
[data-phase="done"] .crew li:nth-child(2) { --n: 1; }
[data-phase="done"] .crew li:nth-child(3) { --n: 2; }
[data-phase="done"] .chip--invited { animation: day-on .5s var(--ease-out) .7s both; }

/* ───────── 8. reports: the range and the view change, and the chart follows ───────── */
.ui--report .ui__title { font-size: 1.45em; }
.ui--report .figure { align-items: baseline; margin-bottom: .9em; }
.ui--report .figure span { font-size: .88em; color: var(--ink-3); }
.chart { position: relative; height: 5.6em; margin-bottom: 1.1em; }
.rbars { position: absolute; inset: 0; display: flex; align-items: flex-end; gap: .55em; }
.rbars i { flex: 1; height: 100%; border-radius: .4em .4em .15em .15em; background: var(--pistachio); transform-origin: bottom; transform: scaleY(var(--h, .5)); transition: transform .75s cubic-bezier(.65, 0, .2, 1), background-color .5s var(--ease), opacity .5s var(--ease); transition-delay: calc(var(--n, 0) * 45ms); }
.rbars i:last-child { background: var(--ink); }
.chart__line { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.chart__line { clip-path: inset(-10% 100% -10% 0); transition: clip-path .15s; }
.chart__line path { fill: none; stroke: var(--ink); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
[data-alt="1"] .rbars i { opacity: .38; background: var(--pistachio); }
[data-alt="1"] .chart__line { clip-path: inset(-10% -2% -10% 0); transition: clip-path 1s cubic-bezier(.65, 0, .2, 1) .25s; }
[data-rep] { transition: opacity .25s var(--ease); }
[data-rep="total"] { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .pulse span, .b--dots i, .qa dd.is-typing::after { animation: none; }
}
