/* =============================================================================
   app.css
   -----------------------------------------------------------------------------
   Dark, low-chroma surfaces by design. This is a colour-judgement app, and
   simultaneous contrast is real: a saturated or warm interface shifts how every
   swatch on screen is perceived. Everything structural is therefore neutral
   grey, and the palette provides the only colour. The Palette view additionally
   offers an 18%-grey "studio surround", the standard neutral backdrop used when
   colour has to be judged accurately.
   ========================================================================== */

:root {
  --bg: #0e0e10;
  --surface: #17171a;
  --surface-2: #1e1e22;
  --surface-3: #26262b;
  --line: #2e2e34;
  --line-soft: #26262b;
  --ink: #f2f2f4;
  --ink-2: #b6b6bd;
  --ink-3: #83838d;
  --accent: #f3f3f3;
  --accent-ink: #111;
  /* the one saturated colour in the interface: iOS system blue, used only for
     controls so it never competes with a palette swatch */
  --tint: #0a84ff;

  --wow: #d8b4fe;
  --great: #6ee7b7;
  --ok: #93c5fd;
  --care: #fcd34d;
  --bad: #fca5a5;

  --r-sm: 8px;
  --r: 14px;
  --r-lg: 20px;
  --r-xl: 28px;

  --pad: 16px;
  --tab-h: 49px;
  --top-h: 56px;

  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  /* Clear the home indicator while letting the controls sit closer to it. The
     full safe-area inset made the tab icons look detached on Face ID iPhones. */
  --tab-safe: max(0px, calc(var(--sab) - 8px));

  --shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.28);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f4f4f6;
    --surface: #ffffff;
    --surface-2: #fafafb;
    --surface-3: #eeeef1;
    --line: #e0e0e6;
    --line-soft: #ebebf0;
    --ink: #16161a;
    --ink-2: #55555f;
    --ink-3: #85858f;
    --accent: #16161a;
    --accent-ink: #fff;
    --tint: #007aff;
    --wow: #7c3aed;
    --great: #047857;
    --ok: #1d4ed8;
    --care: #a16207;
    --bad: #b91c1c;
    --shadow: 0 1px 2px rgba(0,0,0,.06), 0 8px 24px rgba(0,0,0,.07);
  }
}

*, *::before, *::after { box-sizing: border-box; }

/*  The `hidden` attribute only sets `display: none` at the UA level, so any rule
    below that gives an element an explicit `display` silently defeats it. The
    sheet host is `position: fixed; inset: 0`, which meant a "hidden" overlay
    still swallowed every tap on the page. Make hidden mean hidden. */
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  /* 17px is the iOS body size; at 16px everything read subtly like a web page */
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -0.01em;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
  /* kill the 300 ms tap delay and double-tap zoom on controls */
  touch-action: manipulation;
}

body {
  min-height: 100dvh;
  /* chrome is not text: stop long-press selecting labels and callout menus */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* …but real content must stay selectable and copyable */
p, li, dd, dt, h1, h2, h3, h4, .mono, .small, .tiny, .muted, textarea, input {
  -webkit-user-select: text;
  user-select: text;
}

/* body scroll lock that survives iOS, used while a sheet or camera is open */
body.is-modal { overflow: hidden; touch-action: none; }

svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7;
      stroke-linecap: round; stroke-linejoin: round; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; -webkit-tap-highlight-color: transparent; }
a { color: inherit; text-decoration: none; }

:focus-visible { outline: 2px solid var(--ok); outline-offset: 2px; border-radius: 4px; }

/* ------------------------------------------------------------------ layout */

.app { min-height: 100dvh; display: flex; flex-direction: column; }

/*  An iOS navigation bar: 44 pt tall, hairline separator, title centred, and
    controls absolutely positioned so the title stays centred whether or not the
    back button is showing. The previous flex layout shifted the title sideways
    depending on which controls happened to be visible, which is one of the
    tells that something is a web page rather than an app. */
.topbar {
  position: sticky; top: 0; z-index: 40;
  padding: calc(var(--sat) + 6px) 56px 8px;
  min-height: calc(44px + var(--sat));
  display: flex; flex-direction: column; justify-content: center;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 0.5px 0 var(--line-soft);
  text-align: center;
}
.topbar__titles { min-width: 0; }
.topbar__title {
  margin: 0; font-size: 1.0rem; font-weight: 650; letter-spacing: -.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar__sub { margin: 0; font-size: .72rem; color: var(--ink-3);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/*  Back is a bare chevron, tinted, with a 44 pt tap target — no filled circle.
    iOS never puts a back chevron in a bubble, and the bubble was what made the
    small glyph inside it look badly padded. */
.topbar__back {
  position: absolute; left: max(4px, calc(var(--pad) - 12px));
  top: calc(var(--sat) + 2px);
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: none; border: 0; padding: 0;
  color: var(--tint);
}
.topbar__back svg { width: 25px; height: 25px; stroke-width: 2.4; }
.topbar__back:active { opacity: .35; }

.topbar__profile {
  position: absolute; right: max(8px, calc(var(--pad) - 6px));
  top: calc(var(--sat) + 4px);
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-3); border: 0; color: var(--ink);
  font-size: .82rem; font-weight: 650;
}
.topbar__profile:active { opacity: .6; }

.view {
  flex: 1;
  padding: var(--pad) var(--pad) calc(var(--tab-h) + var(--tab-safe) + 18px);
  max-width: 720px; width: 100%; margin: 0 auto;
  -webkit-overflow-scrolling: touch;
}
.view:focus { outline: none; }
.view--enter { animation: view-enter .2s cubic-bezier(.22,.8,.3,1); }
@keyframes view-enter {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: translateY(0); }
}

.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
  display: grid; grid-template-columns: repeat(5, 1fr);
  padding: 0 env(safe-area-inset-right, 0px) var(--tab-safe) env(safe-area-inset-left, 0px);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 -0.5px 0 var(--line-soft);
}
.tab {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; height: var(--tab-h); color: var(--ink-3);
  font-size: 10px; font-weight: 560; letter-spacing: 0;
}
.tab svg { width: 25px; height: 25px; stroke-width: 1.9; }
.tab[aria-current="page"] { color: var(--tint); }
.tab[aria-current="page"] svg { stroke-width: 2.15; }
.tab:active { opacity: .5; }

/* ------------------------------------------------------------------- blocks */

/*  iOS inset-grouped: a filled panel with a generous corner radius and NO
    border. The 1 px outline on every card was the single most "web" thing in
    the interface. */
.card {
  background: var(--surface); border: 0;
  border-radius: 16px; padding: 16px; margin: 0 0 12px;
}
.card--flush { padding: 0; overflow: hidden; }
.card--quiet { background: var(--surface-2); }

.stack > * + * { margin-top: 12px; }
.row { display: flex; align-items: center; gap: 10px; }
.row--between { justify-content: space-between; }
.row--wrap { flex-wrap: wrap; }
.grow { flex: 1; min-width: 0; }
.center { text-align: center; }
.muted { color: var(--ink-2); }
.dim { color: var(--ink-3); }
.tiny { font-size: .76rem; }
.small { font-size: .86rem; }
.mono { font-family: var(--mono); font-size: .8rem; letter-spacing: .02em; }
.nowrap { white-space: nowrap; }

h2 { font-size: 1.16rem; font-weight: 650; letter-spacing: -.01em; margin: 22px 0 10px; }
h3 { font-size: .96rem; font-weight: 650; margin: 0 0 8px; }
h4 { font-size: .8rem; font-weight: 620; margin: 0 0 6px; color: var(--ink-2);
     text-transform: uppercase; letter-spacing: .06em; }
p { margin: 0 0 10px; }
p:last-child { margin-bottom: 0; }
ul { margin: 0 0 10px; padding-left: 1.1rem; }
li { margin-bottom: 4px; }
hr { border: 0; border-top: 1px solid var(--line-soft); margin: 16px 0; }

/* ------------------------------------------------------------------ buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 18px; border-radius: 12px; border: 0;
  background: var(--surface-3); color: var(--tint);
  font-size: 1rem; font-weight: 600; min-height: 50px;
  transition: transform .1s cubic-bezier(.2,.9,.3,1), opacity .12s ease;
  -webkit-user-select: none; user-select: none;
}
.btn:active { transform: scale(.97); opacity: .75; }
.btn--primary { background: var(--tint); color: #fff; border-color: transparent; }
.btn--ghost { background: transparent; }
.btn--danger { color: var(--bad); background: color-mix(in srgb, var(--bad) 12%, transparent); }
.btn--block { width: 100%; }
.btn--sm { padding: 8px 14px; min-height: 36px; font-size: .88rem; border-radius: 10px; }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn svg { width: 19px; height: 19px; }

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }
.btn-row .btn { flex: 1 1 auto; }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: 999px; background: var(--surface-3);
  border: 1px solid var(--line); font-size: .78rem; font-weight: 560; color: var(--ink-2);
}
.chip--on { background: var(--tint); color: #fff; border-color: transparent; }

/* -------------------------------------------------------------- form fields */

.field { display: block; margin-bottom: 12px; }
.field > span { display: block; font-size: .78rem; font-weight: 600; color: var(--ink-2);
                margin-bottom: 6px; }
.field input[type=text], .field input[type=number], .field select, .field textarea {
  width: 100%; padding: 13px 14px; border-radius: 12px;
  background: var(--surface-3); border: 0; color: var(--ink);
  font-size: 1rem;   /* < 16px makes iOS zoom the page on focus */
  -webkit-appearance: none; appearance: none;
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 2px solid var(--tint); outline-offset: -2px;
}
.field textarea { min-height: 84px; resize: vertical; }

.switch { display: flex; align-items: center; justify-content: space-between; gap: 12px;
          padding: 12px 0; }
.switch + .switch { border-top: 1px solid var(--line-soft); }
.switch input { width: 46px; height: 28px; appearance: none; background: var(--surface-3);
                border: 1px solid var(--line); border-radius: 999px; position: relative;
                flex: 0 0 auto; transition: background .16s; }
.switch input::after { content: ""; position: absolute; top: 3px; left: 3px;
                       width: 20px; height: 20px; border-radius: 50%; background: var(--ink-2);
                       transition: transform .16s, background .16s; }
.switch input:checked { background: var(--great); border-color: transparent; }
.switch input:checked::after { transform: translateX(18px); background: #fff; }

/* -------------------------------------------------------------- swatch grid */

.swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.swatches--sm { grid-template-columns: repeat(auto-fill, minmax(62px, 1fr)); }

.swatch {
  position: relative; border-radius: var(--r); overflow: hidden;
  aspect-ratio: 1; display: flex; align-items: flex-end;
  border: 1px solid rgba(128,128,128,.28); text-align: left;
  padding: 7px; width: 100%; background-clip: padding-box;
}
.swatch__name { font-size: .66rem; font-weight: 620; line-height: 1.2;
                text-shadow: 0 1px 3px rgba(0,0,0,.35); }
.swatch__wow { position: absolute; top: 6px; right: 6px; width: 15px; height: 15px;
               border-radius: 50%; display: grid; place-items: center;
               background: rgba(0,0,0,.32); font-size: .55rem; }
.swatch--round { border-radius: 50%; align-items: center; justify-content: center;
                 text-align: center; padding: 10px; }
.swatch--wide { aspect-ratio: 2.2; }

.group-label { font-size: .7rem; font-weight: 650; text-transform: uppercase;
               letter-spacing: .1em; color: var(--ink-3); margin: 16px 0 7px; }

/* neutral studio surround for accurate colour judgement */
.studio { background: #7f7f7f !important; border-radius: var(--r-lg); padding: 14px; }
.studio .group-label, .studio .swatch__name { color: #111; text-shadow: none; }
.studio .swatch { border-color: rgba(0,0,0,.2); }

/* --------------------------------------------------------------- score ring */

.score {
  --pct: 0; --col: var(--ok);
  position: relative; width: 92px; height: 92px; flex: 0 0 auto;
  border-radius: 50%;
  background:
    conic-gradient(var(--col) calc(var(--pct) * 1%), color-mix(in srgb, var(--line) 70%, transparent) 0),
    var(--surface);
  display: grid; place-items: center;
}
.score::after {
  content: ""; position: absolute; inset: 8px; border-radius: 50%; background: var(--surface);
}
/*  z-index is load-bearing: .score::after paints the inner disc that turns the
    conic gradient into a ring, and without it that disc covers the number. */
.score__val { position: relative; z-index: 1; font-size: 1.5rem; font-weight: 700; letter-spacing: -.03em; }
.score__val sup { font-size: .6rem; font-weight: 600; color: var(--ink-3); top: -.7em; }
.score--sm { width: 56px; height: 56px; }
.score--sm::after { inset: 5px; }
.score--sm .score__val { font-size: 1rem; }

.verdict { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
           border-radius: 999px; font-size: .8rem; font-weight: 650; }
.v-wow  { background: color-mix(in srgb, var(--wow) 20%, transparent); color: var(--wow); }
.v-great{ background: color-mix(in srgb, var(--great) 18%, transparent); color: var(--great); }
.v-ok   { background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok); }
.v-care { background: color-mix(in srgb, var(--care) 18%, transparent); color: var(--care); }
.v-bad  { background: color-mix(in srgb, var(--bad) 18%, transparent); color: var(--bad); }

/* ---------------------------------------------------------------- reasoning */

.reasons { list-style: none; padding: 0; margin: 0; }
.reasons li { display: flex; gap: 9px; padding: 9px 0; font-size: .89rem; line-height: 1.45;
              border-top: 1px solid var(--line-soft); }
.reasons li:first-child { border-top: 0; }
.reasons .dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; margin-top: 7px; }
.r-good .dot { background: var(--great); }
.r-info .dot { background: var(--ok); }
.r-warn .dot { background: var(--care); }
.r-bad  .dot { background: var(--bad); }

/* ------------------------------------------------------------------- meters */

.meter { display: grid; grid-template-columns: 96px 1fr 34px; gap: 9px;
         align-items: center; font-size: .8rem; padding: 5px 0; }
.meter__track { height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.meter__fill { height: 100%; border-radius: 999px; background: var(--ink-2); }
.meter__val { text-align: right; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* axis meter: bipolar, -1 … +1 */
.axis { padding: 9px 0; border-top: 1px solid var(--line-soft); }
.axis:first-child { border-top: 0; }
.axis__head { display: flex; justify-content: space-between; font-size: .8rem; margin-bottom: 7px; }
.axis__head b { font-weight: 650; }
.axis__bar { position: relative; height: 8px; border-radius: 999px; background: var(--surface-3); }
.axis__bar::before { content: ""; position: absolute; left: 50%; top: -3px; bottom: -3px;
                     width: 1px; background: var(--line); }
.axis__pin { position: absolute; top: -4px; width: 16px; height: 16px; border-radius: 50%;
             background: var(--ink); border: 3px solid var(--surface); transform: translateX(-50%); }
.axis__ends { display: flex; justify-content: space-between; font-size: .68rem;
              color: var(--ink-3); margin-top: 5px; }

/* ------------------------------------------------------------------ camera */

.cam { position: fixed; inset: 0; z-index: 90; background: #000;
       display: flex; flex-direction: column; }
.cam__stage { position: relative; flex: 1; overflow: hidden; }
/*  contain, not cover. `cover` on a phone screen crops a 3:4 camera frame to
    19.5:9 and discards nearly half of it, which read as "the camera is zoomed
    right in" and made it impossible to get a whole head in shot. Letterboxing
    shows exactly what the detector sees. */
.cam__video, .cam__canvas { position: absolute; inset: 0; width: 100%; height: 100%;
                            object-fit: contain; }
.cam__canvas { pointer-events: none; }
.cam__guide { position: absolute; inset: 0; pointer-events: none; }
.cam__hud { position: absolute; left: 0; right: 0; top: calc(var(--sat) + 10px);
            padding: 0 16px; display: flex; flex-direction: column; gap: 7px; }
.cam__pill { align-self: center; padding: 7px 14px; border-radius: 999px;
             background: rgba(0,0,0,.62); color: #fff; font-size: .8rem; font-weight: 600;
             backdrop-filter: blur(8px); text-align: center; max-width: 92%; }
.cam__pill--good { background: rgba(16,120,80,.82); }
.cam__pill--warn { background: rgba(150,100,10,.82); }
.cam__quality { display: flex; gap: 5px; justify-content: center; }
.cam__qbar { width: 26px; height: 4px; border-radius: 2px; background: rgba(255,255,255,.28); }
.cam__qbar--on { background: #6ee7b7; }
.cam__bar { display: flex; align-items: center; justify-content: space-between;
            gap: 14px; padding: 16px 22px calc(16px + var(--sab));
            background: #000; color: #fff; }
.cam__shutter { width: 68px; height: 68px; border-radius: 50%; border: 4px solid #fff;
                background: rgba(255,255,255,.16); }
.cam__shutter[disabled] { opacity: .4; }
.cam__side { width: 46px; height: 46px; border-radius: 50%; border: 1px solid rgba(255,255,255,.3);
             background: rgba(255,255,255,.08); color: #fff; display: grid; place-items: center; }
.cam__side--wide { width: auto; padding: 0 14px; border-radius: 999px; font-size: .82rem; }

/* ------------------------------------------------------------------ sheets */

.sheet-host { position: fixed; inset: 0; z-index: 80; display: grid; align-items: end; }
.sheet-host__scrim { position: absolute; inset: 0; background: rgba(0,0,0,.4);
                     backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
                     animation: fade .2s ease; }
@keyframes fade { from { opacity: 0; } }
.sheet {
  position: relative; background: var(--surface);
  border-radius: 14px 14px 0 0;
  padding: 6px var(--pad) calc(var(--pad) + var(--sab));
  /* 100% of the (visual-viewport-sized) host, so the keyboard cannot bury it */
  max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  box-shadow: 0 -1px 0 var(--line-soft), 0 -20px 50px rgba(0,0,0,.35);
  animation: rise .34s cubic-bezier(.32,.72,0,1);
  will-change: transform;
}
@keyframes rise { from { transform: translateY(100%); } }
.sheet__grip { width: 36px; height: 5px; border-radius: 3px; background: var(--ink-3);
               opacity: .35; margin: 6px auto 10px; }
.sheet__title { font-size: 1.06rem; font-weight: 650; margin: 0 0 12px; text-align: center;
                letter-spacing: -.02em; }

@media (min-width: 640px) {
  .sheet-host { align-items: center; justify-items: center; }
  .sheet { border-radius: var(--r-xl); max-width: 520px; width: 100%; }
}

/* ------------------------------------------------------------------- toast */

.toast { position: fixed; left: 50%; bottom: calc(var(--tab-h) + var(--tab-safe) + 12px);
         transform: translateX(-50%); z-index: 95;
         background: var(--surface-3); color: var(--ink);
         border: 1px solid var(--line); border-radius: 999px;
         padding: 10px 18px; font-size: .86rem; font-weight: 560;
         box-shadow: var(--shadow); max-width: 90vw; text-align: center;
         animation: rise .18s ease; }

/* ------------------------------------------------------------------- lists */

.list { list-style: none; padding: 0; margin: 0; }
.list__item { display: flex; align-items: center; gap: 12px; padding: 12px 0;
              border-top: 0.5px solid var(--line-soft); width: 100%; text-align: left;
              background: none; border-left: 0; border-right: 0; border-bottom: 0;
              min-height: 48px; }
.list__item:active { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.list__item:first-child { border-top: 0; }
.list__thumb { width: 52px; height: 52px; border-radius: var(--r); flex: 0 0 auto;
               object-fit: cover; background: var(--surface-3); }
.list__thumb--dot { border-radius: 12px; border: 1px solid rgba(128,128,128,.25); }
.list__title { font-size: .92rem; font-weight: 600; }
.list__sub { font-size: .76rem; color: var(--ink-3); }
.list__chev { color: var(--ink-3); }

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 9px; }
.gitem { position: relative; border-radius: var(--r); overflow: hidden; background: var(--surface-2);
         border: 1px solid var(--line); text-align: left; padding: 0; }
.gitem img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.gitem__bar { display: flex; align-items: center; justify-content: space-between;
              gap: 6px; padding: 7px 9px; }
.gitem__n { font-size: .72rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis;
            white-space: nowrap; }
.gitem__s { font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.gitem__sel { position: absolute; top: 7px; right: 7px; width: 22px; height: 22px;
              border-radius: 50%; background: rgba(0,0,0,.45); display: grid; place-items: center;
              color: #fff; font-size: .7rem; }
.gitem[aria-pressed="true"] { outline: 2px solid var(--great); outline-offset: -2px; }

/* ----------------------------------------------------------------- drape UI */

.drape { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.drape__opt { border-radius: var(--r-lg); overflow: hidden; border: 2px solid transparent;
              background: var(--surface-2); padding: 0; }
.drape__opt[aria-pressed="true"] { border-color: var(--great); }
.drape__face { position: relative; aspect-ratio: .82; overflow: hidden; }
.drape__face img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.drape__cloth { position: absolute; left: 0; right: 0; bottom: 0; height: 34%; }
.drape__label { padding: 9px; font-size: .78rem; font-weight: 620; text-align: center; }

.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; border-radius: var(--r);
        overflow: hidden; height: 46px; }
.pair > div { height: 100%; }

/* ------------------------------------------------------------------ helpers */

.empty { text-align: center; padding: 44px 20px; color: var(--ink-3); }
.empty svg { width: 40px; height: 40px; margin-bottom: 12px; opacity: .5; }

.progress { height: 5px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.progress__fill { height: 100%; background: var(--great); transition: width .25s ease; }

.spinner { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--line);
           border-top-color: var(--ink); animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.banner { display: flex; gap: 10px; padding: 12px 14px; border-radius: var(--r);
          font-size: .85rem; line-height: 1.45; margin-bottom: 12px; }
.banner--info { background: color-mix(in srgb, var(--ok) 13%, transparent);
                color: color-mix(in srgb, var(--ok) 88%, var(--ink)); }
.banner--warn { background: color-mix(in srgb, var(--care) 14%, transparent);
                color: color-mix(in srgb, var(--care) 88%, var(--ink)); }
.banner--bad  { background: color-mix(in srgb, var(--bad) 14%, transparent);
                color: color-mix(in srgb, var(--bad) 88%, var(--ink)); }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; font-size: .82rem; }
.kv dt { color: var(--ink-3); }
.kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

.combo { display: flex; align-items: center; gap: 10px; padding: 10px 0;
         border-top: 1px solid var(--line-soft); }
.combo:first-of-type { border-top: 0; }
.combo__pair { display: flex; flex: 0 0 auto; border-radius: 10px; overflow: hidden;
               width: 62px; height: 38px; border: 1px solid rgba(128,128,128,.25); }
.combo__pair > i { flex: 1; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ------------------------------------------------- horizontal swatch strip */
/*  Two full palette grids stacked (top + bottom) made the try-on screen six
    screens tall on a phone. A single scrolling row keeps the preview and the
    score visible while you audition colours, which is the whole point. */
.swatch-strip {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 8px;
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.swatch-strip::-webkit-scrollbar { height: 4px; }
.swatch-strip::-webkit-scrollbar-thumb { background: var(--line); border-radius: 2px; }
.swatch-strip .swatch {
  flex: 0 0 auto; width: 66px; height: 66px; aspect-ratio: auto;
  scroll-snap-align: start;
}
.swatch-strip .swatch__name { font-size: .56rem; line-height: 1.15; }
