/* Theme case studies: the industry interaction (the "build your box" builder) and the token strip. Markup: src/_includes/e2/theme/
   sig-builder.njk and tokens.njk. Nothing is brand-specific: the wrapper's inline style carries the theme (--th-from/--th-to/--th-ink/
   --th-accent from stage, --th-f-head/ui/prod from tokens.fonts); every colour below derives from those.
   The builder is a light stage (the hero's gradient) on the dark page; the token strip is a white spec sheet.
   Layout: wide, three columns (items, the box, the receipt); under 1100px the items sit on top as a row; on a phone they become a
   horizontal scroll-snap row above the box, then the receipt. Every control is at least 44px tall and wide. */

.th-sigwrap {
  --th-spring: cubic-bezier(.34, 1.56, .64, 1);
  --th-out: cubic-bezier(.2, .8, .2, 1);
  --th-muted: color-mix(in srgb, var(--th-ink) 74%, transparent);
  --th-line: color-mix(in srgb, var(--th-ink) 12%, transparent);
  --th-soft: color-mix(in srgb, var(--th-ink) 5%, transparent);
  /* The kraft of the box: warm paper from the stage's own cream, pulled towards cardboard. */
  --th-kraft: color-mix(in srgb, var(--th-to) 34%, #b98c58);
  --th-kraft-hi: color-mix(in srgb, var(--th-kraft) 72%, #fff);
  --th-kraft-lo: color-mix(in srgb, var(--th-kraft) 80%, var(--th-ink));
  --th-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .36 0 0 0 0 .24 0 0 0 0 .12 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --arn: .342;          /* an object's width / height until the script has measured its image (every item and filled slot then carries its own --arn: a jar is not shaped like a bottle) */
  --th-slot-ar: .75;    /* a slot's width / height (3 / 4; 3 / 4.1 on a phone), for fitting a wide object inside it */
  --th-accent-ink: color-mix(in srgb, var(--th-accent) 78%, var(--th-ink));   /* the accent as small text on the light stage: pulled towards the ink (Aurelle's terracotta alone is 4.0:1 at 12px; this is 5.3:1) */
  --th-sale: #b4322b;   /* the sale badge: a UI red, not a brand colour (5.2:1 on its tint) */
  --th-sale-bg: #fde7e5;
  display: flex; flex-direction: column; gap: clamp(40px, 5vw, 64px);
}
.th-sigwrap .th-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
:where(.th-sigwrap) button { font: inherit; color: inherit; }
.th-sigwrap :focus-visible { outline: 2px solid var(--th-ink); outline-offset: 3px; }
/* the dark page's focus ring is light blue: on the light stage the ink ring has the contrast */

/* The section header is the shared one (.th-block / .th-hd in e2-theme.css), so the eyebrow, title and intro line up with Design and Tests. */

/* ---------- The stage ---------- */
.th-builder {
  position: relative; isolation: isolate; border-radius: 32px; padding: clamp(18px, 3vw, 40px);
  background: linear-gradient(135deg, var(--th-from), var(--th-to)); color: var(--th-ink);
  font-family: var(--th-f-ui); font-size: 15px; line-height: 1.4;
  display: grid; align-items: start; gap: 32px clamp(24px, 3vw, 44px);
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1.1fr) minmax(0, .84fr);
  grid-template-areas: "items box pay";
}
.th-items { grid-area: items; }
.th-boxcol { grid-area: box; }
.th-pay { grid-area: pay; align-self: stretch; }

/* ---------- Items ---------- */
.th-items { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.th-items > li { display: flex; min-width: 0; }
.th-item {
  position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
  padding: 10px 10px 14px; border-radius: 22px; border: 1px solid var(--th-line); background: rgba(255,255,255,.7);
  box-shadow: 0 1px 0 rgba(255,255,255,.8) inset, 0 14px 24px -22px color-mix(in srgb, var(--th-ink) 70%, transparent);
  transition: transform .3s var(--th-spring), box-shadow .3s ease, background-color .2s ease, opacity .2s ease;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.th-item__art {
  position: relative; display: block; aspect-ratio: 1 / 1.08; border-radius: 15px; overflow: hidden; margin-bottom: 8px;
  background:
    radial-gradient(70% 55% at 50% 88%, color-mix(in srgb, var(--c) 38%, transparent), transparent 72%),
    linear-gradient(180deg, color-mix(in srgb, var(--c) 12%, #fff), color-mix(in srgb, var(--c) 22%, #fff));
}
.th-item__img {
  /* tall objects stand 88% of the art; a wide one (a jar) is held to 66% of its width, so its height follows from its own shape (.926 = the art's width / height) */
  position: absolute; left: 50%; bottom: 5%; translate: -50% 0; display: block; height: min(88%, calc(66% * .926 / var(--arn))); aspect-ratio: var(--arn); width: auto; max-width: none; object-fit: contain;
  filter: drop-shadow(0 8px 6px color-mix(in srgb, var(--c) 45%, transparent));
  transition: transform .35s var(--th-spring);
}
/* the name sits over the price at every width: names come from data, so a side-by-side row would wrap for some name at some width */
.th-item__row { display: flex; flex-direction: column; align-items: flex-start; gap: 0; padding: 0 3px; font-family: var(--th-f-prod); }
.th-item__name { font-size: 16px; font-weight: 600; line-height: 1.2; letter-spacing: -.01em; }
.th-item__price { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.th-item__note { padding: 0 3px; font-family: var(--th-f-prod); font-size: 13px; line-height: 1.35; color: var(--th-muted); text-wrap: pretty; }
.th-item__plus {
  position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  background: var(--th-ink); color: #fff; opacity: 0; scale: .6; transition: opacity .2s ease, scale .3s var(--th-spring);
}
.th-item__qty {
  position: absolute; left: 8px; top: 8px; display: inline-flex; align-items: baseline; gap: 1px; padding: 3px 9px 3px 8px; border-radius: 99px;
  background: var(--th-ink); color: #fff; font: 600 12px/1.3 var(--th-f-ui); font-variant-numeric: tabular-nums;
}
.th-item__qty:not([hidden]) { animation: th-pop .4s var(--th-spring); }
.th-item__qty b { font-weight: 600; }
/* steps mode: the card is a toggle; in the box it carries a tick, an ink ring, and its glyph turns to a cross (a press takes it out) */
.th-item__qty--tick { padding: 0; width: 24px; height: 24px; justify-content: center; align-items: center; }
.th-item.is-picked { border-color: var(--th-ink); box-shadow: 0 0 0 1px var(--th-ink), 0 14px 24px -22px color-mix(in srgb, var(--th-ink) 70%, transparent); }
.th-item.is-picked .th-item__plus svg { rotate: 45deg; }
.th-item__qty[hidden] { display: none; }
@media (hover: hover) {
  .th-item:hover { transform: translateY(-5px) rotate(-1.2deg); background: rgba(255,255,255,.92); box-shadow: 0 1px 0 rgba(255,255,255,.9) inset, 0 26px 34px -22px color-mix(in srgb, var(--th-ink) 75%, transparent); }
  .th-item:hover .th-item__img { transform: translateY(-3%) rotate(2.5deg) scale(1.04); }
  .th-item:hover .th-item__plus { opacity: 1; scale: 1; }
}
.th-item:focus-visible .th-item__plus { opacity: 1; scale: 1; }
.th-item:focus-visible { background: rgba(255,255,255,.92); }
.th-item:active { transform: scale(.97); transition-duration: .1s; }
.th-item.is-maxed { opacity: .55; }
.th-item.is-maxed:hover { transform: none; }
/* a full box: the add glyph goes (aria-disabled says the same to a screen reader); a click still answers, the box shakes or flashes */
.th-item.is-maxed .th-item__plus, .th-item.is-maxed:hover .th-item__plus, .th-item.is-maxed:focus-visible .th-item__plus { opacity: 0; }
@keyframes th-pop { from { scale: .4; opacity: 0; } to { scale: 1; opacity: 1; } }

/* ---------- The box ---------- */
.th-boxcol { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.th-boxcol__head { display: flex; align-items: center; justify-content: space-between; min-height: 44px; margin-bottom: -6px; }
.th-count { font: 600 15px/1 var(--th-f-ui); font-variant-numeric: tabular-nums; color: var(--th-muted); }
.th-count b { font-weight: 600; font-size: 24px; letter-spacing: -.02em; color: var(--th-ink); font-family: var(--th-f-prod); }
.th-reset {
  min-width: 64px; min-height: 44px; padding: 0 14px; margin-right: -14px; border: 0; background: none; cursor: pointer; border-radius: 99px;
  font-size: 14px; font-weight: 500; color: var(--th-muted); text-underline-offset: 4px; transition: color .15s ease, opacity .15s ease;
}
.th-reset:hover { color: var(--th-ink); text-decoration: underline; }
.th-reset[aria-disabled="true"] { opacity: .4; cursor: default; text-decoration: none; }
.th-reset[aria-disabled="true"]:hover { color: var(--th-muted); }

.th-box {
  --pad: 12px;
  position: relative; padding: var(--pad) var(--pad) 0; border-radius: 22px 22px 18px 18px;
  background: var(--th-grain), linear-gradient(180deg, var(--th-kraft-hi), var(--th-kraft));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--th-ink) 14%, transparent), 0 1px 0 rgba(255,255,255,.45) inset, 0 34px 40px -26px color-mix(in srgb, var(--th-ink) 55%, transparent);
}
.th-box.is-nope { animation: th-nope .34s ease; }
/* the same answer without motion (reduced motion): an accent ring for a moment; a static shadow, so the reduce block leaves it alone */
.th-box.is-full-cue { box-shadow: 0 0 0 2px var(--th-accent), 0 34px 40px -26px color-mix(in srgb, var(--th-ink) 55%, transparent); }
@keyframes th-nope { 20% { translate: -6px 0; } 40% { translate: 6px 0; } 60% { translate: -4px 0; } 80% { translate: 3px 0; } }
.th-slots {
  list-style: none; margin: 0; padding: 7px; display: grid; gap: 6px; border-radius: 14px;
  grid-template-columns: repeat(var(--th-cols), minmax(0, 1fr));
  background: var(--th-kraft-hi); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--th-ink) 10%, transparent);
}
.th-slots > li { display: flex; min-width: 0; }
.th-slot {
  position: relative; flex: 1; min-width: 44px; min-height: 44px; aspect-ratio: 3 / 4; padding: 0; border: 0; border-radius: 9px; cursor: default; overflow: hidden;
  background: linear-gradient(180deg, color-mix(in srgb, var(--th-kraft) 88%, var(--th-ink)), color-mix(in srgb, var(--th-kraft) 72%, var(--th-ink)));
  box-shadow: inset 0 7px 12px -5px color-mix(in srgb, var(--th-ink) 55%, transparent), inset 0 0 0 1px color-mix(in srgb, var(--th-ink) 14%, transparent);
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform .2s var(--th-spring);
}
/* the tint of the unit that stands in the slot */
.th-slot::before {
  content: ""; position: absolute; inset: 0; opacity: 0; transition: opacity .35s ease;
  background: radial-gradient(80% 62% at 50% 100%, color-mix(in srgb, var(--c, transparent) 62%, transparent), transparent 74%);
}
.th-slot.is-full::before { opacity: 1; }
.th-slot__n { position: absolute; left: 50%; top: 50%; translate: -50% -50%; font: 500 12px/1 var(--mono); color: var(--th-ink); transition: opacity .2s ease; }   /* ink, not white: white never reaches 3:1 on the kraft (ink is 5.5:1 on Aurelle's, 5.7:1 on ava's) */
.th-slot.is-full .th-slot__n { opacity: 0; }
/* the next free slot: a quiet dashed ring says where the next one goes */
.th-slot.is-next { box-shadow: inset 0 7px 12px -5px color-mix(in srgb, var(--th-ink) 55%, transparent), inset 0 0 0 1.5px rgba(255,255,255,.5); }
.th-slot__shadow {
  position: absolute; left: 50%; bottom: 5%; width: 62%; height: 9%; translate: -50% 0; border-radius: 50%; opacity: 0; transition: opacity .3s ease;
  background: radial-gradient(closest-side, rgba(0,0,0,.6), rgba(0,0,0,.25) 60%, transparent);
}
.th-slot.is-full .th-slot__shadow { opacity: 1; }
/* while the unit is still in the air, its tint and shadow wait (they fade in as it lands) */
.th-slot.is-landing::before, .th-slot.is-landing .th-slot__shadow { opacity: 0; transition: none; }
.th-slot__img {
  position: absolute; left: 50%; bottom: 8%; height: min(80%, calc(74% * var(--th-slot-ar) / var(--arn))); aspect-ratio: var(--arn); width: auto; translate: -50% 0; object-fit: contain; object-position: 50% 100%;
  visibility: hidden; pointer-events: none; filter: drop-shadow(0 3px 3px rgba(0,0,0,.28));
}
.th-slot.is-full .th-slot__img { visibility: visible; }
.th-slot.is-landing .th-slot__img { visibility: hidden; }
.th-slot__img--pop { visibility: visible !important; }
.th-slot__x {
  position: absolute; right: 5px; top: 5px; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: var(--th-ink); color: #fff; opacity: 0; scale: .6; transition: opacity .15s ease, scale .25s var(--th-spring); pointer-events: none;
}
.th-slot.is-full { cursor: pointer; }
.th-slot.is-full:focus-visible { outline-offset: -3px; }
.th-slot.is-full:focus-visible .th-slot__x { opacity: 1; scale: 1; }
@media (hover: hover) { .th-slot.is-full:hover .th-slot__x { opacity: 1; scale: 1; } .th-slot.is-full:hover { transform: translateY(-2px); } }
@media (hover: none) { .th-slot.is-full .th-slot__x { opacity: .9; scale: 1; } }
.th-slot.is-full:active { transform: scale(.97); }
.th-slot.is-thunk { animation: th-thunk .4s var(--th-spring); }
@keyframes th-thunk { 0% { transform: scale(1); } 30% { transform: scale(.955, .97); } 100% { transform: scale(1); } }

/* Four slots or fewer stand in ONE row, numbered 1 to 4 left to right (the data's order, morning to night in Aurelle's case): tall, narrow slots,
   so the tray keeps ava's height and the three columns end together. It beats the phone's 3 / 4.1 (more specific), and its own --th-slot-ar
   (width / height, 3 / 5) is what fits a wide object inside the slot. */
.th-box--row { --th-slot-ar: .6; }
.th-box--row .th-slot { aspect-ratio: 3 / 5; }
/* beside the items and the receipt (three columns) the shorter tray sits in the middle of the row, not hanging from its top */
@media (min-width: 1100px) { .th-boxcol:has(> .th-box--row) { align-self: center; } }

/* The front of the carrier: a paper label with the brand's name. */
.th-box__lip {
  position: relative; height: 58px; margin: 12px calc(var(--pad) * -1) 0; display: grid; place-items: center; border-radius: 0 0 18px 18px;
  background: var(--th-grain), linear-gradient(180deg, var(--th-kraft), color-mix(in srgb, var(--th-kraft) 88%, var(--th-ink)));
  box-shadow: 0 1px 0 rgba(255,255,255,.35) inset, 0 -8px 12px -8px color-mix(in srgb, var(--th-ink) 40%, transparent);
}
.th-box__lip::before { /* the tape across the lid */
  content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 14px; translate: 0 -50%; background: rgba(255,255,255,.12);
  border-block: 1px dashed rgba(255,255,255,.28);
}
.th-box__wm { display: block; height: 17px; width: auto; max-width: 150px; background: currentColor; -webkit-mask: var(--wm) center / contain no-repeat; mask: var(--wm) center / contain no-repeat; }
@media (forced-colors: active) { .th-box__wm { forced-color-adjust: none; background: CanvasText; } }
.th-box__label {
  position: relative; padding: 9px 26px 10px; border-radius: 5px; background: #fffdf8; color: var(--th-ink); rotate: -.8deg;
  font: 600 25px/1 var(--th-f-head); letter-spacing: -.01em;
  box-shadow: 0 0 0 1px rgba(0,0,0,.06), 0 8px 12px -8px color-mix(in srgb, var(--th-ink) 70%, transparent);
}

/* ---------- Progress ---------- */
.th-prog { display: flex; flex-direction: column; gap: 10px; padding: 0 2px; }
/* the track starts where the tier line starts; the 10px on the right keeps the end tick (20px, 1.12x when reached) inside the column */
.th-meter { position: relative; height: 10px; margin: 6px 10px 24px 0; border-radius: 99px; background: color-mix(in srgb, var(--th-ink) 11%, transparent); }
.th-meter__fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--p, 0) * 100%); border-radius: inherit;
  background: linear-gradient(90deg, var(--th-accent), color-mix(in srgb, var(--th-accent) 55%, #fff), var(--th-accent)); background-size: 220% 100%;
  transition: width .55s var(--th-spring);
}
.th-meter.is-live .th-meter__fill { animation: th-shimmer 2s linear infinite; }
@keyframes th-shimmer { from { background-position: 220% 0; } to { background-position: -220% 0; } }
.th-tick { position: absolute; top: 50%; left: calc(var(--at) * 100%); width: 0; height: 0; }
.th-tick i {
  position: absolute; left: 0; top: 0; translate: -50% -50%; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; box-sizing: border-box;
  background: #fff; border: 2px solid color-mix(in srgb, var(--th-ink) 24%, transparent); color: #fff; transition: background-color .25s ease, border-color .25s ease, scale .4s var(--th-spring);
}
.th-tick i svg { opacity: 0; transition: opacity .2s ease; }
.th-tick.is-hit i { background: var(--th-accent); border-color: var(--th-accent); scale: 1.12; }
.th-tick.is-hit i svg { opacity: 1; }
.th-tick__l {
  position: absolute; left: 0; top: 18px; translate: -50% 0; white-space: nowrap; font: 500 12px/1.2 var(--th-f-ui); font-variant-numeric: tabular-nums;
  color: var(--th-muted); transition: color .2s ease;
}
.th-tick.is-hit .th-tick__l { color: var(--th-accent-ink); font-weight: 600; }
.th-tick--end .th-tick__l { translate: -100% 0; }
.th-tier { display: flex; flex-direction: column; gap: 2px; min-height: 44px; }
.th-tier__msg { font-size: 16px; font-weight: 600; line-height: 1.3; letter-spacing: -.01em; }
.th-tier__next { font-size: 13px; line-height: 1.35; color: var(--th-muted); }
.th-tier__next:empty { display: none; }

/* ---------- The receipt ---------- */
.th-pay {
  display: flex; flex-direction: column; gap: 18px; padding: 20px; border-radius: 24px; min-width: 0;
  background: rgba(255,255,255,.66); border: 1px solid var(--th-line);
  box-shadow: 0 1px 0 rgba(255,255,255,.8) inset, 0 24px 34px -28px color-mix(in srgb, var(--th-ink) 60%, transparent);
}
.th-lines { list-style: none; margin: 0; padding: 0 0 16px; display: flex; flex-direction: column; gap: 4px; border-bottom: 1px solid var(--th-line); }
.th-line { display: flex; align-items: baseline; gap: 6px; min-height: 34px; font: 500 15px/1.3 var(--th-f-prod); transition: color .25s ease; }
/* a line not in the box yet: lighter ink, still 4.5:1 on the receipt (only the leader goes faint; measured on every theme's ink: 5.5:1 on Aurelle's) */
.th-line.is-zero { color: color-mix(in srgb, var(--th-ink) 68%, transparent); }
.th-line.is-zero .th-line__dots { opacity: .4; }
.th-line__q { font-weight: 600; font-variant-numeric: tabular-nums; }
/* the leader: an empty flex item's baseline is its bottom border edge, so on the row's baseline the dots sit on the text's baseline,
   lifted a touch so they read as leader dots, not an underline */
.th-line__dots { flex: 1; min-width: 12px; align-self: baseline; translate: 0 -3px; border-bottom: 1.5px dotted color-mix(in srgb, var(--th-ink) 34%, transparent); }
.th-line__amt { font-variant-numeric: tabular-nums; font-weight: 500; }
.th-line.is-bump .th-line__amt, .th-line.is-bump .th-line__q { animation: th-bump .4s var(--th-spring); }
@keyframes th-bump { 0% { transform: translateY(0); } 35% { transform: translateY(-3px) scale(1.08); } 100% { transform: none; } }
/* The receipt reads like a cart drawer: the lines at the top; the switch, the amounts and the button one group at the bottom (lined up
   with the box), so any spare height is a single gap under the lines. */
.th-switch {
  margin-top: auto; display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; padding: 6px 4px; border: 0; background: none; cursor: pointer; text-align: left; border-radius: 12px;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.th-switch__track {
  position: relative; flex: none; width: 48px; height: 28px; border-radius: 99px; background: color-mix(in srgb, var(--th-ink) 22%, transparent); transition: background-color .2s ease;
}
.th-switch__track i {
  position: absolute; left: 3px; top: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 2px 4px rgba(0,0,0,.28);
  transition: translate .3s var(--th-spring);
}
.th-switch[aria-checked="true"] .th-switch__track { background: var(--th-accent); }
.th-switch[aria-checked="true"] .th-switch__track i { translate: 20px 0; }
.th-switch:active .th-switch__track i { width: 26px; }
.th-switch[aria-checked="true"]:active .th-switch__track i { translate: 16px 0; }
.th-switch__text { font-size: 14px; line-height: 1.35; }
.th-switch__label, .th-switch__x { display: block; }
.th-switch__label { font-weight: 600; }
.th-switch__x { color: var(--th-accent-ink); font-weight: 500; }
.th-switch__dot { display: none; }   /* the text keeps its " · " for a copy or a reader; the two lines make it redundant on screen */

.th-sum { margin: 0; display: flex; flex-direction: column; gap: 9px; }
.th-sum__row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 14px; }
.th-sum dt { color: var(--th-muted); }
.th-sum dd { margin: 0; font-family: var(--th-f-prod); font-weight: 500; font-size: 16px; }
.th-sum__row--save dd { color: var(--th-accent-ink); }
.th-sum__row--total { margin-top: 4px; padding-top: 14px; border-top: 1px solid var(--th-line); align-items: center; }
.th-sum__row--total dt { font-size: 15px; font-weight: 600; color: var(--th-ink); }
.th-sum__row--total dd { font-size: 34px; font-weight: 600; letter-spacing: -.03em; }

/* Digits roll: every digit is a column showing 0 to 9 stacked; --d is the digit it shows, so a change scrolls it. The columns are hidden
   from assistive tech (one StaticText per character would read "$", "1", "4", "7"...) and hold no text: a digit column's width is a ::before
   "0" (tabular figures), a "$" or "." is drawn from its data-c, and the digits themselves by the ::after. The whole amount stays beside
   them in a .th-sr span, which is what a screen reader reads (and the element's text, once). */
.th-money { --rc: var(--th-ink); display: inline-flex; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.th-money--save { --rc: var(--th-accent-ink); }
.th-money__roll { display: inline-flex; }   /* the columns (aria-hidden); the whole amount sits beside it in a .th-sr span, which screen readers read */
.th-money .th-ch { display: inline-block; height: 1.1em; }
.th-money .th-ch::before { content: attr(data-c); content: attr(data-c) / ""; }
.th-money .th-d::before { content: "0"; content: "0" / ""; }
.th-money .th-d {
  position: relative; display: inline-block; height: 1.1em; overflow: hidden; color: transparent; font-variant-numeric: tabular-nums;
}
.th-money .th-d::after {
  content: "0\A 1\A 2\A 3\A 4\A 5\A 6\A 7\A 8\A 9";
  content: "0\A 1\A 2\A 3\A 4\A 5\A 6\A 7\A 8\A 9" / "";
  position: absolute; left: 0; right: 0; top: 0; white-space: pre; text-align: center; color: var(--rc);   /* centred: a face without tabular figures (DM Sans) leaves a narrow 1 no gap on one side only */
  transform: translateY(calc(var(--d, 0) * -10%));
  transition: transform .7s cubic-bezier(.2, .9, .25, 1) calc(var(--i, 0) * 45ms);
}

.th-cta {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 56px; padding: 0 24px; border: 0; border-radius: 99px; cursor: pointer;
  background: var(--th-ink); color: #fff; font: 600 16px/1.2 var(--th-f-ui); letter-spacing: -.005em;
  box-shadow: 0 14px 22px -14px color-mix(in srgb, var(--th-ink) 80%, transparent);
  transition: transform .25s var(--th-spring), background-color .2s ease, box-shadow .2s ease, color .2s ease; -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
@media (hover: hover) { .th-cta:not(:disabled):hover { transform: translateY(-2px); background: color-mix(in srgb, var(--th-ink) 78%, var(--th-accent)); } }
.th-cta:not(:disabled):active { transform: scale(.98); transition-duration: .1s; }
.th-cta:disabled { cursor: default; box-shadow: none; background: color-mix(in srgb, var(--th-ink) 14%, transparent); color: color-mix(in srgb, var(--th-ink) 48%, transparent); }
.th-cta__check { display: none; }
.th-cta.is-done { background: var(--th-accent); }
.th-cta.is-done .th-cta__check { display: block; animation: th-pop .45s var(--th-spring); }

/* ---------- Token strip: a white spec sheet ---------- */
.th-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.th-tok {
  position: relative; display: flex; flex-direction: column; gap: clamp(28px, 3.4vw, 44px); padding: clamp(20px, 3vw, 40px); border-radius: 32px;
  background: #fff; color: var(--th-ink); font-family: var(--th-f-ui); font-size: 15px; line-height: 1.4;
}
.th-tok :focus-visible { outline: 2px solid var(--th-ink); outline-offset: 3px; }
:where(.th-tok) button { font: inherit; color: inherit; }
.th-tok__bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--th-line); margin-bottom: -8px; }
.th-tok__cap, .th-comp__cap {
  margin: 0; font: 500 12px/1.4 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: color-mix(in srgb, var(--th-ink) 62%, transparent);
}
.th-tok__brand { font: 600 20px/1 var(--th-f-head); letter-spacing: -.01em; }
/* a theme with its own wordmark artwork (th.wordmark): the brand is a mask of it in the text colour, so it matches the real logotype in any font state */
.th-tok__wm { display: block; flex: none; height: 24px; width: auto; max-width: 180px; background: currentColor; -webkit-mask: var(--wm) center / contain no-repeat; mask: var(--wm) center / contain no-repeat; }
@media (forced-colors: active) { .th-tok__wm { forced-color-adjust: none; background: CanvasText; } }
.th-tok__group { display: flex; flex-direction: column; gap: 16px; }

/* swatches */
.th-sw { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(124px, 1fr)); }
/* The rows balance by count, so the sheet never ends on one or two swatches alone: six go 3 + 3, seven and eight go 4 + 3 and 4 + 4, and each
   goes onto ONE row once its group is wide enough for it (n x 124px + gaps: a container query on the group, because the page's width is not
   the group's). These (0,2,x) selectors outrank the phones' 4-column rule below. */
.th-tok__group:has(> .th-sw) { container-type: inline-size; }
.th-sw:has(> li:nth-child(6):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.th-sw:has(> li:nth-child(7):last-child), .th-sw:has(> li:nth-child(8):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@container (min-width: 824px) { .th-sw:has(> li:nth-child(6):last-child) { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@container (min-width: 964px) { .th-sw:has(> li:nth-child(7):last-child) { grid-template-columns: repeat(7, minmax(0, 1fr)); } }
@container (min-width: 1104px) { .th-sw:has(> li:nth-child(8):last-child) { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
.th-swatch {
  display: flex; flex-direction: column; align-items: stretch; gap: 2px; width: 100%; min-height: 44px; padding: 0; border: 0; background: none; text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.th-swatch__chip {
  position: relative; display: grid; place-items: center; aspect-ratio: 4 / 3; margin-bottom: 8px; border-radius: 14px; background: var(--sw); color: #fff;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--th-ink) 12%, transparent), 0 10px 16px -14px color-mix(in srgb, var(--th-ink) 70%, transparent);
  transition: transform .25s var(--th-spring), box-shadow .25s ease;
}
.th-swatch__chip svg {
  grid-area: 1 / 1; box-sizing: border-box; width: 32px; height: 32px; padding: 7px; border-radius: 50%; background: #fff; color: var(--th-ink);
  box-shadow: 0 6px 12px -6px rgba(0,0,0,.45); opacity: 0; scale: .7; transition: opacity .15s ease, scale .25s var(--th-spring);
}
.th-swatch__ok { display: none; }
@media (hover: hover) { .th-swatch:hover .th-swatch__chip { transform: translateY(-3px) rotate(-1deg); } .th-swatch:hover .th-swatch__copy { opacity: 1; scale: 1; } }
.th-swatch:focus-visible .th-swatch__copy { opacity: 1; scale: 1; }
.th-swatch:active .th-swatch__chip { transform: scale(.97); transition-duration: .1s; }
.th-swatch.is-copied .th-swatch__copy { display: none; }
.th-swatch.is-copied .th-swatch__ok { display: block; opacity: 1; scale: 1; }
.th-swatch__name { font-size: 14px; font-weight: 600; line-height: 1.3; }
.th-swatch__hex { font: 500 12px/1.3 var(--mono); letter-spacing: .02em; color: color-mix(in srgb, var(--th-ink) 66%, transparent); }

/* type specimens */
.th-types { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.th-type {
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "aa meta" "sample sample"; align-items: center; gap: 14px 16px; padding: 20px; border-radius: 20px;
  background: color-mix(in srgb, var(--th-ink) 3.5%, #fff); box-shadow: inset 0 0 0 1px var(--th-line);
}
/* the Aa cell has one em-based width in every card, so the role and font name start at the same x in all three */
.th-type__aa { grid-area: aa; min-width: 1.3em; font-size: 56px; line-height: 1; letter-spacing: -.02em; font-weight: 500; }
.th-type__meta { grid-area: meta; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.th-type__role { font: 500 12px/1.4 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: color-mix(in srgb, var(--th-ink) 62%, transparent); }
.th-type__name { font-size: 16px; font-weight: 600; line-height: 1.3; }
.th-type__sample { grid-area: sample; margin: 0; font-size: 24px; line-height: 1.22; font-weight: 500; letter-spacing: -.01em; text-wrap: balance; }
/* three across, the cards share a height: the Aa rows line up at the top and every sample starts on the same line, however many lines it takes */
@media (min-width: 1100px) { .th-type { grid-template-rows: auto 1fr; } .th-type__sample { align-self: start; } }

/* live components: the same 12-column grid and 16px gutter as the type specimens (4 + 8, then 4 + 4 + 4) */
.th-comps { display: grid; gap: 16px; grid-template-columns: repeat(12, minmax(0, 1fr)); }
.th-comp {
  display: flex; flex-direction: column; justify-content: space-between; gap: 18px; padding: 18px 20px 20px; border-radius: 20px; min-width: 0;
  background: color-mix(in srgb, var(--th-ink) 3.5%, #fff); box-shadow: inset 0 0 0 1px var(--th-line);
}
.th-comp--btn { grid-column: span 4; }
.th-comp--chips { grid-column: span 8; }
.th-comp--price { grid-column: span 4; }
.th-comp--rate { grid-column: span 4; }
.th-comp--qty { grid-column: span 4; }
.th-comps--norate .th-comp--price, .th-comps--norate .th-comp--qty { grid-column: span 6; }   /* no rating sample: price and quantity share the row */
.th-comp__row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-height: 44px; font-family: var(--th-f-prod); }
.th-comp--btn .th-comp__row { gap: 8px; }   /* the chips' gap; a long label wraps the second pill rather than overflow the card */

/* buttons: a pill by default, the filled one is ink (spans: specimens, not actions; hover and press still show). A theme with its own
   button shape (tokens.button: Mason Varde's square, upper-case buttons) sets --th-btn-r / --th-btn-case / --th-btn-ls on .th-comp--btn. */
.th-b {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 22px; border-radius: var(--th-btn-r, 99px); cursor: pointer; font: 500 15px/1 var(--th-f-ui); white-space: nowrap;
  text-transform: var(--th-btn-case, none); letter-spacing: var(--th-btn-ls, normal);
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s var(--th-spring), box-shadow .18s ease;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.th-b--fill { border: 1px solid var(--th-ink); background: var(--th-ink); color: #fff; }
.th-b--line { border: 1px solid var(--th-ink); background: transparent; color: var(--th-ink); }
@media (hover: hover) {
  .th-b--fill:hover { background: color-mix(in srgb, var(--th-ink) 78%, var(--th-accent)); border-color: color-mix(in srgb, var(--th-ink) 78%, var(--th-accent)); transform: translateY(-1px); box-shadow: 0 10px 14px -10px color-mix(in srgb, var(--th-ink) 80%, transparent); }
  .th-b--line:hover { background: var(--th-ink); color: #fff; transform: translateY(-1px); }
}
.th-b:active { transform: scale(.97); transition-duration: .1s; }

/* option chips: grey pills, the selected one is ink */
.th-chips { gap: 8px; }
.th-chip {
  min-height: 44px; padding: 0 20px; border: 0; border-radius: 99px; cursor: pointer; font: 400 15px/1 var(--th-f-prod); white-space: nowrap;
  background: color-mix(in srgb, var(--th-ink) 7%, #fff); color: color-mix(in srgb, var(--th-ink) 70%, transparent);
  transition: background-color .18s ease, color .18s ease, transform .18s var(--th-spring);
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
@media (hover: hover) { .th-chip[aria-checked="false"]:hover { background: color-mix(in srgb, var(--th-ink) 13%, #fff); color: var(--th-ink); } }
.th-chip[aria-checked="true"] { background: var(--th-ink); color: #fff; }
/* optimise.mobile.optionStyle "outline" (Aurelle): outlined pills, the name left and its price right; the selected one has a heavier ink outline */
.th-chip--line { display: inline-flex; align-items: center; justify-content: space-between; gap: 18px; background: transparent; font-weight: 600; color: var(--th-ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--th-ink) 22%, #fff); }
.th-chip__p { font-weight: 400; color: color-mix(in srgb, var(--th-ink) 70%, transparent); font-variant-numeric: tabular-nums; }
.th-chip--line[aria-checked="true"] { background: transparent; color: var(--th-ink); box-shadow: inset 0 0 0 1.5px var(--th-ink); }
@media (hover: hover) { .th-chip--line[aria-checked="false"]:hover { background: color-mix(in srgb, var(--th-ink) 5%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--th-ink) 50%, #fff); } }
.th-chip:active { transform: scale(.96); transition-duration: .1s; }

/* price, compare-at and the sale badge */
.th-price { gap: 12px; }
.th-price__now { font-size: 30px; font-weight: 500; letter-spacing: -.02em; line-height: 1; }
.th-price__was { font-size: 24px; line-height: 1; color: color-mix(in srgb, var(--th-ink) 60%, transparent); text-decoration-thickness: 1.5px; }
.th-badge {
  display: inline-flex; align-items: center; min-height: 28px; padding: 0 12px; border-radius: 99px; font: 500 14px/1 var(--th-f-prod);
  background: var(--th-sale-bg); color: var(--th-sale); font-variant-numeric: tabular-nums;
}
.th-badge--tag { background: color-mix(in srgb, var(--th-ink) 8%, #fff); color: var(--th-ink); }   /* a tag that isn't a saving ("Pre order") */

/* rating: five stars; the filled row is clipped to the value (4.5 of 5 shows a half star) */
.th-rate { position: relative; flex: none; display: block; width: 110px; height: 22px; }
.th-rate svg { display: block; width: 22px; height: 22px; flex: none; }
.th-rate__base, .th-rate__fill { position: absolute; left: 0; top: 0; display: flex; height: 22px; }
.th-rate__base { color: color-mix(in srgb, var(--th-ink) 34%, transparent); }
.th-rate__base use { fill: none; stroke: currentColor; stroke-width: 1.5; }
.th-rate__fill { overflow: hidden; width: calc(var(--r, 0) / 5 * 100%); color: var(--th-star, var(--th-ink)); transition: width .9s var(--th-out) .15s; }
.th-rate__fill use { fill: currentColor; stroke: currentColor; stroke-width: 1.5; }
.th-rate__txt { font-size: 15px; font-weight: 500; font-variant-numeric: tabular-nums; }
.th-sigwrap.is-ready .th-rate:not(.is-in) .th-rate__fill { width: 0; }

/* quantity stepper */
.th-step { display: inline-flex; align-items: center; border-radius: 99px; background: color-mix(in srgb, var(--th-ink) 7%, #fff); }
.th-step__b {
  width: 44px; height: 44px; padding: 0; display: grid; place-items: center; border: 0; border-radius: 50%; background: none; cursor: pointer; color: var(--th-ink);
  transition: background-color .18s ease, transform .18s var(--th-spring), opacity .18s ease; -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
@media (hover: hover) { .th-step__b:not([aria-disabled="true"]):hover { background: color-mix(in srgb, var(--th-ink) 9%, transparent); } }
.th-step__b:not([aria-disabled="true"]):active { transform: scale(.9); transition-duration: .1s; }
.th-step__b[aria-disabled="true"] { opacity: .35; cursor: default; }
.th-step__v { min-width: 36px; text-align: center; font: 500 16px/1 var(--th-f-prod); font-variant-numeric: tabular-nums; }

/* the toast: sits just above the swatch that was clicked */
.th-toast {
  position: absolute; left: 0; top: 0; z-index: 3; margin: 0; padding: 9px 14px; border-radius: 99px; pointer-events: none; white-space: nowrap;
  background: var(--th-ink); color: #fff; font: 500 13px/1.2 var(--th-f-ui); box-shadow: 0 12px 22px -10px rgba(0,0,0,.5);
  opacity: 0; translate: -50% calc(-100% + 6px); transition: opacity .16s ease, translate .25s var(--th-spring);
}
.th-toast.is-on { opacity: 1; translate: -50% calc(-100% - 6px); }

/* ---------- The flying copy (appended to <body> while it travels) ---------- */
.th-fly {
  position: fixed; left: 0; top: 0; z-index: 60; margin: 0; max-width: none; pointer-events: none; transform-origin: 50% 50%; object-fit: contain;
  filter: drop-shadow(0 14px 12px rgba(0,0,0,.28)); will-change: transform;
}

/* ---------- Entrance: items and swatches deal in once, when in view (only once the script has started) ---------- */
.th-sigwrap.is-ready .th-item:not(.is-in), .th-sigwrap.is-ready .th-swatch:not(.is-in) { opacity: 0; translate: 0 22px; }
.th-sigwrap.is-ready .th-item.is-in, .th-sigwrap.is-ready .th-swatch.is-in { translate: 0 0; transition: opacity .5s ease, translate .7s var(--th-out), transform .3s var(--th-spring), box-shadow .3s ease, background-color .2s ease; }

/* ---------- Tablets: the items become a row on top, the box and the receipt share the next row ---------- */
@media (max-width: 1099px) {
  .th-builder { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "items items" "box pay"; }
  .th-items { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .th-pay { align-self: stretch; }
  .th-types { grid-template-columns: 1fr; }
  .th-type { grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.4fr); grid-template-areas: "aa meta sample"; }
  .th-comp--btn, .th-comp--chips { grid-column: span 12; }
  .th-comp--price, .th-comp--rate, .th-comp--qty { grid-column: span 4; }
}
@media (max-width: 899px) {
  .th-items { gap: 12px; }
  .th-type { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "aa meta" "sample sample"; }
  /* the widest sample takes the row, like the buttons and options; rating and quantity share the next.
     Without a rating, .th-comps--norate (higher specificity) keeps price and quantity side by side. */
  .th-comp--price { grid-column: span 12; }
  .th-comp--rate, .th-comp--qty { grid-column: span 6; }
}

/* ---------- Phones: items are a swipeable row above the box; the box keeps its shape (one row of four, or 2 x 3); the receipt comes last ---------- */
@media (max-width: 699px) {
  .th-builder { border-radius: 24px; padding: 18px 16px 16px; gap: 22px; grid-template-columns: minmax(0, 1fr); grid-template-areas: "items" "box" "pay"; }
  .th-items {
    display: flex; gap: 12px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
    margin: -8px -16px; padding: 8px 16px 18px; scroll-padding-inline: 16px;
  }
  .th-items::-webkit-scrollbar { display: none; }
  /* 2.25 cards to a screen: the third shows enough of itself to say the row scrolls */
  .th-items > li { flex: 0 0 max(126px, calc((100% - 24px) / 2.25)); scroll-snap-align: start; }
  .th-item__name { font-size: 16px; }
  .th-boxcol__head { margin-bottom: -8px; }
  .th-box { --pad: 10px; border-radius: 18px 18px 14px 14px; }
  .th-slots { padding: 6px; gap: 5px; }
  .th-slot { aspect-ratio: 3 / 4.1; }
  .th-builder { --th-slot-ar: .7317; }
  .th-box__lip { height: 50px; border-radius: 0 0 14px 14px; }
  .th-box__label { font-size: 22px; padding: 8px 22px 9px; }
  .th-pay { padding: 16px; gap: 14px; }
  .th-sum__row--total dd { font-size: 30px; }
  .th-tok { border-radius: 24px; padding: 20px 16px; gap: 28px; }
  .th-sw { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 10px; }
  .th-swatch__chip { aspect-ratio: 1; border-radius: 12px; margin-bottom: 6px; }
  .th-swatch__name { font-size: 12.5px; }
  .th-swatch__hex { font-size: 12px; letter-spacing: 0; }
  .th-type { grid-template-columns: auto minmax(0, 1fr); padding: 16px; }
  .th-type__aa { font-size: 44px; }
  .th-type__sample { font-size: 21px; }
  .th-comps { grid-template-columns: minmax(0, 1fr); }
  .th-comps > .th-comp { grid-column: auto; }
  .th-comp { padding: 16px; }
  /* a filled and an outline button (Mason Varde's pair) do not fit one row in a phone's card: they stack, each the width of the card, like a product page */
  .th-comp__row--pair { flex-direction: column; align-items: stretch; }
  .th-comp__row--pair .th-b { justify-content: center; white-space: normal; text-align: center; }
}
/* narrow phones: a little less padding and type in the item cards, so every name stays on one line and the prices line up */
@media (max-width: 419px) { .th-item { padding: 8px 8px 12px; } .th-item__name { font-size: 15px; } }
/* large phones: three cards and part of the fourth, not two very wide ones */
@media (min-width: 560px) and (max-width: 699px) { .th-items > li { flex-basis: calc((100% - 36px) / 3.3); } }

/* ---------- Phones: the dock. Off by default; on a phone it is a pill pinned to the bottom of the screen while the box is being filled
   and the receipt is out of view (the script adds .is-off otherwise). It spans the whole grid, so it can stick for the builder's full
   height, and at rest it sits over the receipt's button, where it is always off, so it adds no height. ---------- */
.th-dock { display: none; }
@media (max-width: 699px) {
  .th-dock {
    grid-area: 1 / 1 / -1 / -1; align-self: end; position: sticky; bottom: max(12px, env(safe-area-inset-bottom)); z-index: 2;
    display: flex; align-items: center; gap: 12px; min-height: 60px; padding: 6px 6px 6px 18px; border-radius: 99px;
    background: color-mix(in srgb, #fff 88%, transparent); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
    box-shadow: 0 0 0 1px var(--th-line), 0 18px 30px -18px color-mix(in srgb, var(--th-ink) 70%, transparent);
    transition: opacity .2s ease, translate .3s var(--th-out), visibility 0s;
  }
  .th-dock.is-off { opacity: 0; translate: 0 16px; pointer-events: none; visibility: hidden; transition: opacity .2s ease, translate .3s var(--th-out), visibility 0s .3s; }
  body:has(.vsw) .th-dock { bottom: 88px; }   /* the review pages' A/B pill sits at the bottom of the screen */
  .th-dock__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .th-dock__top { display: flex; align-items: baseline; gap: 8px; }
  .th-dock__top .th-money { font: 600 20px/1.1 var(--th-f-prod); letter-spacing: -.02em; }
  .th-dock__n { font: 500 12px/1 var(--th-f-ui); font-variant-numeric: tabular-nums; color: var(--th-muted); }
  .th-dock__n b { font-weight: 600; color: var(--th-ink); }
  .th-dock__tier {
    font-size: 12px; font-weight: 500; line-height: 1.25; color: var(--th-muted); text-wrap: balance;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
  }
  .th-dock__tier:empty { display: none; }
  .th-dock__cta {
    flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-width: 44px; min-height: 48px; padding: 0 18px;
    border: 0; border-radius: 99px; cursor: pointer; background: var(--th-ink); color: #fff; font: 600 14px/1.2 var(--th-f-ui); white-space: nowrap;
    transition: background-color .2s ease, color .2s ease, transform .2s var(--th-spring); -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  }
  .th-dock__cta:not(:disabled):active { transform: scale(.97); transition-duration: .1s; }
  .th-dock__cta:disabled { cursor: default; background: color-mix(in srgb, var(--th-ink) 14%, transparent); color: color-mix(in srgb, var(--th-ink) 48%, transparent); }
  .th-dock__cta .th-cta__check { display: none; }
  .th-dock__cta.is-done { background: var(--th-accent); }
  .th-dock__cta.is-done .th-cta__check { display: block; animation: th-pop .45s var(--th-spring); }
}

/* ---------- Reduced motion: no flying, no shimmer, no rolling, no entrance; everything shows its finished state ---------- */
@media (prefers-reduced-motion: reduce) {
  .th-sigwrap *, .th-sigwrap *::before, .th-sigwrap *::after { animation: none !important; transition: none !important; }
  .th-sigwrap.is-ready .th-item:not(.is-in), .th-sigwrap.is-ready .th-swatch:not(.is-in) { opacity: 1; translate: 0 0; }
  .th-item:hover, .th-item:hover .th-item__img, .th-swatch:hover .th-swatch__chip, .th-slot.is-full:hover { transform: none; }
  .th-sigwrap.is-ready .th-rate:not(.is-in) .th-rate__fill { width: calc(var(--r, 0) / 5 * 100%); }
}
