/* QuoteIt v2 "Radiant" — design/v2/BRIEF.md, built 25 Sep 2026.
   One ground, one tray, one key: the red ground stays, every control is a white
   key that goes DOWN red, and every tray is white.

   Order (BRIEF §9): 1 tokens · 2 base · 3 chrome · 4 components · 5 screens ·
   6 overlays · 7 motion · 8 modes (bright sun, pink trays, wide) · 9 reduced
   motion. One :root, no appended override layers. Tokens mirror
   design/v2/gen/tokens.py — change a value there and here together. */

/* ============================================================ 1 · tokens */
:root {
  /* colour — BRIEF §4.1. Red is the brand, the ground and the selected key; it
     never marks an error, a problem or a shortfall. */
  --ground: #E5252B;
  --ground-hi: #EE3A3F;
  --ground-deep: #C41A21;
  --ground-ink: #8E0F15;
  --tray: #FFFFFF;
  --well: #F4F0EF;
  --well-2: #E9E2E0;
  --rule: #ECE6E5;
  --ink: #16171A;
  --ink-2: #45484F;
  --ink-3: #6B6F77;
  --good: #1E9E5A;
  --good-ink: #147A45;
  --good-wash: #E7F5EC;
  --advice: #E08A00;
  --advice-ink: #9A5200;
  --advice-wash: #FFF4E5;
  --heat-0: #FFE7D6;
  --heat-1: #FFC09A;
  --heat-2: #FF8A57;
  --heat-3: #F2553A;
  --graphite: #24262A;
  --track-off: #D9D1CF;

  --key-face: linear-gradient(180deg, #FFFFFF 0%, #F6F1F0 100%);
  --down-face: linear-gradient(180deg, #E8292F 0%, #D61D23 100%);
  --red-face: linear-gradient(180deg, #EE3A40 0%, #D61D23 100%);
  --stage-bg: radial-gradient(120% 90% at 50% 38%, #D8232A 0%, #B9161D 58%, #8E0F15 100%);
  /* Heat view (House survey, 7 Oct 2026): a thermal camera's dark, cool ground,
     so the warm colours (heat being lost) read; the normal view stays red */
  --thermal-bg: radial-gradient(115% 95% at 62% 42%, #26343E 0%, #19242C 52%, #0E151A 100%);

  /* material — BRIEF §4.4: ground, tray, key, well, stage; sheet and dock float */
  --sh-tray: 0 1px 0 rgba(90, 10, 15, 0.10), 0 10px 26px rgba(120, 10, 15, 0.22);
  --sh-key: inset 0 1px 0 #FFFFFF, inset 0 -3px 0 rgba(90, 20, 25, 0.12), 0 2px 0 rgba(90, 10, 15, 0.18), 0 6px 14px rgba(120, 10, 15, 0.18);
  --sh-key-ground: inset 0 1px 0 #FFFFFF, inset 0 -3px 0 rgba(90, 20, 25, 0.14), 0 2px 0 rgba(90, 10, 15, 0.30), 0 10px 22px rgba(90, 5, 10, 0.34);
  --sh-key-pressed: inset 0 1px 0 #FFFFFF, inset 0 -1px 0 rgba(90, 20, 25, 0.12), 0 1px 0 rgba(90, 10, 15, 0.18), 0 2px 4px rgba(120, 10, 15, 0.14);
  --sh-down: inset 0 3px 6px rgba(0, 0, 0, 0.30), inset 0 1px 0 rgba(0, 0, 0, 0.22), 0 1px 0 rgba(60, 0, 5, 0.22);
  --sh-red: inset 0 1px 0 rgba(255, 255, 255, 0.28), inset 0 -3px 0 rgba(0, 0, 0, 0.25), 0 2px 0 rgba(60, 0, 5, 0.35), 0 8px 18px rgba(120, 10, 15, 0.30);
  --sh-red-pressed: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(60, 0, 5, 0.35), 0 3px 6px rgba(120, 10, 15, 0.25);
  --sh-dock: 0 10px 30px rgba(60, 0, 5, 0.35);
  --sh-sheet: 0 -16px 48px rgba(60, 0, 5, 0.40);
  --sh-well: inset 0 1px 3px rgba(60, 10, 15, 0.10);
  --sh-stage: inset 0 2px 14px rgba(60, 0, 5, 0.45);
  --sh-chip: 0 4px 12px rgba(60, 0, 5, 0.35);

  /* type — Manrope only (ruled 10 Sep), weights 500–800, tabular figures */
  --font: "Manrope", "Trebuchet MS", sans-serif;

  /* space, size, radius — BRIEF §4.3 */
  --gutter: 16px;
  --r-key: 16px;
  --r-well: 14px;
  --r-tray: 24px;
  --r-stage: 20px;
  --r-sheet: 28px;
  --r-dock: 28px;
  --dock-h: 64px;
  --bar-h: 68px;
  --frame-w: 100vw;
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
  --hdr-now: 72px; /* set live by the header (ResizeObserver) */

  /* motion — BRIEF §4.5 (static/motion.js mirrors the numbers) */
  --t-tap: 90ms;
  --t-settle: 180ms;
  --t-move: 240ms;
  --t-sheet: 340ms;
  --t-roll: 420ms;
  --t-count: 500ms;
  --t-long: 700ms;
  --t-hero: 900ms;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-pop: cubic-bezier(0.34, 1.4, 0.64, 1);
  --ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-enter: cubic-bezier(0.05, 0.7, 0.1, 1);
  --stagger: 35ms;

  /* weights that Bright sun mode lifts */
  --w-body: 600;
  --w-strong: 700;
}

@media (min-width: 600px) {
  :root {
    --frame-w: 460px;
  }
}

/* a tablet held upright (600-899 px): use the width (owner, 30 Sep 2026: a
   phone column with red either side). The column grows to 820 px; the keys,
   the 3D stages and the lists grow with it. Landscape keeps the two panes
   from 900 px (section 8), and phones (< 600 px) are untouched. */
@media (min-width: 600px) and (max-width: 899px) and (orientation: portrait) {
  :root {
    --frame-w: min(100vw, 820px);
    --gutter: 24px;
    --stage-pick: 380px; /* the room in 3D needs the height (7 Oct 2026; was 340) */
    --stage-house: 300px;
    --stage-room: 250px;
    --stage-show: 380px;
    --stage-show-home: 300px;
  }
}

/* ============================================================ 2 · base */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  color: var(--ink);
  font-family: var(--font);
}

/* the ground is painted on the canvas (html) so the ambient highlights at
   z-index −1 sit between it and the content */
html {
  background: var(--ground);
  /* keyboard focus scrolls a key clear of the fixed header, Quote Bar and dock */
  scroll-padding-top: 140px;
  scroll-padding-bottom: 190px;
}

body {
  background: transparent;
}

a.key,
a.key-icon {
  text-decoration: none;
}

body {
  font-weight: var(--w-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-variant-numeric: tabular-nums;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  margin: 0;
  padding: 0;
  cursor: pointer;
  text-align: inherit;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
}

button:disabled {
  cursor: default;
}

input,
select,
textarea {
  font: inherit;
  color: inherit;
  margin: 0;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

p,
h1,
h2,
h3,
ul,
ol {
  margin: 0;
  padding: 0;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.on-ground :focus-visible,
.hdr :focus-visible,
.rail :focus-visible,
.stage :focus-visible,
.show :focus-visible,
.celebrate :focus-visible {
  outline-color: #FFFFFF;
}

.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.tnum {
  font-variant-numeric: tabular-nums;
}

/* The app column. Phones: the whole width; tablets: a 460 px column on the red.
   Two panes from 900 px live in section 8. */
#app {
  min-height: 100vh;
}

/* No isolation here on purpose: the fixed header, strip, fade and Quote Bar
   inside the screen must stack against the dock, sheets and toasts at the root. */
.frame {
  position: relative;
  max-width: var(--frame-w);
  min-height: 100vh;
  margin: 0 auto;
}

/* e0 ground — flat red plus two slow ambient highlights (≤ 8 %) */
.frame::before,
.frame::after {
  content: "";
  position: fixed;
  z-index: -1;
  pointer-events: none;
  width: 78vw;
  height: 46vh;
  border-radius: 50%;
  will-change: transform;
}

.frame::before {
  top: 2%;
  left: -18%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0) 72%);
  animation: ground-drift-a 40s linear infinite;
}

.frame::after {
  bottom: 0;
  right: -22%;
  background: radial-gradient(closest-side, rgba(142, 15, 21, 0.28), rgba(142, 15, 21, 0) 72%);
  animation: ground-drift-b 40s linear infinite;
}

/* every screen: a fixed header, a spacer that keeps its expanded height in flow,
   and a body column that leaves room for the Quote Bar and the dock */
.screen {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* scrolled to the end, the last card clears the dock's fade (.scrim, 130
     px) instead of washing out pink under it (8 Oct 2026; was dock + 40) */
  padding: 12px var(--gutter) calc(var(--dock-h) + 72px + var(--safe-b));
}

.screen.has-bar .body {
  padding-bottom: calc(var(--dock-h) + var(--bar-h) + 56px + var(--safe-b));
}

.screen.no-dock .body {
  padding-bottom: calc(32px + var(--safe-b));
}

/* ============================================================ 3 · chrome */

/* ---- header (BRIEF §6.7): pinned, back key, title, customer, one ⋯ key ---- */
.hdr {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  max-width: var(--frame-w);
  margin: 0 auto;
  padding: calc(12px + var(--safe-t)) var(--gutter) 10px;
  background: var(--ground);
  transition: box-shadow var(--t-settle) var(--ease);
}

.hdr.is-scrolled {
  box-shadow: 0 14px 18px -14px rgba(90, 5, 10, 0.55);
}

.hdr-spacer {
  flex: 0 0 auto;
}

.hdr-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
}

.hdr-titles {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.hdr-title {
  font-size: 30px;
  line-height: 34px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #FFFFFF;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: font-size var(--t-settle) var(--ease), line-height var(--t-settle) var(--ease);
}

.hdr-sub {
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  color: #FFFFFF;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hdr.is-compact .hdr-title {
  font-size: 22px;
  line-height: 28px;
}

.hdr-mark {
  flex: 0 0 auto;
  display: block;
}

/* the logo in a header (ui.js BrandLockup, the Today screen): Quoty's
   plain-name compact, smaller once the header collapses */
.hdr-lockup {
  flex: 0 0 auto;
  display: block;
  width: auto;
  height: 34px;
  margin: 0 6px 0 -3px; /* the file keeps room for the tag's shadow; then air before the title */
  transition: height var(--t-settle) var(--ease);
}

.hdr.is-compact .hdr-lockup {
  height: 28px;
}

/* the menu rail's mark (ui.js BrandMark): Quoty's house tag */
.brand-tag {
  flex: 0 0 auto;
  display: block;
}

/* the step bar (v3): Visit · House · Rooms · Quote · Sign — always shown on
   quote screens. Each step is a key: the current one is a white key with red
   text; done steps carry a tick, a step that needs a look an advisory flag;
   steps not reached yet keep a dim segment and cannot be tapped. Labels stay
   pure white on the red (no translucent text). */
.steps {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 4px;
  padding: 10px 0 0;
  transition: padding var(--t-settle) var(--ease);
}

.step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 0;
  min-height: 44px;
  padding: 0 0 2px;
  border-radius: 12px;
  color: #FFFFFF;
}

.step-seg {
  align-self: stretch;
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.34);
  transition: background var(--t-settle) var(--ease);
}

.step.is-reached .step-seg {
  background: #FFFFFF;
}

.step-name {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 6px;
  border-radius: 999px;
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background var(--t-settle) var(--ease), transform var(--t-tap) var(--ease);
}

.step.is-current .step-name {
  padding: 0 9px;
  background: #FFFFFF;
  color: var(--ground);
  box-shadow: 0 2px 0 rgba(90, 10, 15, 0.3);
}

/* done / needs a look: a badge on the label's corner, so the label alone sets
   the width (fits five steps across a 360 px phone). Green = good, amber = advice. */
.step-badge {
  position: absolute;
  top: -8px;
  right: -11px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 99px;
  background: #FFFFFF;
  box-shadow: 0 1px 2px rgba(90, 10, 15, 0.35);
}

.step-badge.is-done {
  color: var(--good-ink);
}

.step-badge.is-attention {
  color: var(--advice);
}

.step-badge .q-icon {
  width: 11px;
  height: 11px;
}

.step:not(:disabled):not(.is-current):active .step-name {
  background: rgba(255, 255, 255, 0.16);
  transform: translateY(1px);
}

.step:disabled {
  cursor: default;
}

.hdr.is-compact .steps {
  padding-top: 6px;
}

/* ---- the dock (BRIEF §6.8): a floating white pill, key-down active tab ---- */
.dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(12px + var(--safe-b));
  z-index: 50;
  width: calc(min(100vw, var(--frame-w)) - 24px);
  margin: 0 auto;
  height: var(--dock-h);
  padding: 6px;
  display: flex;
  gap: 4px;
  border-radius: var(--r-dock);
  background: #FFFFFF;
  box-shadow: var(--sh-dock);
}

.dock-tab {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  height: 52px;
  border-radius: 22px;
  color: var(--ink-2);
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  white-space: nowrap;
  transition: transform var(--t-tap) var(--ease), background var(--t-settle) var(--ease), color var(--t-settle) var(--ease);
}

.dock-tab .q-icon {
  width: 22px;
  height: 22px;
}

.dock-tab:active {
  transform: translateY(1px) scale(0.97);
}

.dock-tab[aria-current="page"] {
  background: var(--down-face);
  box-shadow: var(--sh-down);
  color: #FFFFFF;
  transform: translateY(1px);
}

.dock-dot {
  position: absolute;
  top: 6px;
  right: calc(50% - 18px);
  width: 8px;
  height: 8px;
  border-radius: 99px;
  background: var(--ground);
  box-shadow: 0 0 0 2px #FFFFFF;
}

/* the fade behind the Quote Bar and the dock: content scrolls under them */
.scrim {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  max-width: var(--frame-w);
  margin: 0 auto;
  height: calc(130px + var(--safe-b));
  pointer-events: none;
  background: linear-gradient(180deg, rgba(229, 37, 43, 0) 0%, rgba(229, 37, 43, 0.94) 38%, #E5252B 60%);
}

.scrim.is-tall {
  height: calc(196px + var(--safe-b));
}

/* ---- the Quote Bar (BRIEF §6.1): the price always in view ---- */
.qbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(12px + var(--dock-h) + 12px + var(--safe-b));
  z-index: 45;
  width: calc(min(100vw, var(--frame-w)) - 24px);
  margin: 0 auto;
  height: var(--bar-h);
  padding: 8px 8px 8px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-radius: 24px;
  background: #FFFFFF;
  box-shadow: var(--sh-dock);
}

/* the price never shrinks: the figure sets this half's width (the caption,
   width 0 / min-width 100%, fills it without widening it) and the next key
   gives way instead, ellipsizing its words */
.qbar-open {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  text-align: left;
  border-radius: 14px;
}

.qbar-figure {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 28px;
}

.qbar-caption {
  width: 0;
  min-width: 100%;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  line-height: 17px;
  font-weight: 700;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.qbar-caption > span {
  overflow: hidden;
  text-overflow: ellipsis;
}

.qbar-dot {
  flex: 0 0 8px;
  width: 8px;
  height: 8px;
  border-radius: 99px;
  background: var(--advice);
}

.qbar-saved {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--good-ink);
  font-weight: 800;
}

.qbar-signal {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px;
  height: 20px;
  border-radius: 999px;
  background: var(--advice-wash);
  color: var(--advice-ink);
  font-weight: 800;
}

.qbar-signal .q-icon,
.qbar-saved .q-icon {
  flex: 0 0 auto;
}

.qbar-next {
  flex: 0 1 auto;
  min-width: 0;
  height: 52px;
  padding: 0 14px 0 16px;
  gap: 8px;
  border-radius: 18px;
  max-width: 60%;
}

.qbar-next > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.qbar-next.has-kicker {
  max-width: 64%;
  padding: 0 12px 0 14px;
  gap: 6px;
}

/* the next key with a kicker: "PICK RADIATORS · 1 OF 3" over "Lounge" */
.qbar-next.has-kicker > span {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-width: 0;
  text-align: left;
}

.qbar-kicker {
  max-width: 100%;
  font-size: 11px;
  line-height: 13px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.qbar-label {
  max-width: 100%;
  font-size: 17px;
  line-height: 21px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.delta-chip {
  position: absolute;
  left: 16px;
  top: -34px;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--ink);
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
  box-shadow: 0 4px 10px rgba(22, 23, 26, 0.3);
  pointer-events: none;
  animation: delta-rise 1200ms var(--ease-pop) both;
}

/* ---- the running total: an odometer (BRIEF §5 moment 1) ---- */
.odo {
  display: inline-flex;
  align-items: baseline;
  font-size: 24px;
  line-height: 28px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.odo-small {
  font-size: 15px;
  color: var(--ink-3);
  letter-spacing: 0;
}

.odo-cur {
  margin-right: 1px;
}

.odo-digit {
  display: inline-block;
  position: relative;
  height: 1.17em;
  overflow: hidden;
  vertical-align: bottom;
}

.odo-strip {
  display: flex;
  flex-direction: column;
  transition: transform var(--t-roll) var(--ease);
  will-change: transform;
}

.odo-strip > span {
  display: block;
  height: 1.17em;
  line-height: 1.17em;
  text-align: center;
}

.odo-static {
  display: inline-block;
}

.qbar-unit {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-3);
  letter-spacing: 0;
  margin-left: 4px;
}

/* ---- toast (BRIEF §6.15): ink, above the dock, never over it ---- */
.toast {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(12px + var(--dock-h) + 12px + var(--safe-b));
  z-index: 60;
  width: calc(min(100vw, var(--frame-w)) - 32px);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 8px 8px 8px 16px;
  border-radius: 18px;
  background: var(--ink);
  color: #FFFFFF;
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  box-shadow: 0 12px 28px rgba(22, 23, 26, 0.35);
  animation: toast-in var(--t-move) var(--ease) both;
}

.toast.above-bar {
  bottom: calc(12px + var(--dock-h) + 12px + var(--bar-h) + 10px + var(--safe-b));
}

.toast.no-dock {
  bottom: calc(16px + var(--safe-b));
}

.toast.is-leaving {
  animation: toast-out var(--t-move) var(--ease) both;
}

.toast-text {
  flex: 1 1 auto;
  min-width: 0;
}

.toast-action {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.14);
  color: #FFFFFF;
  font-size: 15px;
  font-weight: 800;
}

.toast-action:active {
  transform: translateY(1px);
}

/* ============================================================ 4 · components */

/* ---- type ---- */
.label {
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.label.on-ground,
.day-label {
  color: #FFFFFF;
}

.day-label {
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 2px 0;
}

.caption {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
}

.help {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 15px;
  line-height: 21px;
  font-weight: 600;
  color: var(--ink-2);
}

.help .q-icon {
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--ink-3);
}

.help.on-ground,
.help.on-ground .q-icon {
  color: #FFFFFF;
}

.mt4 {
  margin-top: 4px;
}

.verdict {
  font-size: 22px;
  line-height: 30px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: #FFFFFF;
  padding: 4px 2px 2px;
  text-wrap: pretty;
}

.hl {
  display: inline-block;
  padding: 0 8px;
  border-radius: 9px;
  background: #FFFFFF;
  color: var(--ground);
  line-height: 28px;
  font-variant-numeric: tabular-nums;
}

.title-s {
  font-size: 18px;
  line-height: 24px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

/* hero money: the £ and the pence set at 55 % in ink-3 (BRIEF §4.2) */
.fig {
  display: inline-flex;
  align-items: baseline;
  font-size: 48px;
  line-height: 50px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.fig-small {
  font-size: 0.55em;
  font-weight: 700;
  color: var(--ink-3);
  letter-spacing: 0;
}

.fig-cur {
  margin-right: 2px;
}

.fig.on-ground,
.fig.on-ground .fig-small {
  color: #FFFFFF;
}

.fig.is-xl {
  font-size: 64px;
  line-height: 66px;
  letter-spacing: -0.035em;
}

.fig.is-l {
  font-size: 52px;
  line-height: 54px;
}

.fig.is-m {
  font-size: 40px;
  line-height: 42px;
}

.fig.is-s {
  font-size: 26px;
  line-height: 30px;
  letter-spacing: -0.02em;
}

.fig.is-xs {
  font-size: 22px;
  line-height: 26px;
  letter-spacing: -0.02em;
}

.fig.is-good,
.fig.is-good .fig-small {
  color: var(--good-ink);
}

.num {
  display: inline-flex;
  align-items: baseline;
  font-size: 36px;
  line-height: 38px;
  font-weight: 800;
  letter-spacing: -0.025em;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.num-unit {
  font-size: max(13px, 0.45em);
  font-weight: 700;
  color: var(--ink-3);
  letter-spacing: 0;
  margin-left: 4px;
}

.num.is-xl {
  font-size: 52px;
  line-height: 54px;
}

.num.is-l {
  font-size: 48px;
  line-height: 50px;
}

.num.is-m {
  font-size: 40px;
  line-height: 42px;
}

.num.is-s {
  font-size: 28px;
  line-height: 30px;
}

.num.is-xs {
  font-size: 24px;
  line-height: 28px;
}

.num.is-muted {
  color: var(--ink-3);
}

.num.on-ground,
.num.on-ground .num-unit {
  color: #FFFFFF;
}

/* ---- tray (e1) ---- */
.tray {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border-radius: var(--r-tray);
  background: var(--tray);
  box-shadow: var(--sh-tray);
  min-width: 0;
}

.tray.is-tight {
  gap: 4px;
}

.tray.is-rows {
  gap: 0;
  padding: 4px 16px;
}

.tray-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 28px;
}

.tray-head .label {
  flex: 1 1 auto;
}

/* the signer tag (a customer's name) must shrink and ellipsise rather than
   overflow the tray on a phone — flex items don't shrink past their content's
   intrinsic (nowrap) width unless min-width is reset */
.tray-head .tag {
  min-width: 0;
}

/* .tag is itself a flex row (icon + text): text-overflow has no effect on a
   flex container's own box, only on a single block/inline-block run of
   content, so the name needs its own shrinking, clipped, ellipsised span */
.tag-clip {
  min-width: 0;
}

.tag-clip-text {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rule {
  height: 1px;
  flex: 0 0 1px;
  background: var(--rule);
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

/* ---- the key (BRIEF §6.2): the one control ---- */
.key {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 48px;
  min-width: 48px;
  padding: 0 14px;
  border-radius: var(--r-key);
  background: var(--key-face);
  box-shadow: var(--sh-key);
  color: var(--ink);
  font-size: 17px;
  line-height: 1.1;
  font-weight: 800;
  letter-spacing: -0.005em;
  white-space: nowrap;
  text-align: center;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease), background var(--t-settle) var(--ease),
    color var(--t-settle) var(--ease);
}

.key .q-icon {
  flex: 0 0 auto;
  color: var(--ground);
  transition: color var(--t-settle) var(--ease), transform var(--t-settle) var(--ease-pop);
}

.key:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: var(--sh-key-pressed);
}

.key.is-s {
  height: 40px;
  min-width: 40px;
  padding: 0 12px;
  font-size: 15px;
  border-radius: 12px;
}

.key.is-l {
  height: 56px;
  padding: 0 18px;
  border-radius: 999px;
}

.key.is-xl {
  height: 64px;
  padding: 0 20px;
  border-radius: 999px;
  font-size: 19px;
}

.key.is-full {
  width: 100%;
}

/* a key whose label can outgrow it ("Call Dr Rabi Thakur-Wolstenholme" in
   half a row on a saved quote): the label ends in an ellipsis inside the key */
.key.key-fit > span {
  min-width: 0;
  padding: 2px 0; /* room for descenders under the clip */
  overflow: hidden;
  text-overflow: ellipsis;
}

.key.is-pill {
  border-radius: 999px;
}

.key.is-start {
  justify-content: flex-start;
  text-align: left;
}

/* red — the primary inside a tray or sheet */
.key.is-red {
  background: var(--red-face);
  box-shadow: var(--sh-red);
  color: #FFFFFF;
}

.key.is-red .q-icon {
  color: #FFFFFF;
}

.key.is-red:active:not(:disabled) {
  box-shadow: var(--sh-red-pressed);
}

/* white on the ground — the primary on the red */
.key.is-ground {
  box-shadow: var(--sh-key-ground);
  color: var(--ground);
}

/* ghost — quiet actions */
.key.is-ghost {
  background: transparent;
  box-shadow: none;
  color: var(--ink);
}

.key.is-ghost:active:not(:disabled) {
  box-shadow: none;
  background: rgba(22, 23, 26, 0.06);
}

.key.is-ghost.on-ground,
.on-ground .key.is-ghost {
  color: #FFFFFF;
}

.key.is-ghost.on-ground .q-icon,
.on-ground .key.is-ghost .q-icon {
  color: #FFFFFF;
}

.key.is-ghost.on-ground:active:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
}

/* the selected key: down and red, white text and icon, no ring, stays sunk */
.key.is-down,
.key[aria-pressed="true"] {
  background: var(--down-face);
  box-shadow: var(--sh-down);
  color: #FFFFFF;
  transform: translateY(2px);
}

.key.is-down .q-icon,
.key[aria-pressed="true"] .q-icon {
  color: #FFFFFF;
}

.key.is-down .key-sub,
.key[aria-pressed="true"] .key-sub {
  color: #FFFFFF;
}

.key:disabled {
  background: var(--well);
  box-shadow: none;
  color: var(--ink-3);
}

.key:disabled .q-icon {
  color: var(--ink-3);
}

.key.is-busy > * {
  visibility: hidden;
}

.key.is-busy::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 28px;
  height: 6px;
  background: radial-gradient(circle at 3px 3px, currentColor 2.6px, transparent 3px) 0 0 / 11px 6px repeat-x;
  animation: busy-dots 900ms steps(3) infinite;
  visibility: visible;
}

.key-sub {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-3);
  line-height: 1.1;
}

.key-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}

/* a disabled key never sits alone: the reason is written under it */
.key-reason {
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: var(--ink-3);
  text-align: center;
}

.key-reason.on-ground {
  color: #FFFFFF;
}

/* the round icon key, 44 px */
.key-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--key-face);
  box-shadow: var(--sh-key);
  color: var(--ink);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.key-icon .q-icon {
  width: 20px;
  height: 20px;
}

.key-icon:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: var(--sh-key-pressed);
}

.key-icon.is-ground {
  box-shadow: var(--sh-key-ground);
}

.key-icon.is-red {
  background: var(--red-face);
  box-shadow: var(--sh-red);
  color: #FFFFFF;
}

.key-icon.is-well {
  background: var(--well);
  box-shadow: none;
  color: var(--ink-2);
}

.key-icon.is-glass {
  background: rgba(255, 255, 255, 0.14);
  box-shadow: none;
  color: #FFFFFF;
}

.key-icon.is-s {
  flex-basis: 40px;
  width: 40px;
  height: 40px;
}

.key-icon.is-xs {
  flex-basis: 36px;
  width: 36px;
  height: 36px;
}

.key-icon:disabled {
  background: var(--well);
  box-shadow: none;
  color: var(--ink-3);
  opacity: 0.8;
}

.key-icon.is-tint .q-icon {
  color: var(--ground);
}

.key-icon.is-tint:disabled .q-icon {
  color: var(--ink-3);
}

/* ---- choice keys (BRIEF §6.3) ---- */
.seg {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 8px;
}

.seg > .key {
  min-width: 0;
  padding: 6px 8px;
  border-radius: 14px;
  white-space: normal;
  line-height: 1.15;
}

.seg.is-tall > .key {
  height: auto;
  min-height: 62px;
  flex-direction: column;
  gap: 3px;
}

.seg.is-numerals > .key {
  height: 54px;
  font-size: 19px;
}

.seg.is-quiet > .key {
  height: 44px;
  font-size: 15px;
}

/* the fabric answer: icon, answer, grade word under it (hidden in Show mode) */
.choice {
  height: auto;
  min-height: 76px;
  flex-direction: column;
  gap: 4px;
  padding: 8px 6px;
  font-size: 15px;
}

.choice .q-icon {
  width: 22px;
  height: 22px;
}

.choice-grade {
  font-size: 12px;
  line-height: 14px;
  font-weight: 700;
  color: var(--ink-3);
}

.key.is-down .choice-grade,
.key[aria-pressed="true"] .choice-grade {
  color: #FFFFFF;
}

.wrap-keys {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.wrap-keys > .key {
  border-radius: 999px;
}

/* a horizontal strip of keys that scrolls (presets, filters) */
.scroll-keys {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  margin: 0 calc(-1 * var(--gutter));
  padding: 4px var(--gutter) 6px;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent);
  mask-image: linear-gradient(90deg, #000 88%, transparent);
}

.tray .scroll-keys {
  margin: 0 -16px;
  padding: 4px 16px 6px;
}

.scroll-keys::-webkit-scrollbar {
  display: none;
}

.scroll-keys > .key {
  flex: 0 0 auto;
  border-radius: 999px;
}

/* ---- toggle (BRIEF §6.4): a native checkbox switch, 52 × 32 ---- */
.switch {
  position: relative;
  display: inline-block;
  flex: 0 0 52px;
  width: 52px;
  height: 32px;
}

.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}

.switch-track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: var(--track-off);
  box-shadow: inset 0 1px 3px rgba(60, 10, 15, 0.22);
  transition: background var(--t-settle) var(--ease), box-shadow var(--t-settle) var(--ease);
}

.switch-knob {
  position: absolute;
  top: 4px;
  left: 4px;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: #FFFFFF;
  box-shadow: 0 1px 3px rgba(60, 10, 15, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ground);
  transition: transform var(--t-settle) var(--ease-pop), width var(--t-tap) var(--ease);
}

.switch-knob svg {
  opacity: 0;
  transform: scale(0.4);
  transition: opacity 120ms var(--ease) 60ms, transform 160ms var(--ease-pop) 60ms;
}

.switch input:checked + .switch-track {
  background: var(--red-face);
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.22), 0 1px 0 rgba(60, 0, 5, 0.25);
}

.switch input:checked + .switch-track .switch-knob {
  transform: translateX(20px);
}

.switch input:checked + .switch-track .switch-knob svg {
  opacity: 1;
  transform: none;
}

.switch input:active + .switch-track .switch-knob {
  width: 28px;
}

.switch input:checked:active + .switch-track .switch-knob {
  transform: translateX(16px);
}

.switch input:focus-visible + .switch-track {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.switch input:disabled + .switch-track {
  opacity: 0.45;
}

/* ---- stepper (BRIEF §6.5): − · value in a well · + ---- */
.stepper {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}

.stepper-val {
  min-width: 36px;
  height: 40px;
  padding: 0 4px;
  border-radius: 12px;
  background: var(--well);
  box-shadow: var(--sh-well);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.stepper.is-compact .key-icon {
  flex-basis: 36px;
  width: 36px;
  height: 36px;
}

/* 36 px keys in dense rows still get a 44 px target (BRIEF §3.6) */
.stepper.is-compact .key-icon::after,
.key-icon.is-xs::after {
  content: "";
  position: absolute;
  inset: -4px;
}

.stepper.is-compact .stepper-val {
  height: 36px;
  min-width: 34px;
}

/* ---- well (BRIEF §6.6): labelled, unit inside, no spinners ---- */
.well {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 0;
}

.well-field {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 52px;
  padding: 0 14px;
  border-radius: var(--r-well);
  background: var(--well);
  box-shadow: var(--sh-well);
  font-size: 17px;
  font-weight: 800;
  color: var(--ink);
  transition: box-shadow var(--t-settle) var(--ease);
}

.well-field.is-big {
  height: 56px;
  font-size: 22px;
}

.well-field.is-area {
  height: auto;
  min-height: 52px;
  padding: 12px 14px;
}

.well-field input,
.well-field textarea,
.well-field select {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  border: 0;
  background: transparent;
  font: inherit;
  color: inherit;
  outline: none;
  padding: 0;
}

.well-field textarea {
  resize: none;
  font-size: 15px;
  font-weight: 700;
  line-height: 21px;
}

.well-field input::placeholder,
.well-field textarea::placeholder {
  color: var(--ink-3);
  font-weight: 600;
  opacity: 1;
}

.well-field:focus-within,
.well-field.is-active {
  box-shadow: inset 0 0 0 2px var(--ground);
}

.well-unit {
  flex: 0 0 auto;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-3);
}

.well-prefix {
  flex: 0 0 auto;
  font-size: 17px;
  font-weight: 800;
  color: var(--ink-3);
}

.well-hint {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: var(--advice-ink);
}

.well-hint .q-icon {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin-top: 1px;
  color: var(--advice);
}

.well-field .key-icon {
  margin-right: -8px;
}

/* ---- tags (BRIEF §6.11): read-only, never tappable ---- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--well);
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tag .q-icon {
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
}

.tag.is-sm {
  height: 24px;
  padding: 0 8px;
  font-size: 12px;
}

.tag.is-good {
  background: var(--good-wash);
  color: var(--good-ink);
}

.tag.is-advice {
  background: var(--advice-wash);
  color: var(--advice-ink);
}

.tag.is-ink {
  background: var(--ink);
  color: #FFFFFF;
}

.tag.is-onground {
  background: #FFFFFF;
  color: var(--ground);
}

.tag.is-glass {
  background: rgba(255, 255, 255, 0.16);
  color: #FFFFFF;
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* ---- meters (BRIEF §6.10): coverage ink/green, load green/amber, never red ---- */
.meter {
  position: relative;
  width: 100%;
  height: 10px;
  border-radius: 999px;
  background: var(--well-2);
  box-shadow: var(--sh-well);
}

.meter.is-thin {
  height: 8px;
}

.meter-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 999px;
  background: var(--ink);
  transition: width var(--t-count) var(--ease), background var(--t-settle) var(--ease);
}

.meter-fill.is-good {
  background: var(--good);
}

.meter-fill.is-advice {
  background: var(--advice);
}

.meter-mark {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  margin-left: -1px;
  border-radius: 2px;
  background: var(--ink);
}

.meter-grid {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 1px;
  background: var(--ink-3);
}

.meter.is-unknown {
  background: repeating-linear-gradient(90deg, var(--well-2) 0 6px, transparent 6px 10px);
  box-shadow: none;
}

.load-line {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  line-height: 20px;
  font-weight: 800;
  color: var(--good-ink);
}

.load-line .q-icon {
  flex: 0 0 auto;
  color: var(--good);
}

.load-line.is-advice {
  color: var(--advice-ink);
}

.load-line.is-advice .q-icon {
  color: var(--advice);
}

.load-line.is-unknown {
  color: var(--ink-2);
}

.load-line.is-unknown .q-icon {
  color: var(--ink-3);
}

.load-line .grow {
  flex: 1 1 auto;
}

.load-note {
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: var(--advice-ink);
}

.load-note.is-muted {
  color: var(--ink-3);
}

/* ---- rows (inside trays, --rule dividers) ---- */
.row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 8px 0;
}

.row + .row,
.row-sep {
  border-top: 1px solid var(--rule);
}

.row > .q-icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--ground);
}

.row-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.row-title {
  font-size: 17px;
  line-height: 22px;
  font-weight: var(--w-strong);
  color: var(--ink);
}

.row-sub {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.row-value {
  flex: 0 0 auto;
  font-size: 16px;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.row-value.is-muted {
  color: var(--ink-2);
}

button.row {
  width: 100%;
  text-align: left;
}

button.row:active {
  background: rgba(22, 23, 26, 0.04);
}

.row.is-col {
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 10px 0;
}

.row-head {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 17px;
  font-weight: var(--w-strong);
}

.row-head .q-icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--ground);
}

/* ---- stage (every 3D host): a deep-red studio (BRIEF §6.9) ---- */
.stage {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-stage);
  background: var(--stage-bg);
  box-shadow: var(--sh-stage);
  color: #FFFFFF;
  flex: 0 0 auto;
}

.stage > .scene-stage,
.stage > .iso {
  position: absolute;
  inset: 0;
}

.stage.is-hub {
  height: 250px;
}

.scene-stage {
  line-height: 0;
}

.scene-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  touch-action: pan-y;
}

.iso {
  line-height: 0;
  pointer-events: none;
}

.iso svg {
  display: block;
}

.scene-labels,
.iso-labels {
  position: absolute;
  inset: 0;
  z-index: 1; /* over the canvas always: pinTo() re-appends the canvas after them on its way back from the strip */
  pointer-events: none;
  overflow: hidden;
}

.scene-chip {
  position: absolute;
  left: 0;
  top: 0;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--ink);
  font-family: var(--font);
  font-size: 13px;
  line-height: 1;
  font-weight: 800;
  white-space: nowrap;
  box-shadow: var(--sh-chip);
  font-variant-numeric: tabular-nums;
  will-change: transform;
}

.scene-chip svg {
  flex: 0 0 auto;
  color: var(--good-ink);
}

.scene-chip[data-kind="cold"] {
  color: var(--ink-2);
}

.scene-chip[data-kind="red"] {
  color: var(--ground);
}

.iso-labels .scene-chip {
  transform: translate(-50%, -50%);
}

/* chips pinned to a corner of a stage, not to a 3D point */
.stage-chip {
  position: absolute;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--ink);
  font-size: 12px;
  font-weight: 800;
  white-space: nowrap;
  box-shadow: var(--sh-chip);
  pointer-events: none;
}

/* the model chip, top-left of a 3D stage: never under the view switch (a
   narrow phone ellipsises it rather than overlap) */
.stage-chip.is-model {
  display: block;
  max-width: calc(100% - var(--beside, 184px)); /* room left for the view switch */
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 26px;
}

.stage-hint {
  position: absolute;
  z-index: 2;
  left: 14px;
  top: 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 800;
  color: #FFFFFF;
  pointer-events: none;
}

/* the 3D set (Pick radiators): how to spin one alone, and how many more
   there are than the six it shows */
.stage-hint.is-set {
  top: auto;
  left: 12px;
  bottom: 10px;
  font-size: 12px;
  opacity: 0.92;
}

.stage-chip.is-more {
  right: 12px;
  bottom: 10px;
}

/* the Room view (Pick radiators, Show mode): zoomed in, the light walls and
   floor fill the stage, so the white words over it sit on a graphite wash */
.stage.is-room .stage-switch {
  background: rgba(36, 10, 14, 0.42);
}

.stage.is-room .stage-hint.is-set {
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(36, 10, 14, 0.42);
  opacity: 1;
}

/* Show mode's Home: the whole house (step 4 of the 3D upgrade, 8 Oct 2026).
   The same graphite wash under the white words as the Room view; the house's
   totals in the corner chip; "Look inside …" bottom left once a room is picked */
.stage.is-home .stage-switch {
  background: rgba(36, 10, 14, 0.42);
}

.stage.is-home .stage-hint.is-set {
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(36, 10, 14, 0.42);
  opacity: 1;
}

.stage-chip.is-total .q-icon {
  margin-right: 4px;
  vertical-align: -2px;
  color: var(--good-ink);
}

.stage-open {
  position: absolute;
  z-index: 3;
  left: 10px;
  bottom: 10px;
  max-width: calc(100% - 20px);
}

.stage-open .key {
  max-width: 100%;
  box-shadow: var(--sh-chip);
}

.stage-corner {
  position: absolute;
  z-index: 3;
  right: 10px;
  bottom: 10px;
}

/* ---- "See it on your wall" (static/ar.js): a white key on the stage ---- */
.ar-key {
  position: relative;
  display: inline-flex;
}

.ar-key[hidden] {
  display: none;
}

.ar-key .key {
  box-shadow: var(--sh-chip);
}

/* model-viewer lives here, off screen, until the tap hands it to AR */
.ar-holder {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.ar-viewer {
  display: block;
  width: 1px;
  height: 1px;
}

/* the finish on the AR key: its swatch and name, under the label */
.ar-key-text {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  line-height: 1.1;
  text-align: left;
}

.ar-key-finish {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-2);
}

.ar-key-finish i {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.3);
}

/* the key under the stage (owner, 29 Sep: never over the radiator): full
   width, a flex item of the screen body, gone entirely where AR is impossible */
.ar-key.is-row {
  display: flex;
  width: 100%;
}

.ar-key.is-row[hidden] {
  display: none; /* no AR here: no key, and no gap in the screen body */
}

/* a room with several radiators: "All N together" or "One at a time" above
   the key (owner, 30 Sep 2026), on the red like the stage's own switch */
.ar-key.is-row.has-set {
  flex-direction: column;
  gap: 8px;
}

.ar-set-switch {
  display: flex;
  gap: 4px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.18);
}

.ar-set-switch > button {
  flex: 1 1 0;
  min-width: 0;
  height: 36px;
  padding: 0 10px;
  border-radius: 999px;
  color: #FFFFFF;
  font-size: 14px;
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background var(--t-settle) var(--ease), transform var(--t-tap) var(--ease);
}

.ar-set-switch > button[aria-pressed="true"] {
  background: var(--down-face);
  box-shadow: var(--sh-down);
}

.ar-key.is-row > .key {
  width: 100%;
  height: 58px;
  justify-content: flex-start;
  gap: 12px;
  padding: 0 16px 0 18px;
  box-shadow: var(--sh-key-ground);
}

.ar-key.is-row > .key > span {
  flex: 1 1 auto;
  min-width: 0;
}

.ar-key.is-row .ar-key-text > span:first-child {
  font-size: 17px;
}

.ar-key.is-row .ar-key-finish {
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ---- Android AR (static/arxr.js): the keys in the camera, a WebXR DOM overlay.
   Plain DOM on the app's own key styles; the empty screen is the gesture
   layer (drag to move, twist to turn, tap to place). ---- */
.xr-canvas {
  position: fixed;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.xr-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  will-change: transform; /* one composited layer over the AR canvas */
  font-family: var(--font);
  color: var(--ink);
  background: transparent;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.xr-overlay[hidden] {
  display: none;
}

.xr-gesture {
  position: absolute;
  inset: 0;
  touch-action: none;
}

.xr-top,
.xr-rail,
.xr-bottom,
.xr-place-row {
  pointer-events: none;
}

.xr-top > *,
.xr-rail > *,
.xr-place-row > *,
.xr-dock {
  pointer-events: auto;
}

.xr-top {
  position: absolute;
  left: 12px;
  right: 12px;
  top: calc(12px + var(--safe-t));
  display: flex;
  align-items: center;
  gap: 8px;
}

.xr-seg {
  margin-left: auto;
  display: inline-flex;
  gap: 6px;
}

.xr-top .key {
  box-shadow: var(--sh-key-ground);
}

.xr-top .key[aria-pressed="true"] {
  box-shadow: var(--sh-down);
}

.key.xr-hide {
  width: 40px;
  padding: 0;
}

.xr-status {
  position: absolute;
  left: 50%;
  top: calc(66px + var(--safe-t));
  transform: translateX(-50%);
  width: min(calc(100% - 24px), 420px);
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 14px 10px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.94);
  box-shadow: var(--sh-chip);
  text-align: center;
  pointer-events: none;
}

.xr-status b {
  font-size: 16px;
  font-weight: 800;
  line-height: 1.2;
}

.xr-status span {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink-2);
}

.xr-coach {
  position: absolute;
  left: 50%;
  top: 44%;
  margin-left: -17px;
  color: #FFFFFF;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5));
  animation: xr-sweep 1.6s var(--ease) infinite alternate;
  pointer-events: none;
}

.xr-coach[hidden] {
  display: none;
}

@keyframes xr-sweep {
  from {
    transform: translateX(-46px) rotate(-10deg);
  }
  to {
    transform: translateX(46px) rotate(10deg);
  }
}

.xr-rail {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-58%);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.xr-rail[hidden],
.xr-dock[hidden],
.xr-place[hidden],
.xr-ahead[hidden],
.xr-models[hidden] {
  display: none;
}

.key.xr-round {
  width: 56px;
  height: 56px;
  min-width: 56px;
  padding: 0;
  gap: 1px;
  flex-direction: column;
  border-radius: 50%;
  box-shadow: var(--sh-key-ground);
}

.xr-round small {
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
}

.xr-bottom {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: calc(14px + var(--safe-b));
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.xr-place-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.key.xr-place {
  width: 100%;
  max-width: 420px;
  height: 60px;
  font-size: 19px;
}

.key.xr-ahead {
  height: auto;
  min-height: 40px;
  padding: 8px 16px;
  white-space: normal;
  font-size: 14px;
  box-shadow: var(--sh-key-ground);
}

.xr-dock {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px;
  border-radius: 22px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: var(--sh-dock);
}

.xr-swatches {
  display: flex;
  justify-content: space-between;
  gap: 6px;
}

.xr-swatch {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  border-radius: 50%;
  background: var(--sw);
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.28), 0 2px 0 rgba(90, 10, 15, 0.18);
  transition: box-shadow var(--t-settle) var(--ease), transform var(--t-tap) var(--ease);
}

.xr-swatch[aria-checked="true"] {
  box-shadow: 0 0 0 3px #FFFFFF, 0 0 0 6px var(--ground);
  transform: scale(0.94);
}

.xr-models {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 2px 0 4px;
}

.xr-models::-webkit-scrollbar {
  display: none;
}

.key.xr-model {
  flex: 0 0 auto;
  flex-direction: column;
  gap: 1px;
  height: 46px;
  line-height: 1;
}

.xr-model small {
  font-size: 11px;
  font-weight: 700;
  opacity: 0.72;
}

/* the room's set (owner, 30 Sep 2026): the tray of the room's radiators,
   Next, Line up, and the live gap between neighbours on one wall */
.xr-tray {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  padding: 2px 2px 4px;
  pointer-events: auto;
}

.xr-tray::-webkit-scrollbar {
  display: none;
}

.xr-tray[hidden],
.xr-next[hidden],
.xr-lineup[hidden],
.xr-gap[hidden] {
  display: none;
}

.xr-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 14px 0 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: var(--sh-chip);
  color: var(--ink);
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
}

.xr-chip i {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px var(--ink-3);
}

.xr-chip[data-placed="true"] i {
  background: var(--good, #1e9e5a);
  box-shadow: none;
}

.xr-chip[aria-pressed="true"] {
  background: var(--down-face);
  color: #FFFFFF;
  box-shadow: var(--sh-down);
}

.xr-chip[aria-pressed="true"] i {
  box-shadow: inset 0 0 0 2px #FFFFFF;
}

.xr-chip[aria-pressed="true"][data-placed="true"] i {
  box-shadow: inset 0 0 0 2px #FFFFFF;
}

.xr-chip.is-more {
  background: rgba(22, 23, 26, 0.55);
  color: #FFFFFF;
  box-shadow: none;
}

.key.xr-lineup {
  flex: 0 0 auto;
  height: 40px;
  box-shadow: var(--sh-key-ground);
}

.xr-gaps {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.xr-gap {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
}

.xr-gap > span {
  display: inline-block;
  transform: translate(-50%, -50%);
  padding: 5px 10px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--ink);
  font-size: 14px;
  font-weight: 800;
  white-space: nowrap;
  box-shadow: 0 0 0 2px var(--ground), var(--sh-chip);
}

.xr-gap.is-level > span::after {
  content: " · level";
  font-weight: 700;
  color: var(--ink-3);
}

/* ---- AR, cheap and flat (round 6, 30 Sep 2026: the owner's tablet still
   died leaving AR). In AR the phone's XR compositor draws this overlay over
   the camera; blurred shadows, filters, layer promotion and running
   animations there are a known crash risk on some mobile GPUs (Mali, Adreno).
   So inside the overlay: no shadows, filters, transitions or animations —
   flat fills and plain borders — and the app page underneath is not painted
   at all while AR runs. ---- */
html.xr-on body > #app {
  visibility: hidden !important;
}

.xr-overlay,
.xr-overlay * {
  box-shadow: none !important;
  text-shadow: none !important;
  filter: none !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  transition: none !important;
  animation: none !important;
  will-change: auto !important;
}

.xr-overlay .key {
  background: #FFFFFF;
  border: 1.5px solid rgba(22, 23, 26, 0.3);
  color: var(--ink);
}

.xr-overlay .key.is-red,
.xr-overlay .key[aria-pressed="true"],
.xr-overlay .key.is-down {
  background: #E5252B;
  border-color: #A8141A;
  color: #FFFFFF;
}

.xr-overlay .key.is-red .q-icon,
.xr-overlay .key[aria-pressed="true"] .q-icon {
  color: #FFFFFF;
}

.xr-overlay .key:disabled {
  background: #F1ECEB;
  color: #8B8E95;
}

.xr-overlay .key:active:not(:disabled) {
  transform: none;
}

.xr-overlay .xr-status,
.xr-overlay .xr-dock {
  background: #FFFFFF;
  border: 1.5px solid rgba(22, 23, 26, 0.18);
}

.xr-overlay .xr-chip {
  background: #FFFFFF;
  border: 1.5px solid rgba(22, 23, 26, 0.25);
}

.xr-overlay .xr-chip[aria-pressed="true"] {
  background: #E5252B;
  border-color: #A8141A;
}

.xr-overlay .xr-swatch {
  border: 2px solid rgba(22, 23, 26, 0.35);
}

.xr-overlay .xr-swatch[aria-checked="true"] {
  border: 4px solid #E5252B;
  transform: none;
}

.xr-overlay .xr-gap > span {
  border: 2px solid #E5252B;
}

.xr-overlay .xr-coach {
  transform: none;
}

/* ---- the colour panel over the camera (round 6): at most 38% of the screen,
   foldable to one line; the radiator on the wall stays in view ---- */
.xr-swatch.xr-more {
  background: conic-gradient(#e53935, #fdd835, #43a047, #00acc1, #1e88e5, #8e24aa, #e53935);
}

.xr-panel {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: calc(8px + var(--safe-b));
  z-index: 3;
  display: flex;
  flex-direction: column;
  max-height: 38vh;
  max-width: 560px;
  margin: 0 auto;
  border-radius: 18px;
  background: #FFFFFF;
  border: 1.5px solid rgba(22, 23, 26, 0.2);
  color: var(--ink);
  overflow: hidden;
  pointer-events: auto;
}

.xr-panel[hidden],
.xr-pane-wheel[hidden],
.xr-pane-list[hidden],
.xr-wheel-dot[hidden],
.xr-panel .xr-use[hidden] {
  display: none;
}

.xr-overlay.panel-open .xr-bottom,
.xr-overlay.panel-open .xr-rail,
.xr-overlay.keys-hidden .xr-panel {
  display: none;
}

.xr-panel-grab {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 18px;
  width: 100%;
}

.xr-panel-grab span {
  width: 40px;
  height: 5px;
  border-radius: 3px;
  background: #C9C1BF;
}

.xr-panel-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px 8px;
}

.xr-panel-raw {
  flex: 0 0 10px;
  height: 36px;
  border-radius: 4px;
  border: 1px solid rgba(22, 23, 26, 0.2);
}

.xr-panel-sw {
  flex: 0 0 36px;
  height: 36px;
  border-radius: 9px;
  border: 1px solid rgba(22, 23, 26, 0.25);
}

.xr-panel-name {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.xr-panel-name b {
  font-size: 15px;
  font-weight: 800;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.xr-panel-name span {
  font-size: 12px;
  font-weight: 700;
  color: #5B5E66;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.xr-panel-controls {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px 8px;
}

.xr-panel .key.xr-use {
  flex: 1 1 auto;
  min-width: 0;
  white-space: normal;
  height: 38px;
  min-height: 38px;
  line-height: 1.1;
  font-size: 13px;
  padding: 2px 10px;
}

.xr-panel .key.xr-panel-close {
  flex: 0 0 40px;
  width: 40px;
  padding: 0;
}

.xr-panel-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 10px 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.xr-panel.is-folded .xr-panel-body {
  display: none;
}

.xr-panel-tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 4px;
}

.xr-panel-tabs button {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  height: 38px;
  border-radius: 999px;
  border: 1.5px solid rgba(22, 23, 26, 0.25);
  background: #FFFFFF;
  font-size: 13px;
  font-weight: 800;
  color: var(--ink);
}

.xr-panel-tabs button[aria-pressed="true"] {
  background: #16171A;
  border-color: #16171A;
  color: #FFFFFF;
}

.xr-pane-wheel {
  display: flex;
  align-items: center;
  gap: 14px;
}

.xr-wheel {
  position: relative;
  flex: 0 0 140px;
  width: 140px;
  height: 140px;
  touch-action: none;
}

.xr-wheel canvas {
  display: block;
  width: 140px;
  height: 140px;
  border-radius: 50%;
  touch-action: none;
}

.xr-wheel-dot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px;
  border-radius: 50%;
  border: 3px solid #FFFFFF;
  outline: 2px solid rgba(22, 23, 26, 0.65);
  pointer-events: none;
}

.xr-wheel-side {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.xr-light-box {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
  font-weight: 800;
  color: #5B5E66;
}

.xr-light {
  width: 100%;
  height: 30px;
  accent-color: #E5252B;
}

.xr-panel-favs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.xr-panel-favs button {
  height: 34px;
  border-radius: 9px;
  border: 2px solid rgba(22, 23, 26, 0.25);
}

.xr-panel-favs button[aria-checked="true"] {
  border: 4px solid #E5252B;
}

.xr-pane-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.xr-ral-search {
  height: 40px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1.5px solid rgba(22, 23, 26, 0.3);
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
  background: #FFFFFF;
}

.xr-ral-results {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
}

.xr-ral-results:empty {
  display: none;
}

.xr-ral-results button {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 10px 0 4px;
  border-radius: 999px;
  border: 1.5px solid rgba(22, 23, 26, 0.25);
  background: #FFFFFF;
  font-size: 13px;
  font-weight: 800;
  color: var(--ink);
}

.xr-ral-results button i {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(22, 23, 26, 0.2);
}

/* nine family strips in two columns: slide along one to run through it */
.xr-strips {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px 8px;
}

.xr-strips[hidden] {
  display: none;
}

.xr-strip {
  display: flex;
  height: 20px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid rgba(22, 23, 26, 0.15);
  touch-action: none;
}

.xr-strip i {
  flex: 1 1 0;
}

.xr-panel-note {
  margin: 0;
  font-size: 11px;
  line-height: 14px;
  font-weight: 600;
  color: #5B5E66;
}

.xr-overlay.keys-hidden .xr-seg,
.xr-overlay.keys-hidden .xr-exit,
.xr-overlay.keys-hidden .xr-status,
.xr-overlay.keys-hidden .xr-rail,
.xr-overlay.keys-hidden .xr-dock,
.xr-overlay.keys-hidden .xr-tray,
.xr-overlay.keys-hidden .xr-place-row {
  visibility: hidden;
}

/* the finish picker under "Colour or smooth finish" (static/config.js COLOURS) */
.finish-pick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  width: 100%;
}

.finish-swatch {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  min-height: 72px;
  padding: 9px 10px 8px;
  border-radius: 14px;
  background: var(--key-face, #ffffff);
  box-shadow: var(--raise-sm, 0 2px 0 #ece6e5), inset 0 0 0 1px var(--rule);
  color: var(--ink);
  font-size: 13px;
  font-weight: 800;
  line-height: 1.15;
  text-align: left;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.finish-swatch i {
  width: 26px;
  height: 18px;
  border-radius: 6px;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.22);
}

.finish-swatch small {
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-3);
}

.finish-swatch.is-on {
  background: var(--down-face);
  color: #ffffff;
  box-shadow: var(--sh-down);
  transform: translateY(2px);
}

.finish-swatch.is-on small {
  color: #ffffff;
}

/* the finish row's way into the whole fan deck, and the owner's disclaimer */
.finish-more {
  width: 100%;
}

.finish-note {
  font-size: 12px;
  line-height: 16px;
  font-weight: 600;
  color: var(--ink-3);
}

/* ---- "All RAL colours" (static/ralpicker.js): the RAL Classic fan deck by
   family, search, and Match a colour (wheel or camera eyedropper) ---- */
.ral-sheet .sheet-body {
  padding-top: 4px;
}

.ral-head {
  align-items: center;
}

.ral-head-text {
  flex: 1 1 auto;
  min-width: 0;
}

.ral-tabs {
  flex: 0 0 auto;
  padding: 0 16px 10px;
}

/* the picker's two switches: quieter and lower than a full key */
.ral-tabs .seg .key,
.ral-match > .seg .key {
  height: 40px;
  min-height: 40px;
  font-size: 15px;
}

.ral-deck,
.ral-match {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.ral-search {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 48px;
  padding: 0 14px;
  border-radius: 14px;
  background: var(--well);
  /* stuck to the top while the deck scrolls: white above and below it, so
     no card peeks round it */
  box-shadow: inset 0 0 0 1px var(--rule), 0 -10px 0 6px #FFFFFF, 0 8px 10px #FFFFFF;
  color: var(--ink-3);
}

.ral-search input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
  outline: none;
}

.ral-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  scroll-margin-top: 60px;
}

.ral-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 15px;
  color: var(--ink);
}

.ral-section-head b {
  font-weight: 800;
}

.ral-section-head span {
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-3);
}

/* the family's colours in a strip, like the fan deck's edge */
.ral-spine {
  display: flex;
  height: 10px;
  border-radius: 5px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.12);
}

.ral-spine i {
  flex: 1 1 0;
}

.ral-jump {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}

.ral-jump::-webkit-scrollbar {
  display: none;
}

.ral-jump button {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px 0 8px;
  border-radius: 999px;
  background: var(--well);
  box-shadow: inset 0 0 0 1px var(--rule);
  font-size: 13px;
  font-weight: 800;
  color: var(--ink);
}

.ral-jump i {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.2);
}

.ral-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 8px;
}

.ral-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 6px 6px 8px;
  border-radius: 14px;
  background: #FFFFFF;
  box-shadow: inset 0 0 0 1px var(--rule);
  text-align: left;
  color: var(--ink);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.ral-card i {
  position: relative;
  display: block;
  width: 100%;
  height: 54px;
  margin-bottom: 4px;
  border-radius: 9px;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.16);
}

.ral-card b {
  font-size: 14px;
  font-weight: 800;
  line-height: 1.1;
}

.ral-card span {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink-3);
}

.ral-card[aria-pressed="true"] {
  box-shadow: 0 0 0 3px var(--ground), inset 0 0 0 1px var(--rule);
  transform: translateY(1px);
}

.ral-card.is-fav b::after {
  content: " ★";
  color: var(--ground);
  font-size: 12px;
}

.ral-badge {
  position: absolute;
  left: 5px;
  bottom: 5px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  font-size: 10px;
  font-style: normal;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.ral-badge.is-luminous {
  background: #16171A;
  color: #FFFFFF;
}

.ral-foot {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ral-chosen {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  line-height: 1.25;
  color: var(--ink);
}

.ral-chosen i {
  flex: 0 0 30px;
  height: 30px;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.18);
}

.ral-chosen b {
  font-weight: 800;
}

.ral-chosen small {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
}

.ral-disclaimer {
  margin: 0;
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
  color: var(--ink-2);
}

.ral-hint {
  margin: 0;
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
}

.ral-wheel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.ral-wheel-disc {
  position: relative;
  touch-action: none;
}

.ral-wheel-disc canvas {
  display: block;
  border-radius: 50%;
  touch-action: none;
  cursor: crosshair;
}

.ral-wheel-dot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  box-shadow: 0 0 0 3px #FFFFFF, 0 0 0 5px rgba(22, 23, 26, 0.55);
  pointer-events: none;
}

.ral-light {
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(100%, 320px);
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-2);
}

.ral-light input {
  flex: 1 1 auto;
  accent-color: var(--ground);
  height: 32px;
}

.ral-camera {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ral-camera-view {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 16px;
  overflow: hidden;
  background: #16171A;
}

.ral-camera-view video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  touch-action: none;
}

.ral-camera-cover {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
  text-align: center;
  color: #FFFFFF;
  font-size: 14px;
  font-weight: 700;
}

.ral-camera-mark {
  position: absolute;
  transform: translate(-50%, -50%);
  border-radius: 6px;
  box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px rgba(22, 23, 26, 0.6);
  pointer-events: none;
}

.ral-results {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ral-picked {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-2);
}

.ral-picked i {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.18);
}

.ral-result {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px;
  border-radius: 14px;
  background: #FFFFFF;
  box-shadow: inset 0 0 0 1px var(--rule);
  text-align: left;
  color: var(--ink);
}

.ral-result > i {
  flex: 0 0 56px;
  height: 56px;
  border-radius: 10px;
  box-shadow: inset 0 0 0 1px rgba(22, 23, 26, 0.16);
}

.ral-result-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.ral-result-text b {
  font-size: 15px;
  font-weight: 800;
}

.ral-result-text small {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
}

.ral-result[aria-pressed="true"] {
  box-shadow: 0 0 0 3px var(--ground), inset 0 0 0 1px var(--rule);
}

.ral-close {
  font-size: 13px;
  font-weight: 800;
  color: var(--ink-3);
}

.ral-close.is-very-close {
  color: var(--good-ink);
}

.ral-close.is-close {
  color: var(--ink-2);
}

.ral-close.is-approximate {
  color: #B4501A;
}

/* Show mode: which of the quote's Neos models the stage turns */
.show-models {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.stage-switch {
  position: absolute;
  z-index: 3;
  right: 10px;
  top: 10px;
  display: flex;
  gap: 4px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.18);
}

.stage-switch > button {
  height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 800;
  transition: background var(--t-settle) var(--ease), transform var(--t-tap) var(--ease);
}

.stage-switch > button[aria-pressed="true"] {
  background: var(--down-face);
  box-shadow: var(--sh-down);
}

.stage-figure {
  position: absolute;
  z-index: 2;
  left: 16px;
  bottom: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: #FFFFFF;
  pointer-events: none;
}

.stage-figure .label {
  color: #FFFFFF;
}

.stage-figure-note {
  font-size: 13px;
  line-height: 17px;
  font-weight: 800;
  color: #FFFFFF;
}

/* ---- the House survey's heat-loss house (step 3 of the 3D upgrade, 7 Oct
   2026): the House | Heat view switch, the thermal ground, the key ---- */
.stage.is-house::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--thermal-bg);
  opacity: 0;
  transition: opacity 400ms var(--ease);
  pointer-events: none;
}

.stage.is-house.is-heat::before {
  opacity: 1;
}

/* where the house faces, top left: never under the switch (a narrow phone
   ellipsises it rather than overlap) */
.stage-chip.is-aspect {
  left: 14px;
  top: 14px;
  display: block;
  max-width: calc(100% - 200px);
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 26px;
}

/* the key sits over the factor figure, in the stage's clear left column */
.heat-legend {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 12px;
  color: #FFFFFF;
}

.heat-legend-words {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  font-size: 12px;
  line-height: 15px;
  font-weight: 800;
}

.heat-legend-less {
  opacity: 0.78;
}

.heat-legend-bar {
  flex: 0 0 auto;
  width: 8px;
  height: 52px;
  border-radius: 99px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.28);
}

/* a phone's shorter stage: a shorter key, so it clears the chip over it */
@media (max-width: 599px) {
  .heat-legend {
    margin-bottom: 6px;
  }

  .heat-legend-bar {
    height: 38px;
  }
}

/* the compass round the house's foot: bare letters on the ground, not chips */
.scene-chip[data-kind="compass"] {
  height: 16px;
  padding: 0;
  background: none;
  box-shadow: none;
  color: rgba(255, 255, 255, 0.92);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-shadow: 0 1px 3px rgba(40, 0, 5, 0.55);
}

/* scrolled past, the strip shows the same house; in Heat view on its dark ground */
.strip.is-heat .strip-scene {
  background: var(--thermal-bg);
}

/* ---- the collapsing stage header (BRIEF §6.9): the scene stays in view as a
   strip under the header and never covers a control — it replaces the pip ----
   A plain-red backdrop (.strip-backdrop, next sibling in the DOM) sits behind
   the tile at the same size, in the header's flat red: it joins the header
   seamlessly and shows through the tile's rounded corners instead of the
   page content scrolling underneath (owner, 7 Oct 2026). */
.strip {
  position: fixed;
  left: 0;
  right: 0;
  top: var(--hdr-now);
  z-index: 25;
  width: calc(min(100vw, var(--frame-w)) - 2 * var(--gutter));
  margin: 0 auto;
  height: 150px;
  display: flex;
  align-items: stretch;
  border-radius: 18px;
  background: var(--stage-bg);
  box-shadow: var(--sh-stage), 0 12px 22px -10px rgba(90, 5, 10, 0.55);
  color: #FFFFFF;
  overflow: hidden;
  transform: translateY(-12px);
  opacity: 0;
  pointer-events: none;
  transition: transform var(--t-move) var(--ease), opacity var(--t-move) var(--ease);
}

.strip.is-on {
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

.strip.is-short {
  height: 140px;
}

.strip-backdrop {
  position: fixed;
  left: 0;
  right: 0;
  top: var(--hdr-now);
  z-index: 24;
  max-width: var(--frame-w);
  margin: 0 auto;
  height: 150px;
  background: var(--ground);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-move) var(--ease);
}

.strip.is-on ~ .strip-backdrop {
  opacity: 1;
}

.strip.is-short ~ .strip-backdrop {
  height: 140px;
}

/* a short window (a landscape tablet with its keyboard up, when the browser
   resizes the page for it): a slimmer strip, so the size field being typed
   still fits between it and the keyboard (Add room, 7 Oct 2026) */
@media (max-height: 520px) {
  .strip,
  .strip ~ .strip-backdrop {
    height: 112px;
  }

  .strip.is-short,
  .strip.is-short ~ .strip-backdrop {
    height: 100px;
  }

  .strip-info {
    gap: 4px;
    padding-top: 8px;
    padding-bottom: 8px;
  }

  .strip-info .num {
    font-size: 28px;
    line-height: 30px;
  }

  .strip-line {
    font-size: 13px;
    line-height: 17px;
  }
}

.strip-scene {
  position: relative;
  flex: 0 0 200px;
  width: 200px;
  line-height: 0;
}

.strip-scene > .iso {
  position: absolute;
  inset: 0;
}

.strip-info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  padding: 16px 16px 16px 6px;
}

.strip-line {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: 15px;
  line-height: 20px;
  font-weight: 800;
  color: #FFFFFF;
}

.strip-keys {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 800;
}

.strip-keys .key {
  height: 42px;
  min-width: 42px;
  width: 42px;
  padding: 0;
  border-radius: 999px;
  font-size: 17px;
}

.strip-meter {
  position: relative;
  height: 10px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.28);
}

.strip-meter-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 99px;
  background: #FFFFFF;
  transition: width var(--t-count) var(--ease);
}

.strip-meter-mark {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  background: #FFFFFF;
}

/* a phone's strip leaves ~160 px beside its 200 px scene: the House survey's
   figure, words and Set keys (44 px touch targets) need more, so its scene
   is 150 px there and the figure a size down (they wrapped and were clipped) */
@media (max-width: 479px) {
  .strip-info {
    gap: 8px;
    padding: 12px 12px 12px 4px;
  }

  .strip-info .num.is-m {
    font-size: 32px;
    line-height: 34px;
  }

  .strip-line {
    font-size: 14px;
    line-height: 18px;
  }

  .strip-keys {
    gap: 6px;
  }

  .strip.is-house:not(.is-band) .strip-scene,
  .strip.is-house:not(.is-band) .strip-expand {
    flex-basis: 150px;
    width: 150px;
  }
}

/* ---- the sticky 3D tile (owner, 8 Oct 2026; sizes in static/striplayout.js) ----
   A tablet held upright (.is-band): the 3D fills the strip edge to edge, the
   figure in a SOLID white corner chip (translucent white on the red reads
   pink — rejected), the height inline from striplayout.js (224 px on the
   owner's tablet, 136 while a field is typed in). Phones keep the strip
   above. A tap anywhere on the band (on a phone, on the strip's 3D) opens
   the 3D full screen (.stage-expand). */
.strip.is-band {
  display: block;
}

.strip.is-band .strip-scene {
  position: absolute;
  inset: 0;
  width: auto;
  flex: none;
}

.strip-chip {
  position: absolute;
  z-index: 2;
  left: 12px;
  bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  max-width: min(calc(100% - 84px), 280px);
  padding: 9px 14px 10px;
  border-radius: 16px;
  background: #FFFFFF;
  color: var(--ink);
  box-shadow: var(--sh-chip);
  pointer-events: none;
}

.strip-chip-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  font-size: 13px;
  line-height: 17px;
  font-weight: 800;
  color: var(--ink-2);
  white-space: nowrap;
}

.strip-chip-line.is-sub {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}

.strip-chip .num {
  font-size: 28px;
  line-height: 30px;
}

.strip-chip-kw {
  font-size: 15px;
  color: var(--ink);
}

.strip-chip-meter {
  width: 172px;
  max-width: 100%;
}

/* typing: the band slims to about the 7 Oct strip, the chip with it */
.strip.is-band.is-typing .strip-chip {
  left: 8px;
  bottom: 8px;
  gap: 3px;
  padding: 6px 12px 7px;
}

.strip.is-band.is-typing .strip-chip .num {
  font-size: 22px;
  line-height: 24px;
}

/* the whole band (a phone: the strip's 3D) is the expand key; the white
   badge says so. The slim strip's figure column keeps its own keys (Set). */
.strip-expand {
  position: absolute;
  z-index: 3;
  left: 0;
  top: 0;
  bottom: 0;
  width: 200px;
  border-radius: 18px 0 0 18px;
  cursor: zoom-in;
}

.strip.is-band .strip-expand {
  right: 0;
  width: auto;
  border-radius: 18px;
}

.strip-expand:focus-visible {
  outline: 3px solid #FFFFFF;
  outline-offset: -5px;
}

.strip-expand-badge {
  position: absolute;
  left: 8px;
  top: 8px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--ground);
  box-shadow: var(--sh-key-ground);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.strip.is-band .strip-expand-badge {
  left: auto;
  right: 12px;
  top: 12px;
  width: 44px;
  height: 44px;
}

.strip.is-band.is-typing .strip-expand-badge {
  right: 8px;
  top: 8px;
  width: 36px;
  height: 36px;
}

.strip-expand:active .strip-expand-badge,
.stage-expand-key:active {
  transform: translateY(2px);
  box-shadow: var(--sh-key-pressed);
}

/* the expand key on a wide screen's left-pane stage: top right, the view
   switch moves over for it */
.stage-expand-key {
  position: absolute;
  z-index: 4;
  right: 10px;
  top: 10px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--key-face);
  color: var(--ground);
  box-shadow: var(--sh-key-ground);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.stage.has-expand-key .stage-switch {
  right: 62px;
}

.stage.has-expand-key .stage-chip.is-aspect {
  max-width: calc(100% - 262px);
}

.stage.has-expand-key .stage-chip.is-model {
  max-width: calc(100% - var(--beside, 184px) - 52px);
}

/* the 3D full screen: the SAME live canvas (pinTo), on a layer over the
   dock and the Quote Bar; the page under it does not scroll */
html.is-stage-expanded {
  overflow: hidden;
}

.stage-expand {
  position: fixed;
  inset: 0;
  z-index: 58;
  background: var(--stage-bg);
  touch-action: none;
  overscroll-behavior: contain;
  -webkit-user-select: none;
  user-select: none;
  animation: stage-expand-in var(--t-move) var(--ease-enter) both;
}

.stage-expand.is-heat {
  background: var(--thermal-bg);
}

.stage-expand.is-leaving {
  animation: stage-expand-out 180ms var(--ease) both;
  pointer-events: none;
}

@keyframes stage-expand-in {
  from {
    opacity: 0;
    transform: scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes stage-expand-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
    transform: scale(0.98);
  }
}

.stage-expand-scene {
  position: absolute;
  inset: 0;
  line-height: 0;
}

/* no live 3D (no WebGL, a 2 GB device, Show open): the flat drawing, kept
   clear of the top bar and the bottom chip (it fills whatever box it gets) */
.stage-expand-flat {
  position: absolute;
  left: 16px;
  right: 16px;
  top: calc(84px + var(--safe-t));
  bottom: calc(118px + var(--safe-b));
}

.stage-expand :focus-visible {
  outline-color: #FFFFFF;
}

.stage-expand-top {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  top: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: calc(18px + var(--safe-t)) 16px 14px;
}

.stage-expand-grab {
  position: absolute;
  left: 50%;
  top: calc(7px + var(--safe-t));
  width: 44px;
  height: 5px;
  margin-left: -22px;
  border-radius: 99px;
  background: #FFFFFF;
  box-shadow: 0 1px 3px rgba(60, 0, 5, 0.35);
}

.stage-expand-title {
  display: block;
  min-width: 0;
  height: 40px;
  padding: 0 16px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--ink);
  font-size: 16px;
  line-height: 40px;
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: var(--sh-chip);
}

.stage-expand-close {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-left: auto;
  border-radius: 999px;
  background: var(--key-face);
  color: var(--ink);
  box-shadow: var(--sh-key-ground);
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.stage-expand-close:active {
  transform: translateY(2px);
  box-shadow: var(--sh-key-pressed);
}

.stage-expand-foot {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 16px calc(16px + var(--safe-b));
  pointer-events: none;
}

.strip-chip.is-expand {
  position: static;
  max-width: min(62%, 360px);
}

.stage-expand-hint {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
  box-shadow: var(--sh-chip);
}

/* a phone: the hint under the chip would crowd it */
@media (max-width: 479px) {
  .stage-expand-hint {
    display: none;
  }
}

/* ---- sheet (BRIEF §6.9): white, radius 28 top, grabber, snap points ---- */
.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(22, 23, 26, 0.45);
  animation: fade-in var(--t-sheet) var(--ease) both;
}

.sheet-backdrop.is-leaving {
  animation: fade-out var(--t-move) var(--ease) both;
}

.sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 71;
  max-width: var(--frame-w);
  margin: 0 auto;
  max-height: calc(100vh - 24px - var(--safe-t));
  display: flex;
  flex-direction: column;
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  background: #FFFFFF;
  box-shadow: var(--sh-sheet);
  overflow: hidden;
  animation: sheet-in var(--t-sheet) var(--ease-sheet) both;
  touch-action: pan-y;
}

.sheet.is-leaving {
  animation: sheet-out var(--t-move) var(--ease) both;
}

.sheet.is-dragging {
  transition: none;
}

.sheet.is-settling {
  transition: transform var(--t-sheet) var(--ease-sheet), height var(--t-sheet) var(--ease-sheet);
}

.sheet.is-well {
  background: var(--well);
}

.sheet-grab {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
  padding: 8px 0 6px;
  cursor: grab;
  touch-action: none;
}

.sheet-grab span {
  width: 40px;
  height: 5px;
  border-radius: 99px;
  background: var(--track-off);
}

.sheet-head {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 2px 16px 10px;
}

.sheet-title {
  font-size: 24px;
  line-height: 30px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.sheet-sub {
  font-size: 15px;
  line-height: 20px;
  font-weight: 600;
  color: var(--ink-2);
}

.sheet-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* children never shrink: the body scrolls instead (the signature pad must keep its 176 px) */
.sheet-body > * {
  flex-shrink: 0;
}

.sign-sheet {
  -webkit-user-select: none;
  user-select: none;
}

.sheet-foot {
  flex: 0 0 auto;
  padding: 14px 16px calc(16px + var(--safe-b));
  border-top: 1px solid var(--rule);
  background: #FFFFFF;
  box-shadow: 0 -10px 24px rgba(22, 23, 26, 0.08);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ---- the ⋯ menu ---- */
.menu {
  display: flex;
  flex-direction: column;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 60px;
  padding: 8px 4px;
  font-size: 17px;
  font-weight: 700;
  color: var(--ink);
  text-align: left;
  border-radius: 14px;
}

.menu-item + .menu-item {
  border-top: 1px solid var(--rule);
  border-radius: 0;
}

.menu-item > .q-icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--ground);
}

.menu-item .grow {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.menu-item .row-sub {
  font-size: 13px;
}

button.menu-item:active {
  background: rgba(22, 23, 26, 0.05);
}

/* ---- modal confirm (reset, switch customer, save confirm) ---- */
.modal-scrim {
  position: fixed;
  inset: 0;
  z-index: 95;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px 16px calc(16px + var(--safe-b));
  background: rgba(22, 23, 26, 0.5);
  animation: fade-in var(--t-move) var(--ease) both;
}

.modal {
  width: 100%;
  max-width: calc(var(--frame-w) - 32px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
  border-radius: 28px;
  background: #FFFFFF;
  box-shadow: var(--sh-sheet);
  animation: modal-in var(--t-move) var(--ease) both;
}

.modal-title {
  font-size: 22px;
  line-height: 28px;
  font-weight: 800;
  letter-spacing: -0.015em;
}

.modal-text {
  font-size: 15px;
  line-height: 22px;
  font-weight: 600;
  color: var(--ink-2);
}

.modal-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

/* ---- photo tile (BRIEF §6.14): 80 px, optional ---- */
.photos {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.photo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 84px;
}

.photo-add {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80px;
  height: 80px;
  border-radius: 16px;
  background: var(--well);
  border: 2px dashed #D3C9C7;
  color: var(--ground);
  transition: transform var(--t-tap) var(--ease);
}

.photo-add:active {
  transform: translateY(2px);
}

.photo-add.is-busy {
  opacity: 0.6;
  animation: busy-dots 900ms ease-in-out infinite;
}

.photo-add .q-icon {
  width: 26px;
  height: 26px;
  animation: tile-breathe 6s ease-in-out infinite;
}

.photo-thumb {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 16px;
  overflow: hidden;
  background: var(--well-2);
  animation: photo-in var(--t-move) var(--ease) both;
}

.photo-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.photo-thumb .key-icon {
  position: absolute;
  right: 4px;
  top: 4px;
  width: 28px;
  height: 28px;
  flex-basis: 28px;
}

.photo-thumb .key-icon .q-icon {
  width: 16px;
  height: 16px;
}

.photo-cap {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-2);
}

.photo-opt {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
}

/* ---- empty, loading, error, signal (BRIEF §6.16) ---- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 28px 20px;
  text-align: center;
}

.empty > .q-icon {
  width: 44px;
  height: 44px;
  color: var(--ground);
}

.empty-title {
  font-size: 20px;
  line-height: 26px;
  font-weight: 800;
  color: var(--ink);
}

.empty-text {
  font-size: 15px;
  line-height: 21px;
  font-weight: 600;
  color: var(--ink-2);
}

.notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 16px;
  background: var(--advice-wash);
  color: var(--ink);
  font-size: 15px;
  line-height: 21px;
  font-weight: 700;
}

.notice .q-icon {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  color: var(--advice);
}

.notice.is-good {
  background: var(--good-wash);
}

.notice.is-good .q-icon {
  color: var(--good);
}

.skeleton-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.skeleton-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px 16px;
  border-radius: var(--r-tray);
  background: #FFFFFF;
  box-shadow: var(--sh-tray);
  animation: row-enter var(--t-move) var(--ease) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}

.skeleton-bar {
  height: 12px;
  border-radius: 999px;
  background: linear-gradient(90deg, #EFE9E8 0%, #F8F5F4 48%, #EFE9E8 100%);
  background-size: 220% 100%;
  animation: skeleton-shimmer 1.2s linear infinite;
}

.skeleton-bar.is-big {
  height: 40px;
  width: 50%;
  border-radius: 12px;
}

.skeleton-bar.is-key {
  height: 48px;
  border-radius: 999px;
}

.skeleton-slow {
  font-size: 15px;
  font-weight: 700;
  color: #FFFFFF;
  padding: 0 2px;
}

/* the dashed add key on the red */
.add-dashed {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 60px;
  border-radius: 22px;
  border: 2px dashed rgba(255, 255, 255, 0.85);
  color: #FFFFFF;
  font-size: 17px;
  font-weight: 800;
  transition: transform var(--t-tap) var(--ease), background var(--t-settle) var(--ease);
}

.add-dashed .q-icon {
  color: #FFFFFF;
  width: 20px;
  height: 20px;
}

.add-dashed:active {
  transform: translateY(2px);
  background: rgba(255, 255, 255, 0.08);
}

/* ---- tick box (the finance declaration, the not-proceeding attestation) ---- */
.tickbox {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 16px;
  background: #FFFFFF;
  box-shadow: var(--sh-key);
  cursor: pointer;
}

.tickbox input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.tickbox-face {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--well);
  box-shadow: inset 0 0 0 2px var(--ink-3), var(--sh-well);
  color: #FFFFFF;
  transition: background var(--t-settle) var(--ease), box-shadow var(--t-settle) var(--ease), transform var(--t-settle) var(--ease);
}

.tickbox-face svg {
  opacity: 0;
}

.tickbox input:checked + .tickbox-face {
  background: var(--down-face);
  box-shadow: var(--sh-down);
  transform: translateY(1px);
}

.tickbox input:checked + .tickbox-face svg {
  opacity: 1;
}

.tickbox input:checked + .tickbox-face svg path {
  animation: tick-draw 240ms var(--ease) both;
  stroke-dasharray: 24;
}

.tickbox input:focus-visible + .tickbox-face {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

.tickbox-text {
  font-size: 15px;
  line-height: 21px;
  font-weight: 800;
  color: var(--ink);
}

/* ============================================================ 5 · screens */

/* ---- sign in (owner, 3 Oct 2026): the Trust red ground, the lockup
   (config.js BRAND; Quoty, by Trust since 8 Oct 2026), six Trust reps who walk
   in and stop in a relaxed group (static/brand/reps.svg — its own keyframes,
   plays once, then still; since 8 Oct the fallback for the van) and the
   Layout-B form — on a white tray with the one red Sign in when day.js
   LOGIN_CARD is on, straight on the red (.no-card, below) when off. Phones and
   upright tablets stack; a tablet on its side splits, reps left, form right.
   .intro-stage is the plain red while the app checks who is signed in. */
.intro-stage {
  position: fixed;
  inset: 0;
  background: var(--ground);
}

.login {
  position: fixed;
  inset: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--ground);
  font-family: var(--font);
  display: flex;
  flex-direction: column;
}

.login :focus-visible {
  outline-color: var(--ink);
}

.login-top :focus-visible {
  outline-color: #FFFFFF;
}

/* the reps stand at the bottom; the lockup sits in the middle of whatever red
   wall is left above their heads, lit softly behind the group like a studio */
.login-top {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-top: calc(20px + var(--safe-t));
  background: radial-gradient(75% 52% at 50% 82%, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 72%);
}

.login-brand {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px 24px;
}

.login-lockup {
  display: block;
  width: auto;
  height: calc(var(--lockup-h) * 0.7);
}

.login-hero {
  position: relative;
  width: 100%;
}

/* exactly the drawing's frame (596 x 350), so the walkers enter from its
   edges, which are the screen's edges on a phone and an upright tablet */
.login-reps {
  position: relative;
  width: 100%;
  height: 0;
  padding-top: 58.725%;
  overflow: hidden;
  /* the still floor + horizon (reps-ground.svg, same frame as the reps) */
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

.login-reps-art,
.login-reps-art > svg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

/* the reps on their own compositor layer: while they walk, only they are
   redrawn, never the floor behind them (the office tablet is weak) */
.login-reps-art {
  will-change: transform;
}

/* the van intro (8 Oct 2026, static/vanintro.js): one canvas behind the whole
   sign-in, scrolling with it; the lockup and the form sit above. The van
   parks in the red between them, so the road runs on behind the form. The
   studio light moves from .login-top to the stage, under the van. */
.login-stage {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.login.has-van .login-stage {
  background: radial-gradient(70% 46% at 50% 44%, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0) 72%);
}

.login-stage .van-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

.login-top,
.login-side {
  position: relative;
  z-index: 1;
}

.login.has-van .login-top {
  background: none;
}

/* the white tray: a sheet from the bottom on a phone */
.login-side {
  flex: 0 0 auto;
  background: var(--tray);
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  box-shadow: 0 -8px 26px rgba(90, 0, 8, 0.16);
  padding: 24px 22px calc(20px + var(--safe-b));
}

.login-form {
  width: 100%;
  max-width: 520px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  animation: login-rise 420ms var(--ease-enter) both;
}

/* login-rise stays in the list, so it is matched by name and never restarts
   when the shake ends (8 Oct 2026: it did, and the form faded in again from
   nothing after every shake — translucent white fields on the red) */
.login-form.is-shake {
  animation: login-rise 420ms var(--ease-enter) both, card-shake 260ms var(--ease) both;
}

.login-greet {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 2px;
}

.login-title {
  margin: 0;
  font-size: 28px;
  line-height: 32px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}

.login-sub {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 8px;
  font-size: 15px;
  line-height: 21px;
  font-weight: 600;
  color: var(--ink-2);
  text-wrap: pretty;
}

.login-link {
  appearance: none;
  border: 0;
  margin: -12px -4px;
  padding: 12px 4px;
  background: none;
  font: inherit;
  font-weight: 800;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.login-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.login-field > label {
  font-size: 12px;
  line-height: 16px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.login-input {
  position: relative;
}

.login-input input {
  width: 100%;
  height: 56px;
  margin: 0;
  padding: 0 16px;
  border: 1.5px solid var(--well-2);
  border-radius: var(--r-well);
  background: var(--well);
  box-shadow: var(--sh-well);
  color: var(--ink);
  caret-color: var(--ground);
  font-family: var(--font);
  font-size: 17px;
  font-weight: 700;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--t-settle) var(--ease), box-shadow var(--t-settle) var(--ease), background var(--t-settle) var(--ease);
}

.login-input input::placeholder {
  color: var(--ink-3);
  font-weight: 600;
  opacity: 1;
}

.login-input input:focus {
  border-color: var(--ground);
  background: #FFFFFF;
  box-shadow: 0 0 0 3px rgba(229, 37, 43, 0.18);
}

/* an empty field on Sign in: ink, never red (red is never an error here) */
.login-input input[aria-invalid="true"] {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(22, 23, 26, 0.12);
}

.login-input.has-show input {
  padding-right: 106px;
}

/* Show / Hide: a small white key inside the field */
.login-show {
  position: absolute;
  right: 7px;
  top: 7px;
  height: 42px;
  min-width: 84px;
  padding: 0 12px 0 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 0;
  border-radius: 12px;
  background: var(--key-face);
  box-shadow: var(--sh-key);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 800;
  cursor: pointer;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.login-show .q-icon {
  color: var(--ground);
}

.login-show:active {
  transform: translateY(1px);
  box-shadow: var(--sh-key-pressed);
}

/* "Call the office" under the form, once the office number is set */
.login-call {
  align-self: center;
}

.login-missing {
  margin: -4px 0 0;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 700;
  color: var(--ink);
}

.login-help {
  margin: 0;
  text-align: center;
  font-size: 15px;
  line-height: 21px;
  font-weight: 600;
  color: var(--ink-2);
}

@keyframes login-rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* an upright tablet: the same stack, larger, the form on a floating tray */
@media (min-width: 600px) {
  .login-top {
    gap: 20px;
    padding-top: calc(36px + var(--safe-t));
  }

  .login-brand {
    padding: 0 40px;
  }

  .login-lockup {
    height: calc(var(--lockup-h) * 0.95);
  }

  .login-side {
    background: none;
    box-shadow: none;
    border-radius: 0;
    padding: 6px 32px calc(32px + var(--safe-b));
  }

  .login-form {
    max-width: 540px;
    gap: 16px;
    padding: 30px 32px 26px;
    border-radius: var(--r-sheet);
    background: var(--tray);
    box-shadow: var(--sh-tray);
  }

  .login-title {
    font-size: 34px;
    line-height: 38px;
  }

  .login-input input {
    height: 60px;
    font-size: 18px;
  }

  .login-show {
    top: 9px;
  }
}

/* a tablet on its side: the reps on the left, the form on the right */
@media (min-width: 900px) and (orientation: landscape) {
  .login {
    flex-direction: row;
    align-items: stretch;
  }

  .login-top {
    flex: 0 0 60%;
    padding: calc(40px + var(--safe-t)) 0 calc(26px + var(--safe-b));
    /* fades out before the panel's edge, so no seam shows beside the form */
    background: radial-gradient(52% 50% at 50% 84%, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0) 94%);
  }

  .login.has-van .login-stage {
    background: radial-gradient(36% 46% at 30% 64%, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0) 80%);
  }

  .login-brand {
    padding: 0 48px;
  }

  .login-side {
    flex: 1 1 40%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: calc(28px + var(--safe-t)) 36px calc(28px + var(--safe-b)) 0;
  }

  .login-form {
    max-width: 440px;
    padding: 28px 28px 24px;
  }

  .login-title {
    font-size: 30px;
    line-height: 34px;
  }
}

/* ---- the sign-in with no tray (owner, 8 Oct 2026: "the tile kinda takes
   away the look"; day.js LOGIN_CARD = false adds .no-card). The form sits
   straight on the red, over the van's road, so the lockup, the van and the
   form read as one red picture: white raised fields (the key's face and its
   shadow on the ground), SOLID white type (translucent white on the red reads
   pink), the white Sign in key with red letters, problems on a white chip,
   and a focus ring of graphite inside white that shows on the red. Every rule
   here is scoped to .no-card, so LOGIN_CARD = true is the tray exactly as it
   was. ---- */
.login.no-card .login-side,
.login.no-card .login-form {
  background: none;
  box-shadow: none;
  border-radius: 0;
}

.login.no-card .login-form {
  padding: 0;
}

/* a phone: no sheet from the bottom, the form ends the red picture */
@media (max-width: 599px) {
  .login.no-card .login-side {
    padding: 4px 22px calc(26px + var(--safe-b));
  }
}

/* stacked (a phone, an upright tablet): the reps' studio light fades out
   before the foot of their panel, so no line shows across the red above the
   form (the tray used to cover it) */
@media (max-width: 899px), (orientation: portrait) {
  .login.no-card:not(.has-van) .login-top {
    background: radial-gradient(75% 42% at 50% 70%, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 72%);
  }

  /* and the van's: drawn in a box that stops at the foot of the van's free
     red (--van-foot, set by day.js as it frames the van), fading out inside
     it, so none of it reaches the red under the form */
  .login.no-card.has-van .login-stage {
    background: radial-gradient(70% 55% at 50% 60%, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0) 72%) top / 100% var(--van-foot, 58%) no-repeat;
  }
}

/* a tablet on its side: the form's top lines up with the lockup's (on the
   owner's 1066 x 711 the road's centre line then runs clear below the form,
   not under its last line) */
@media (min-width: 900px) and (orientation: landscape) {
  .login.no-card .login-side {
    align-items: flex-start;
    padding-top: calc(104px + var(--safe-t));
  }
}

.login.no-card .login-title,
.login.no-card .login-sub,
.login.no-card .login-link,
.login.no-card .login-help,
.login.no-card .login-field > label {
  color: #FFFFFF;
}

.login.no-card .login-sub,
.login.no-card .login-help {
  font-weight: 700;
}

.login.no-card .login-field > label {
  font-size: 13px;
}

.login.no-card .login-link {
  border-radius: 8px;
}

/* the fields: white keys set into the red */
.login.no-card .login-input input {
  border-color: transparent;
  background: var(--key-face);
  box-shadow: var(--sh-key-ground);
  color: var(--ink);
}

.login.no-card .login-input input::placeholder {
  color: var(--ink-3);
}

.login.no-card .login-input input:focus {
  border-color: transparent;
  background: #FFFFFF;
  box-shadow: var(--sh-key-ground), 0 0 0 2px var(--graphite), 0 0 0 5px #FFFFFF;
}

/* an empty field on Sign in: a graphite ring, never red */
.login.no-card .login-input input[aria-invalid="true"] {
  border-color: transparent;
  box-shadow: var(--sh-key-ground), 0 0 0 3px var(--graphite);
}

.login.no-card .login-input input[aria-invalid="true"]:focus {
  box-shadow: var(--sh-key-ground), 0 0 0 3px var(--graphite), 0 0 0 6px #FFFFFF;
}

/* Show / Hide: a small well-grey key inside the white field */
.login.no-card .login-show {
  background: linear-gradient(180deg, #F7F3F2 0%, #ECE6E5 100%);
  box-shadow: inset 0 1px 0 #FFFFFF, inset 0 -2px 0 rgba(90, 20, 25, 0.14), 0 1px 2px rgba(90, 10, 15, 0.18);
  color: var(--ink);
}

.login.no-card .login-show .q-icon {
  color: var(--ground-deep);
}

.login.no-card .login-show:active {
  box-shadow: inset 0 1px 3px rgba(60, 10, 15, 0.18);
}

/* Sign in: the white key on the ground, its letters the deep red (6:1 on
   the key's face); busy, it stays a white key (pressed in, the dots red),
   never the grey of a key that is switched off */
.login.no-card .login-form .key.is-ground,
.login.no-card .login-form .key.is-ground .q-icon {
  color: var(--ground-deep);
}

.login.no-card .login-form .key.is-ground:disabled {
  background: var(--key-face);
  box-shadow: var(--sh-key-pressed);
  transform: translateY(2px);
  color: var(--ground-deep);
}

.login.no-card .login-call {
  box-shadow: var(--sh-key-ground);
}

/* focus on the red: white outside, graphite inside */
.login.no-card :focus-visible {
  outline: 3px solid #FFFFFF;
  outline-offset: 2px;
}

.login.no-card .key:focus-visible {
  box-shadow: var(--sh-key-ground), 0 0 0 2px var(--graphite);
}

/* "Not you?": the ring hugs the words, not the link's tall touch area (which
   would cut through the greeting above) */
.login.no-card .login-link {
  position: relative;
}

.login.no-card .login-link:focus-visible {
  outline: none;
}

.login.no-card .login-link:focus-visible::after {
  content: "";
  position: absolute;
  inset: 9px -3px;
  border-radius: 8px;
  box-shadow: inset 0 0 0 2px var(--graphite), 0 0 0 3px #FFFFFF;
  pointer-events: none;
}

/* inside a white field the ring is graphite */
.login.no-card .login-show:focus-visible {
  outline: 3px solid var(--graphite);
  outline-offset: 1px;
}

/* a problem (wrong password, no network; a field left empty): a white chip */
.login.no-card .notice,
.login.no-card .login-missing {
  background: #FFFFFF;
  box-shadow: var(--sh-key-ground);
  color: var(--ink);
}

.login.no-card .login-missing {
  align-self: flex-start;
  margin: -2px 0 0;
  padding: 7px 12px 7px 10px;
  border-radius: 12px;
}

.login.no-card .login-missing .q-icon {
  color: var(--advice);
}

/* ---- Today: the day sheet ---- */
.day-hero .hero-time {
  display: flex;
  align-items: flex-end;
  gap: 12px;
}

.hero-time-end {
  font-size: 17px;
  font-weight: 800;
  color: var(--ink-3);
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}

.hero-name {
  font-size: 24px;
  line-height: 30px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.hero-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  color: var(--ink-2);
}

.hero-meta .q-icon {
  color: var(--ground);
}

.progress-note {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--well);
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  color: var(--ink-2);
}

.progress-note .q-icon {
  flex: 0 0 auto;
  color: var(--ground);
}

.visit-row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 64px;
  padding: 8px 0;
  text-align: left;
}

.visit-row + .visit-row {
  border-top: 1px solid var(--rule);
}

.visit-row:active {
  background: rgba(22, 23, 26, 0.04);
}

/* v3 visit cards: the card opens the visit; today's carry Start, or the quote
   in progress "Continue · 3 rooms · £7,060.60" on a line of its own */
.visit-row:has(> .visit-open) {
  flex-wrap: wrap;
  row-gap: 4px;
}

.visit-row:has(> .visit-open):active {
  background: transparent;
}

.visit-open {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 48px;
  text-align: left;
  border-radius: 12px;
}

.visit-open:active {
  background: rgba(22, 23, 26, 0.04);
}

.visit-open > .q-icon {
  flex: 0 0 auto;
  color: var(--ink-3);
}

.visit-row > .key.is-full {
  flex: 1 1 100%;
  margin: 2px 0 4px;
}

/* the day's small keys stay 44 px under the finger: Start / Continue on a
   visit card, Visit details, the My quotes filters (8 Oct 2026; 40 px on
   phones and a tablet on its side — upright tablets already make them 46) */
.visit-row > .key.is-s,
.day-hero .key.is-s,
.quote-filters > .key.is-s {
  min-height: 44px;
}

.visit-time {
  flex: 0 0 58px;
  font-size: 20px;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.visit-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.visit-name {
  display: flex;
  flex-wrap: wrap; /* a long name puts its Rebook tag under it, never crushes it */
  align-items: center;
  gap: 2px 8px;
  font-size: 17px;
  line-height: 22px;
  font-weight: 800;
  color: var(--ink);
  overflow-wrap: anywhere; /* "Featherstonehaugh-" beside Start on a phone */
}

.visit-name > .tag,
.visit-row > .tag {
  flex: 0 0 auto;
}

/* "Quoted £14,853.00 · office follows up" on a visit card: on a phone it
   takes a second line rather than losing the outcome to an ellipsis */
.visit-main .tag {
  height: auto;
  min-height: 24px;
  padding-top: 3px;
  padding-bottom: 3px;
  line-height: 16px;
  white-space: normal;
  text-wrap: balance;
  border-radius: 12px;
}

.visit-row > .q-icon {
  flex: 0 0 auto;
  color: var(--ink-3);
}

/* ---- Visits: the week (owner, 8 Oct 2026, screens/day.js VisitsScreen) ----
   ‹ week › on the red, then the week bar: seven white day keys (the chosen one
   down and red), or on a tablet on its side seven columns of small cards.
   Solid colours only: greys for the past, graphite for closed, deep red for
   days the app has no data for — never white let through onto the red. */
.wk {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.wk-nav {
  display: flex;
  align-items: center;
  gap: 8px;
}

.wk-title {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  color: #FFFFFF;
}

.wk-name {
  font-size: 19px;
  line-height: 24px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.wk-span {
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
}

.wk-nav > .key.wk-this {
  min-height: 44px;
  border-radius: 999px;
}

/* the first / last week of the data: the arrow key goes flat deep red (the
   usual disabled well at 80 % read pink on the red) */
.wk-nav > .key-icon:disabled {
  background: var(--ground-deep);
  box-shadow: none;
  opacity: 1;
}

.wk-nav > .key-icon:disabled .q-icon {
  color: var(--ground);
}

.wk-bar {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
  touch-action: pan-y; /* a sideways swipe pages the week; up and down still scrolls */
}

.wk-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
  min-height: 96px;
  padding: 8px 3px;
  border-radius: 14px;
  background: var(--key-face);
  box-shadow: var(--sh-key);
  color: var(--ink);
  text-align: center;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease), background var(--t-settle) var(--ease);
}

.wk-day:active:not(:disabled):not(.is-head) {
  transform: translateY(2px);
  box-shadow: var(--sh-key-pressed);
}

.wk-dow {
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.wk-date {
  font-size: 21px;
  line-height: 24px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.wk-count {
  min-width: 24px;
  height: 24px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--ground);
  color: #FFFFFF;
  font-size: 13px;
  line-height: 24px;
  font-weight: 800;
  white-space: nowrap;
}

.wk-none {
  height: 24px;
  font-size: 15px;
  line-height: 24px;
  font-weight: 800;
  color: var(--ink-3);
}

/* "Closed": sentence case so it fits a phone's 47 px day key */
.wk-shut {
  max-width: 100%;
  height: 20px;
  padding: 0 3px;
  border-radius: 6px;
  background: var(--graphite);
  color: #FFFFFF;
  font-size: 10px;
  line-height: 20px;
  font-weight: 800;
  overflow: hidden;
}

.wk-areas {
  display: flex;
  flex-direction: column;
  gap: 3px;
  width: 100%;
}

.wk-area {
  display: block;
  padding: 2px 2px;
  border-radius: 6px;
  background: var(--well);
  color: var(--ink-2);
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.wk-area.is-more {
  background: var(--tray);
  color: var(--ink-3);
}

/* today: a red ring and the word "Today" */
.wk-day.is-today {
  box-shadow: inset 0 0 0 2px var(--ground), var(--sh-key);
}

.wk-day.is-today .wk-dow {
  color: var(--ground);
}

/* days gone: flat grey, still open to look back at */
.wk-day.is-past {
  background: var(--well);
  box-shadow: none;
  color: var(--ink-3);
}

.wk-day.is-past .wk-count {
  background: var(--ink-3);
}

.wk-day.is-past .wk-area {
  background: var(--well-2);
}

.wk-day.is-past .wk-area.is-more {
  background: var(--well);
}

/* past the ends of the data: an empty dashed outline on the red, not a key */
.wk-day.is-out {
  background: transparent;
  box-shadow: none;
  border: 2px dashed #FFFFFF;
  color: #FFFFFF;
}

.wk-day.is-out .wk-dow,
.wk-day.is-out .wk-none {
  color: #FFFFFF;
}

/* the chosen day: down and red, like a chosen key */
.wk-day.is-sel {
  background: var(--down-face);
  box-shadow: var(--sh-down);
  color: #FFFFFF;
  transform: translateY(2px);
}

.wk-day.is-sel .wk-dow,
.wk-day.is-sel .wk-none {
  color: #FFFFFF;
}

.wk-day.is-sel .wk-count,
.wk-day.is-sel .wk-area {
  background: #FFFFFF;
  color: var(--ground);
}

.wk-day.is-sel .wk-area.is-more {
  background: var(--ground-deep);
  color: #FFFFFF;
}

.wk-day.is-sel .wk-shut {
  background: #FFFFFF;
  color: var(--graphite);
}

/* a new week slides in the way the rep moved (backwards fill: no transform
   left on the element once it lands) */
.wk-bar.slide-next,
.wk-grid.slide-next {
  animation: wk-in-next var(--t-move) var(--ease-enter) backwards;
}

.wk-bar.slide-prev,
.wk-grid.slide-prev {
  animation: wk-in-prev var(--t-move) var(--ease-enter) backwards;
}

@keyframes wk-in-next {
  from {
    transform: translateX(32px);
  }
}

@keyframes wk-in-prev {
  from {
    transform: translateX(-32px);
  }
}

.wk-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* a closed day under the week bar: graphite lock, the reason, what is booked */
.wk-closed-note {
  flex-direction: row;
  align-items: center;
  gap: 14px;
}

.wk-closed-icon {
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--graphite);
  color: #FFFFFF;
}

.wk-closed-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.wk-closed-title {
  font-size: 17px;
  line-height: 22px;
  font-weight: 800;
  color: var(--ink);
}

/* on its side: seven columns, each day's visits as small cards */
.wk-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 8px;
  align-items: start;
  touch-action: pan-y;
}

.wk-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.wk-day.is-head {
  min-height: 88px; /* a "not loaded" head (no count) lines up with the rest */
  padding: 8px 4px 10px;
}

.wk-card {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  min-height: 44px;
  padding: 8px 10px;
  border-radius: 14px;
  background: var(--key-face);
  box-shadow: var(--sh-key);
  color: var(--ink);
  text-align: left;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.wk-card:active {
  transform: translateY(2px);
  box-shadow: var(--sh-key-pressed);
}

.wk-card.is-past {
  background: var(--well);
  box-shadow: none;
}

.wk-card-time {
  font-size: 15px;
  line-height: 20px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.wk-card-name {
  font-size: 14px;
  line-height: 18px;
  font-weight: 800;
  overflow-wrap: anywhere;
}

.wk-card-area {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
  color: var(--ink-3);
}

.wk-card-tick {
  color: var(--good);
}

.wk-shut-card {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px;
  border-radius: 14px;
  background: var(--graphite);
  color: #FFFFFF;
  font-size: 13px;
  line-height: 17px;
  font-weight: 800;
}

.wk-shut-card .q-icon {
  flex: 0 0 auto;
}

.wk-col-empty {
  padding: 8px 4px;
  text-align: center;
  color: #FFFFFF;
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
}

.bento-cell {
  gap: 6px;
  padding: 14px;
}

.bento-note {
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: var(--ink-3);
}

.bento-note.is-good {
  color: var(--good-ink);
}

.bento-note.is-advice {
  color: var(--advice-ink);
}

.bento-4 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 12px;
}

.bento-4 > div {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.bento-4 > div:nth-child(n + 3) {
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}

/* My quotes summary, wide tablet landscape (same ≥900 px breakpoint as the
   rest of the wide layout): Quoted / Deposits / Office follow-up / Not
   proceeding read better 4 across in one row than 2x2. Portrait and phone
   keep the 2x2 grid above, with its second-row rule. */
@media (min-width: 900px) and (orientation: landscape) {
  .bento-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .bento-4 > div:nth-child(n + 3) {
    padding-top: 0;
    border-top: none;
  }
}

/* ---- My quotes ---- */
.quote-card {
  gap: 10px;
  padding: 14px 16px;
  text-align: left;
  width: 100%;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
}

.quote-card:active {
  transform: translateY(2px);
}

.quote-card-top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.quote-card-name {
  font-size: 19px;
  line-height: 24px;
  font-weight: 800;
  color: var(--ink);
  overflow-wrap: anywhere; /* one long word beside the figure on a phone */
}

.quote-card.is-new {
  animation: card-land 520ms var(--ease-enter) both;
}

/* ---- saved quote / signature card ---- */
.sig-box {
  position: relative;
  height: 112px;
  border-radius: 16px;
  background: var(--well);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sig-box img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.sig-note {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: var(--good-ink);
}

.sig-note.is-muted {
  color: var(--ink-3);
}

/* ---- House: fuse numerals, heating keys, fabric answers ---- */
.fabric-q {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.fabric-q + .fabric-q {
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

.fabric-q-title {
  font-size: 17px;
  line-height: 22px;
  font-weight: 800;
  color: var(--ink);
}

.override {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.override-label {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-2);
}

.override .key {
  width: 44px;
  height: 44px;
  min-width: 44px;
  padding: 0;
  border-radius: 999px;
}

.override .key.is-ghost {
  width: auto;
  padding: 0 10px;
  font-size: 15px;
}

.factor-honest {
  font-size: 13px;
  line-height: 18px;
  font-weight: 700;
  color: var(--ink-3);
}

/* ---- Add room: presets, dimensions (Length/Width/Height use the device's
   own number keyboard — owner, 6 Oct 2026) ---- */
.dims {
  display: flex;
  gap: 8px;
}

.dims .well-field {
  padding: 0 12px;
}

.dims input {
  caret-color: var(--ground);
}

.kw-hero-top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}

.details-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 32px;
}

.details-toggle .key {
  height: 32px;
  padding: 0 4px;
}

/* ---- Rooms hub: room rows with a meter and £, swipe to remove ---- */
.room-row-wrap {
  position: relative;
  overflow: hidden;
}

.room-row-wrap + .room-row-wrap {
  border-top: 1px solid var(--rule);
}

.room-row {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  padding: 12px 0;
  text-align: left;
  background: var(--tray);
  transition: transform var(--t-move) var(--ease);
  touch-action: pan-y;
}

.room-row.is-dragging {
  transition: none;
}

.room-row:active:not(.is-dragging) {
  background: linear-gradient(0deg, rgba(22, 23, 26, 0.035), rgba(22, 23, 26, 0.035)), var(--tray);
}

.room-row-line {
  display: flex;
  align-items: center;
  gap: 10px;
}

.room-row-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 18px;
  line-height: 24px;
  font-weight: 800;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.room-row-kw {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 17px;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.room-row-kw.is-empty {
  color: var(--ink-3);
}

.room-row-kw .q-icon {
  color: var(--good-ink);
}

.room-row-meta {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.room-row-price {
  font-size: 15px;
  font-weight: 800;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.room-row-fit {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 15px;
  font-weight: 800;
  color: var(--ground);
}

/* the checklist mark: a tick once a room has radiators, an empty ring until then */
.room-check {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  border-radius: 99px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: inset 0 0 0 2px var(--ink-3);
  color: var(--good-ink);
}

.room-check.is-done {
  background: var(--good-wash);
  box-shadow: none;
}

/* Pick radiators: the room's size, with a way to put it right */
.size-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--rule);
}

.size-line .key {
  flex: 0 0 auto;
  margin-right: -8px;
}

/* small links on the ground: "All rooms · 2 of 3 rooms have radiators" */
.flow-links {
  display: flex;
  justify-content: center;
}

.flow-links .key {
  white-space: normal;
  height: auto;
  min-height: 44px;
}

.room-row-remove {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  width: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: var(--ink);
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 800;
  border-radius: 0 12px 12px 0;
}

.room-row-remove .q-icon {
  color: #FFFFFF;
}

.room-row.is-new .meter-fill.is-good,
.cover-tray.is-warm .meter-fill {
  animation: warm-glow var(--t-long) var(--ease) both;
}

/* ---- Pick radiators: coverage, best fit, models ---- */
.cover-top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}

.cover-tray .cover-tick {
  display: inline-flex;
  color: var(--good-ink);
}

.cover-tray .cover-tick svg path {
  stroke-dasharray: 24;
  animation: tick-draw 240ms var(--ease) both;
}

.bestfit {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 16px;
  background: var(--good-wash);
}

.bestfit > .q-icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--good-ink);
}

.bestfit-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.bestfit-title {
  font-size: 15px;
  line-height: 20px;
  font-weight: 800;
  color: var(--ink);
}

.bestfit-sub {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.model-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 68px;
  padding: 6px 0;
}

.model-row + .model-row {
  border-top: 1px solid var(--rule);
}

.model-glyph {
  flex: 0 0 60px;
  width: 60px;
  display: flex;
  align-items: center;
}

.model-glyph > span {
  display: flex;
  border-radius: 4px;
  background: #FFFFFF;
  border: 1.5px solid #CDBDB9;
  overflow: hidden;
}

.model-glyph > span > i {
  flex: 1 1 0;
  border-right: 1px solid #E1D6D3;
}

.model-glyph > span > i:last-child {
  border-right: 0;
}

.model-row.has-qty .model-glyph > span {
  border-color: var(--ground);
}

/* the radiator tapped in the 3D (Pick radiators, the Room or the Radiator
   view): its line wears the same red frame the radiator does there */
.model-row.is-picked {
  position: relative;
}

.model-row.is-picked::after {
  content: "";
  position: absolute;
  inset: 3px -8px;
  border: 2px solid var(--ground);
  border-radius: 14px;
  pointer-events: none;
  animation: picked-in var(--t-settle) var(--ease) both;
}

@keyframes picked-in {
  from {
    opacity: 0;
    transform: scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.model-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.model-code {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
  line-height: 22px;
  font-weight: 800;
  color: var(--ink);
}

.model-sub {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.models-in {
  display: flex;
  flex-direction: column;
  animation: fade-in 160ms var(--ease) both;
}

.wall-note {
  font-size: 13px;
  line-height: 18px;
  font-weight: 800;
  color: #FFFFFF;
}

/* ---- the Quote step: Extras | Summary ---- */
.total-hero .fig {
  margin: 2px 0;
}

.tray.part-switch {
  padding: 8px;
}

.room-controls + .room-controls {
  border-top: 1px solid var(--rule);
  margin-top: 4px;
}

.room-controls-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 12px 0 2px;
}

/* ---- the Sign step: what's missing, then the outcome ---- */
.missing-row > .q-icon {
  color: var(--advice);
}

.missing-row .row-title,
.missing-block .row-title {
  font-size: 16px;
  line-height: 21px;
}

.missing-block {
  align-items: center;
  margin: 4px 0 6px;
}

.missing-block .key {
  flex: 0 0 auto;
}

.outcome-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.contact-fields {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* a "Fix →" link lands here: the focus ring, briefly */
.fix-target {
  outline: 3px solid var(--ink);
  outline-offset: 4px;
  animation: fix-ring 1800ms var(--ease) both;
}

@keyframes fix-ring {
  0%,
  72% {
    outline-color: var(--ink);
  }
  100% {
    outline-color: rgba(22, 23, 26, 0);
  }
}

/* ---- the ticket (a customer document) ---- */
.ticket {
  display: flex;
  flex-direction: column;
}

.ticket-room {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 0 2px;
}

.ticket-room .label {
  flex: 1 1 auto;
  color: var(--ink-2);
}

.tline {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 8px 0;
}

.tline + .tline {
  border-top: 1px solid var(--rule);
}

.tline-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.tline-title {
  font-size: 16px;
  line-height: 22px;
  font-weight: 700;
  color: var(--ink);
}

.tline-sub {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

.tline-amount {
  flex: 0 0 auto;
  font-size: 16px;
  line-height: 22px;
  font-weight: 800;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.tline.is-good .tline-amount,
.tline.is-good .tline-title {
  color: var(--good-ink);
}

.tline.is-included .tline-amount {
  color: var(--ink-3);
}

.ticket-sums {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ticket-sum {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 15px;
  line-height: 21px;
  font-weight: 700;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.ticket-sum.is-good {
  color: var(--good-ink);
  font-weight: 800;
}

.ticket-total {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}

.vat-note {
  font-size: 13px;
  line-height: 18px;
  font-weight: 600;
  color: var(--ink-3);
}

/* ---- the outcome step ---- */
.outcome-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.outcome-key {
  height: auto;
  min-height: 112px;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 14px;
  border-radius: 18px;
  text-align: left;
  white-space: normal;
}

.outcome-key .q-icon {
  width: 24px;
  height: 24px;
}

.outcome-key-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.outcome-key-title {
  font-size: 17px;
  line-height: 21px;
  font-weight: 800;
}

.outcome-key-sub {
  font-size: 14px;
  line-height: 18px;
  font-weight: 700;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.key.is-down .outcome-key-sub,
.key[aria-pressed="true"] .outcome-key-sub {
  color: #FFFFFF;
}

.panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border-radius: 18px;
  background: var(--well);
}

.panel .well-field {
  background: #FFFFFF;
}

.panel .label {
  color: var(--ink-2);
}

.bal-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 2px 2px 0;
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.bal-line strong {
  font-weight: 800;
  color: var(--ink);
}

/* ---- the Sign sheet: the customer holds the phone ---- */
.terms {
  display: flex;
  flex-direction: column;
  gap: 8px;
  list-style: none;
  padding: 14px;
  border-radius: 18px;
  background: var(--well);
}

.terms li {
  display: flex;
  gap: 10px;
  font-size: 15px;
  line-height: 21px;
  font-weight: 600;
  color: var(--ink-2);
}

.terms li::before {
  content: "";
  flex: 0 0 6px;
  width: 6px;
  height: 6px;
  margin-top: 8px;
  border-radius: 99px;
  background: var(--ink-3);
}

.pad {
  position: relative;
  height: 176px;
  border-radius: 18px;
  background: var(--well);
  box-shadow: var(--sh-well);
  overflow: hidden;
  touch-action: none;
}

.pad canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  cursor: crosshair;
}

.pad-base {
  position: absolute;
  left: 44px;
  right: 22px;
  top: 128px;
  border-top: 2px dashed var(--ink-3);
  pointer-events: none;
}

.pad-cross {
  position: absolute;
  left: 18px;
  top: 116px;
  width: 16px;
  height: 16px;
  pointer-events: none;
  color: var(--ink-2);
}

.pad-hint {
  position: absolute;
  left: 44px;
  top: 138px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-3);
  pointer-events: none;
}

.pad-clear {
  position: absolute;
  right: 10px;
  top: 10px;
  z-index: 2;
}

/* ---- hand back: hold to save ---- */
.hold-key {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  height: 72px;
  border-radius: 999px;
  background: var(--key-face);
  box-shadow: var(--sh-key-ground);
  color: var(--ground);
  font-size: 19px;
  font-weight: 800;
  transition: transform var(--t-tap) var(--ease), box-shadow var(--t-tap) var(--ease);
  touch-action: none;
  -webkit-touch-callout: none;
}

.hold-key.is-holding {
  transform: translateY(2px) scale(0.99);
  box-shadow: var(--sh-key-pressed);
}

.hold-key.is-done {
  background: var(--down-face);
  color: #FFFFFF;
  box-shadow: var(--sh-down);
}

.hold-ring {
  flex: 0 0 44px;
  display: block;
}

.hold-ring .ring-bg {
  stroke: #F3D3D4;
}

.hold-ring .ring-fg {
  stroke: var(--ground);
}

.hold-key.is-done .ring-bg {
  stroke: rgba(255, 255, 255, 0.35);
}

.hold-key.is-done .ring-fg,
.hold-key.is-done .ring-tick {
  stroke: #FFFFFF;
}

.hold-help {
  text-align: center;
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  color: #FFFFFF;
}

.foot-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 8px;
}

/* ============================================================ 6 · overlays */

/* ---- Show mode: the customer's view ---- */
.show {
  position: fixed;
  inset: 0;
  z-index: 80;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: radial-gradient(90% 55% at 12% 0%, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 60%),
    radial-gradient(80% 50% at 100% 100%, rgba(142, 15, 21, 0.3) 0%, rgba(142, 15, 21, 0) 70%), var(--ground);
  animation: show-in 320ms var(--ease-enter) both;
}

.show.is-leaving {
  animation: fade-out var(--t-move) var(--ease) both;
}

.show-inner {
  max-width: var(--frame-w);
  margin: 0 auto;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: calc(10px + var(--safe-t)) var(--gutter) calc(100px + var(--safe-b));
}

.show-top {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
}

.show-top .key.is-s {
  padding: 0 8px;
}

.show .tray.is-rows {
  padding: 2px 16px;
}

.tline.is-show {
  padding: 7px 0;
}

.tline.is-show .tline-title,
.tline.is-show .tline-amount {
  font-size: 15px;
  line-height: 20px;
}

.tline.is-show .tline-sub {
  font-size: 13px;
  line-height: 17px;
}

.show-top .grow {
  flex: 1 1 auto;
}

.show-title {
  font-size: 30px;
  line-height: 34px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #FFFFFF;
}

.show-sub {
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
  color: #FFFFFF;
}

.show-total {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 2px 2px 0;
}

.show-total-note {
  font-size: 15px;
  line-height: 20px;
  font-weight: 800;
  color: #FFFFFF;
}

.show-hidden {
  font-size: 22px;
  line-height: 28px;
  font-weight: 800;
  color: #FFFFFF;
}

.next-steps {
  display: flex;
  gap: 4px;
  padding: 12px 6px;
  border-radius: 20px;
  background: rgba(142, 15, 21, 0.35);
}

.next-step {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  font-size: 12px;
  line-height: 15px;
  font-weight: 800;
  color: #FFFFFF;
}

.next-step-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  color: #FFFFFF;
}

.next-step:first-child .next-step-dot {
  background: #FFFFFF;
  color: var(--ground);
}

.show-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(16px + var(--safe-b));
  z-index: 81;
  width: calc(min(100vw, var(--frame-w)) - 32px);
  margin: 0 auto;
}

.show .reveal {
  animation: row-enter var(--t-move) var(--ease) both;
  animation-delay: calc(120ms + var(--i, 0) * var(--stagger));
}

/* ---- Lights on: the save celebration ---- */
.celebrate {
  position: fixed;
  inset: 0;
  z-index: 90;
  overflow: hidden;
  cursor: pointer;
  animation: fade-in 200ms var(--ease) both;
}

/* the red room is its own layer so it can melt away while the house flies
   into its new My quotes card underneath */
.celebrate::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(70% 45% at 50% 32%, #F0373D 0%, #E5252B 55%, #C41A21 100%);
  transition: opacity 420ms var(--ease);
}

.celebrate.is-flying::before,
.celebrate.is-flying .celebrate-glow,
.celebrate.is-flying .celebrate-foot {
  opacity: 0;
}

.celebrate-glow {
  position: absolute;
  left: -60px;
  right: -60px;
  top: 60px;
  height: 460px;
  background: radial-gradient(50% 50% at 50% 50%, rgba(255, 176, 120, 0.38) 0%, rgba(255, 176, 120, 0) 70%);
  pointer-events: none;
  transition: opacity 320ms var(--ease);
}

.celebrate-inner {
  position: relative;
  max-width: var(--frame-w);
  height: 100%;
  margin: 0 auto;
}

/* the whole house (step 4 of the 3D upgrade, 8 Oct 2026) wants a little more
   height than the old plan did: 380 px at most, still 40% of the screen */
.celebrate-scene {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(56px + var(--safe-t));
  height: min(380px, 40vh);
}

.celebrate-scene > .scene-stage,
.celebrate-scene > .iso {
  position: absolute;
  inset: 0;
}

.celebrate-copy {
  position: absolute;
  left: 20px;
  right: 20px;
  top: calc(56px + var(--safe-t) + min(380px, 40vh) + 8px);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.celebrate-copy > * {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 320ms var(--ease), transform 420ms var(--ease-enter);
}

.celebrate.phase-total .celebrate-when,
.celebrate.phase-total .celebrate-total,
.celebrate.phase-total .celebrate-who,
.celebrate.phase-card .celebrate-copy > * {
  opacity: 1;
  transform: none;
}

.celebrate-when {
  font-size: 11px;
  line-height: 14px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #FFFFFF;
}

.celebrate-who {
  font-size: 24px;
  line-height: 30px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: #FFFFFF;
}

.celebrate-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  border-radius: 22px;
  background: #FFFFFF;
  box-shadow: var(--sh-tray);
}

.celebrate-card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 48px;
  width: 48px;
  height: 48px;
  border-radius: 16px;
  background: var(--well);
  color: var(--ground);
}

.celebrate-card-icon .q-icon {
  width: 26px;
  height: 26px;
}

.celebrate-foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(26px + var(--safe-b));
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 800;
  color: #FFFFFF;
  opacity: 0;
  transition: opacity 320ms var(--ease);
}

.celebrate.phase-card .celebrate-foot {
  opacity: 1;
}

.celebrate.is-flying {
  pointer-events: none;
}

.celebrate.is-flying .celebrate-inner {
  transition: transform 520ms var(--ease-enter), opacity 520ms var(--ease);
}

.celebrate.is-leaving {
  animation: fade-out 380ms var(--ease) both;
}

/* ============================================================ 7 · motion */

/* screens fly, never cut: the entering screen slides in (the wave-3 shell) */
.tab-content {
  overflow-x: clip;
}

/* The shell only ever animates OPACITY: a transform on it would make the fixed
   header, strip and Quote Bar inside it position against the shell instead of
   the viewport for the length of the move. The scrolling body does the slide. */
.screen-shell {
  animation: shell-fade-in var(--t-move) var(--ease) both;
}

/* fill-mode `backwards`, not `both`: a `both`/`forwards` fill keeps the
   transform animation "in effect" on .body even after it finishes (Chrome
   then treats .body as the containing block for any position:fixed
   descendant — the RAL picker, any sheet opened on this screen — pinning it
   to the bottom of the tall scrolling .body instead of the viewport until
   the rep scrolls all the way down). `backwards` only affects the moment
   before the animation starts, which doesn't exist here (no animation-delay),
   so the entering frame looks identical; once the animation ends .body goes
   back to its unanimated computed style (no transform) — ruling, 6 Oct 2026. */
.screen-shell.shell-forward .body {
  animation: shell-in-right var(--t-move) var(--ease) backwards;
}

.screen-shell.shell-back .body {
  animation: shell-in-left var(--t-move) var(--ease) backwards;
}

@keyframes shell-in-right {
  from {
    opacity: 0;
    transform: translate3d(24px, 0, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes shell-in-left {
  from {
    opacity: 0;
    transform: translate3d(-24px, 0, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes shell-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* lists: rows rise 8 px, staggered 35 ms, capped at 8 */
.stagger-item {
  animation: row-enter var(--t-move) var(--ease) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}

.stagger-item.is-pop {
  animation: row-pop 260ms var(--ease-pop) both;
  animation-delay: 0ms;
}

.stagger {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* rows that rise in on mount, 35 ms apart (set --i inline), without a wrapper */
.rise {
  animation: row-enter var(--t-move) var(--ease) both;
  animation-delay: calc(min(var(--i, 0), 7) * var(--stagger));
}

@keyframes row-enter {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes row-pop {
  0% {
    opacity: 0;
    transform: scale(0.94);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: none;
  }
}

.row-collapsing {
  display: grid;
  grid-template-rows: 1fr;
  animation: row-collapse var(--t-move) var(--ease) forwards;
  pointer-events: none;
}

.row-collapsing > * {
  overflow: hidden;
  min-height: 0;
}

@keyframes row-collapse {
  from {
    grid-template-rows: 1fr;
    opacity: 1;
  }
  to {
    grid-template-rows: 0fr;
    opacity: 0;
  }
}

/* the stepper digit ticks (motion.js Ticker) */
.ticker {
  position: relative;
  display: inline-block;
  min-width: 1ch;
  text-align: center;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  vertical-align: bottom;
  line-height: 1.25;
}

.ticker-out {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
}

.ticker-in {
  display: block;
}

.ticker-out.tick-up {
  animation: tick-out-up 140ms var(--ease) both;
}

.ticker-out.tick-down {
  animation: tick-out-down 140ms var(--ease) both;
}

.ticker-in.tick-up {
  animation: tick-in-up 140ms var(--ease) both;
}

.ticker-in.tick-down {
  animation: tick-in-down 140ms var(--ease) both;
}

@keyframes tick-out-up {
  to {
    opacity: 0;
    transform: translateY(-100%);
  }
}

@keyframes tick-out-down {
  to {
    opacity: 0;
    transform: translateY(100%);
  }
}

@keyframes tick-in-up {
  from {
    opacity: 0;
    transform: translateY(100%);
  }
}

@keyframes tick-in-down {
  from {
    opacity: 0;
    transform: translateY(-100%);
  }
}

.num-tween {
  font-variant-numeric: tabular-nums;
}

@keyframes delta-rise {
  0% {
    opacity: 0;
    transform: translateY(10px) scale(0.9);
  }
  12% {
    opacity: 1;
    transform: none;
  }
  70% {
    opacity: 1;
    transform: translateY(-4px);
  }
  100% {
    opacity: 0;
    transform: translateY(-8px);
  }
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes toast-out {
  to {
    opacity: 0;
    transform: translateY(12px);
  }
}

@keyframes sheet-in {
  from {
    transform: translateY(100%);
  }
  to {
    transform: none;
  }
}

@keyframes sheet-out {
  to {
    transform: translateY(100%);
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-out {
  to {
    opacity: 0;
  }
}

@keyframes modal-in {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes show-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes card-land {
  0% {
    opacity: 0;
    transform: translateY(-18px) scale(1.04);
  }
  100% {
    opacity: 1;
    transform: none;
  }
}

@keyframes card-shake {
  0%,
  100% {
    transform: none;
  }
  20%,
  60% {
    transform: translateX(-4px);
  }
  40%,
  80% {
    transform: translateX(4px);
  }
}

@keyframes tick-draw {
  from {
    stroke-dashoffset: 24;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes warm-glow {
  0% {
    box-shadow: 0 0 0 0 rgba(30, 158, 90, 0);
  }
  40% {
    box-shadow: 0 0 0 5px rgba(30, 158, 90, 0.22);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(30, 158, 90, 0);
  }
}

@keyframes busy-dots {
  0% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0.4;
  }
}

@keyframes skeleton-shimmer {
  from {
    background-position: 120% 0;
  }
  to {
    background-position: -120% 0;
  }
}

@keyframes photo-in {
  from {
    opacity: 0;
    transform: scale(1.04);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes tile-breathe {
  0%,
  74%,
  100% {
    transform: none;
  }
  84% {
    transform: scale(1.12);
  }
}

@keyframes ground-drift-a {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(16%, 26%, 0) scale(1.18);
  }
  100% {
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes ground-drift-b {
  0% {
    transform: translate3d(0, 0, 0) scale(1.12);
  }
  50% {
    transform: translate3d(-14%, -22%, 0) scale(1);
  }
  100% {
    transform: translate3d(0, 0, 0) scale(1.12);
  }
}

/* ---- View Transitions (Chrome 111+, Safari 18+): the Quote Bar, the header
   and the dock stay put while the screen flies; the shell slide above is the
   fallback, switched off while a transition runs so it is never doubled. ---- */
.qbar {
  view-transition-name: qbar;
}

.dock {
  view-transition-name: dock;
}

.hdr {
  view-transition-name: hdr;
}

html.vt-on .screen-shell,
html.vt-on .screen-shell .body {
  animation: none;
}

::view-transition-group(*) {
  animation-duration: var(--t-move);
  animation-timing-function: var(--ease);
}

html[data-vt="forward"]::view-transition-old(root) {
  animation: vt-out-left 200ms var(--ease) both;
}

html[data-vt="forward"]::view-transition-new(root) {
  animation: vt-in-right var(--t-move) var(--ease) both;
}

html[data-vt="back"]::view-transition-old(root) {
  animation: vt-out-right 200ms var(--ease) both;
}

html[data-vt="back"]::view-transition-new(root) {
  animation: vt-in-left var(--t-move) var(--ease) both;
}

html[data-vt="fade"]::view-transition-old(root) {
  animation: fade-out 160ms var(--ease) both;
}

html[data-vt="fade"]::view-transition-new(root) {
  animation: fade-in var(--t-move) var(--ease) both;
}

@keyframes vt-in-right {
  from {
    opacity: 0;
    transform: translateX(28px);
  }
}

@keyframes vt-in-left {
  from {
    opacity: 0;
    transform: translateX(-28px);
  }
}

@keyframes vt-out-left {
  to {
    opacity: 0;
    transform: translateX(-12px);
  }
}

@keyframes vt-out-right {
  to {
    opacity: 0;
    transform: translateX(12px);
  }
}

/* the Add room fields wipe as "Save & add" clears them */
.wipe-host.is-wiping {
  animation: field-wipe var(--t-move) var(--ease) both;
}

@keyframes field-wipe {
  0% {
    opacity: 0.25;
    transform: translateX(-10px);
  }
  100% {
    opacity: 1;
    transform: none;
  }
}

/* the icon draw-on host */
.icon-draw {
  display: inline-flex;
}

/* ============================================================ 8 · modes */

/* Bright sun mode (the ⋯ menu): heavier weights, darker secondary text */
html[data-sun="on"] {
  --ink-2: #2E3036;
  --ink-3: #464950;
  --rule: #DDD4D2;
  --well: #EFE9E8;
  --w-body: 700;
  --w-strong: 800;
  --track-off: #C9BEBC;
}

html[data-sun="on"] .caption,
html[data-sun="on"] .row-sub,
html[data-sun="on"] .tline-sub,
html[data-sun="on"] .model-sub,
html[data-sun="on"] .room-row-meta,
html[data-sun="on"] .help,
html[data-sun="on"] .modal-text {
  font-weight: 700;
}

html[data-sun="on"] .tray {
  box-shadow: 0 1px 0 rgba(90, 10, 15, 0.18), 0 10px 26px rgba(90, 5, 10, 0.34);
}

/* the 14 Sep pink tray tint, kept only as a flag (config.js FLAGS.trays) */
html[data-trays="pink"] {
  --tray: linear-gradient(180deg, #FFF7F7 0%, #FBEEEE 100%);
}

html[data-trays="pink"] .room-row {
  background: transparent;
}

/* ---- Chromebook / tablet: two panes from 900 px (BRIEF §7, owner Q8) ---- */
.app.is-wide {
  --frame-w: 100vw;
}

.app.is-wide .frame {
  max-width: none;
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr) 462px;
  min-height: 100vh;
}

/* no ticket pane (Today, Visits, My quotes, a visit, a saved quote): the
   pane's column goes back to the screen (8 Oct 2026: it sat empty, squeezing
   the day into ~500 px on the left of a tablet on its side) */
.app.is-wide:not(.has-pane) .frame {
  grid-template-columns: 96px minmax(0, 1fr);
}

.rail {
  display: none;
}

.app.is-wide .rail {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  z-index: 50;
  width: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 20px 0;
  background: rgba(142, 15, 21, 0.28);
}

.rail-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 72px;
  height: 64px;
  border-radius: 20px;
  color: #FFFFFF;
  font-size: 12px;
  font-weight: 800;
  transition: transform var(--t-tap) var(--ease), background var(--t-settle) var(--ease);
}

.rail-tab .q-icon {
  width: 22px;
  height: 22px;
}

.rail-tab[aria-current="page"] {
  background: var(--down-face);
  box-shadow: var(--sh-down);
  transform: translateY(1px);
}

.rail-tab:active {
  transform: translateY(1px);
}

.rail .grow {
  flex: 1 1 auto;
}

/* "a quote is in progress" on the rail: a solid white dot on the red (the
   dock's red dot with its white ring read as a hollow ring here, 8 Oct 2026) */
.rail .dock-dot {
  background: #FFFFFF;
  box-shadow: 0 1px 2px rgba(90, 10, 15, 0.35);
}

.app.is-wide .dock,
.app.is-wide .scrim {
  display: none;
}

/* v3: the Quote Bar stays on wide screens — it carries each step's next key
   (the pane is the live, read-only ticket), under the build column */
.app.is-wide .qbar {
  left: 120px;
  right: 24px;
  bottom: 16px;
  width: auto;
  max-width: 760px;
  margin: 0 auto;
}

.app.is-wide.has-pane .qbar {
  right: 502px;
  max-width: none;
  margin: 0;
}

.app.is-wide .toast.above-bar {
  bottom: calc(16px + var(--bar-h) + 12px);
}

.app.is-wide .tab-content {
  grid-column: 2;
  min-width: 0;
}

.app.is-wide .hdr {
  left: 96px;
  right: 0;
  max-width: none;
  margin: 0;
  padding-left: max(24px, calc((100vw - 96px - 760px) / 2));
  padding-right: max(24px, calc((100vw - 96px - 760px) / 2));
}

.app.is-wide .body {
  width: 100%; /* auto side margins in the column flex would shrink it to its content */
  padding: 16px 24px 40px;
  max-width: 808px;
  margin: 0 auto;
}

/* the quote tab keeps the live ticket pane on the right */
.app.is-wide.has-pane .hdr {
  right: 478px;
  padding-left: 24px;
  padding-right: 24px;
}

.app.is-wide.has-pane .body {
  max-width: 860px;
  margin: 0;
}

.app.is-wide .hdr-row > .brand-lockup-mark {
  display: none;
}

/* the Visits week on its side takes the width for its seven columns (the
   header lines up with it) */
.app.is-wide .screen.is-week .body {
  max-width: 1240px;
}

.app.is-wide .screen.is-week .hdr {
  padding-left: max(24px, calc((100vw - 96px - 1192px) / 2));
  padding-right: max(24px, calc((100vw - 96px - 1192px) / 2));
}

.app.is-wide .screen.has-bar .body {
  padding-bottom: calc(var(--bar-h) + 48px);
}

.app.is-wide .strip {
  left: 120px;
  right: 24px;
  width: auto;
  max-width: 760px;
  margin: 0 auto;
}

.app.is-wide.has-pane .strip {
  right: 502px;
  max-width: none;
  margin: 0;
}

/* the backdrop matches the HEADER's span (not the inset strip tile), so it
   joins the header's background seamlessly in wide mode too */
.app.is-wide .strip-backdrop {
  left: 96px;
  right: 0;
  max-width: none;
  margin: 0;
}

.app.is-wide.has-pane .strip-backdrop {
  right: 478px;
}

.app.is-wide .toast {
  left: 96px;
  right: 0;
  bottom: 24px;
  width: auto;
  max-width: 560px;
}

.app.is-wide.has-pane .toast {
  right: 478px;
}

.app.is-wide .stage.is-hub {
  height: 330px;
}

/* ---- wide screens, the screens with a 3D stage (the sticky tile, owner
   8 Oct 2026): rail | the 3D in a LEFT pane that stays put | header, form
   and Quote Bar scrolling on the right. The pane is fixed and full height
   (like the ticket pane it stands in for here; the Quote Bar still opens the
   ticket); it sits outside the body, whose slide-in is a transform. ---- */
.app.is-wide.has-stage {
  --sp-left: 112px; /* the 96 px rail + 16 */
  --sp-w: clamp(360px, calc((100vw - 96px) * 0.46), 760px);
  --sp-right: calc(var(--sp-left) + var(--sp-w));
}

.app.is-wide.has-stage .frame {
  grid-template-columns: 96px minmax(0, 1fr);
}

.app.is-wide .screen.has-aside .stage-pane {
  position: fixed;
  z-index: 20;
  left: var(--sp-left);
  top: 16px;
  bottom: 16px;
  width: var(--sp-w);
  display: flex;
  flex-direction: column;
}

.app.is-wide .screen.has-aside .stage-pane > .stage {
  flex: 1 1 auto;
  min-height: 0;
  height: auto !important; /* over the stage's own inline height */
  border-radius: 28px;
}

.app.is-wide .screen.has-aside .hdr {
  left: var(--sp-right);
  right: 0;
  max-width: none;
  margin: 0;
  padding-left: 20px;
  padding-right: 24px;
}

.app.is-wide .screen.has-aside .body {
  max-width: none;
  margin: 0;
  padding: 16px 24px 40px calc(var(--sp-right) - 96px + 20px);
}

.app.is-wide .screen.has-aside.has-bar .body {
  padding-bottom: calc(var(--bar-h) + 48px);
}

.app.is-wide .screen.has-aside .qbar {
  left: calc(var(--sp-right) + 20px);
  right: 24px;
  width: auto;
  max-width: none;
  margin: 0;
}

.app.is-wide.has-stage .toast {
  left: var(--sp-right);
  right: 0;
}

.pane {
  display: none;
}

.app.is-wide .pane {
  position: fixed;
  right: 16px;
  top: 16px;
  bottom: 16px;
  z-index: 40;
  width: 462px;
  display: flex;
  flex-direction: column;
  border-radius: 28px;
  background: #FFFFFF;
  box-shadow: var(--sh-dock);
  overflow: hidden;
}

.pane-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 20px 6px;
}

.pane-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 0 20px 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.pane-foot {
  padding: 14px 20px 18px;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.pane-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex: 1 1 auto;
  padding: 24px;
  text-align: center;
}

.app.is-wide .show-inner,
.app.is-wide .celebrate-inner {
  max-width: 720px;
}

.app.is-wide .sheet,
.app.is-wide .modal-scrim .modal {
  max-width: 560px;
}

.app.is-wide .room-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}

/* wide screens: bigger 3D stages beside the ticket */
.app.is-wide {
  --stage-pick: 360px; /* the room in 3D (7 Oct 2026; was 320) */
  --stage-house: 300px;
  --stage-room: 250px;
  --stage-show: 380px;
  --stage-show-home: 300px;
}

/* ---- tablet, portrait (600-899 px): bigger touch targets, two columns where
   a list is long and each item is short ---- */
@media (min-width: 600px) and (max-width: 899px) and (orientation: portrait) {
  .key {
    height: 54px;
    min-width: 54px;
    padding: 0 18px;
    font-size: 18px;
  }

  .key.is-s {
    height: 46px;
    min-width: 46px;
    font-size: 16px;
  }

  .key.is-l {
    height: 62px;
  }

  .models-in {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 24px;
  }

  .models-in .model-row + .model-row {
    border-top: 0;
  }

  .models-in .model-row {
    border-bottom: 1px solid var(--rule);
  }

  .finish-pick {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .room-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }

  .show-models .key {
    height: 50px;
  }

  .stage.is-hub {
    height: 360px;
  }

  /* the Visits week bar: bigger day keys, three area chips each */
  .wk-bar {
    gap: 6px;
  }

  .wk-day {
    min-height: 112px;
    padding: 10px 6px;
    gap: 5px;
  }

  .wk-date {
    font-size: 24px;
    line-height: 28px;
  }

  .wk-area {
    font-size: 12px;
    line-height: 16px;
  }

  .wk-shut {
    padding: 0 6px;
    font-size: 12px;
  }
}

/* the column heads on a tablet on its side: the same roomy "Closed" */
.app.is-wide .wk-shut {
  padding: 0 6px;
  font-size: 12px;
}

/* ============================================================ 9 · reduced motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .frame::before,
  .frame::after,
  .photo-add .q-icon,
  .skeleton-bar {
    animation: none !important;
  }

  .odo-strip {
    transition: none !important;
  }

  .delta-chip {
    animation: delta-hold 1200ms linear both !important;
    animation-duration: 1200ms !important;
  }
}

@keyframes delta-hold {
  0%,
  99% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
