/* =====================================================================
   V&F Beauty Lounge · app
   Dark lacquer + brand gold. Italiana for the nameplate, Manrope for UI.
   ===================================================================== */
/* Italiana's ampersand is a stylised "Ɛ". This face covers ONLY U+0026 and is listed
   first, so every "&" is drawn by a classic serif while all other glyphs stay Italiana. */
@font-face {
  font-family: "VF Amp";
  src: local("Georgia"), local("Baskerville"), local("Times New Roman"), local("Noto Serif"), local("Droid Serif"), local("Tinos");
  unicode-range: U+26;
}
/* Italiana's figures are thin, uneven and sit awkwardly beside its letters, and they carry the
   biggest numbers in the app - the points balance, "4-in-1", "% off", the month heading. This face
   covers ONLY the digits and the thousands comma, so they are cut by a proper serif while every
   letter stays Italiana. Same technique as the ampersand above; if no local serif matches, the
   browser simply falls through to Italiana and nothing breaks. */
@font-face {
  font-family: "VF Num";
  src: local("Didot"), local("Bodoni 72"), local("Baskerville"), local("Georgia"), local("Times New Roman"),
       local("Liberation Serif"), local("Tinos"), local("Noto Serif"), local("Droid Serif"), local("DejaVu Serif");
  unicode-range: U+0030-0039, U+002C;
}

:root {
  color-scheme: dark;
  --lacquer: var(--th-app-d-lacquer, #141110);
  --lacquer-rgb: var(--th-app-d-lacquer-rgb, 20, 17, 16);
  --surface: var(--th-app-d-surface, #1c1917);
  --raised: var(--th-app-d-raised, #26221f);
  --soft: var(--th-app-d-soft, #302b27);
  --line: var(--th-app-d-line, #3a342f);
  --line-soft: var(--th-app-d-line-soft, #2b2622);
  /* --gold is the brand gold as a FILL (chips, tags, the chosen day) and carries --gold-ink on top;
     --gold-text is the same brand gold used as TEXT on the page ground. They part company in light
     mode, where a gold pale enough to sit under near-black ink is far too pale to read as a link. */
  --gold: var(--th-app-d-gold, #c1a15e);
  --gold-text: var(--th-app-d-gold-text, #c1a15e);
  --gold-light: var(--th-app-d-gold-light, #ddc88d);
  --gold-deep: var(--th-app-d-gold-deep, #8f6c2a);
  --gold-ink: var(--th-app-d-gold-ink, #1a1408);
  --gold-wash: var(--th-app-d-gold-wash, rgba(193, 161, 94, .10));
  --gold-wash-strong: var(--th-app-d-gold-wash-strong, rgba(193, 161, 94, .14));
  --silver-ink: var(--th-app-d-silver-ink, #d9dde3);
  --silver-line: var(--th-app-d-silver-line, #8d939c);
  --silver-bg: var(--th-app-d-silver-bg, var(--soft));
  --pending-ink: var(--th-app-d-pending-ink, #f0c674);
  --pending-bg: var(--th-app-d-pending-bg, rgba(240, 198, 116, .12));
  --linen: var(--th-app-d-linen, #f5f0e8);
  --muted: var(--th-app-d-muted, #a9a399);
  --faint: var(--th-app-d-faint, #6f6962);
  --success: var(--th-app-d-success, #8fd3a8);
  --danger: var(--th-app-d-danger, #f29b9b);
  --display: var(--th-font-display, "VF Amp", "VF Num", "Italiana", "Didot", "Bodoni MT", Georgia, serif);
  --ui: var(--th-font-ui, "Manrope", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
  /* Chips (NEW, NEW PRICES, LIMITED TIME, ONLY £70). On the dark theme these are light gold
     with near-black text. On the pale one the ask was white text, and white on the light gold
     is only 3.4:1 - too weak for 11px bold - so the chip itself goes a shade deeper there and
     the white sits on it at 6.3:1. */
  --chip-bg: var(--th-app-d-chip-bg, var(--gold)); --chip-ink: var(--th-app-d-chip-ink, var(--gold-ink));
  /* The flame keeps its own red in both themes; only the disc behind it follows the page,
     so the badge reads as a flame sitting on the tile rather than a coloured blob. */
  --flame: var(--th-app-d-flame, #ff5747);
  --r-sm: 10px; --r: 16px; --r-lg: 22px; --r-pill: 999px;
  --appbar-h: 56px; --tabs-h: 64px; --note-h: 0px;
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --ease: cubic-bezier(.2,.7,.2,1);
  --shadow: var(--th-app-d-shadow, 0 14px 40px rgba(0,0,0,.35));
}
/* Three states, one palette. :root above is the dark one and defines every colour, so nothing
   below invents a value that only exists in one theme.
     · Match my phone (no data-theme)  - the media query decides.
     · Light  (data-theme="light")     - the customer's choice, even on a dark phone.
     · Dark   (data-theme="dark")      - :root stands, and the media query is excluded.
   index.html stamps the attribute before the first paint so nothing flashes. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --lacquer: var(--th-app-l-lacquer, #f6f1ea); --lacquer-rgb: var(--th-app-l-lacquer-rgb, 246, 241, 234); --surface: var(--th-app-l-surface, #ffffff); --raised: var(--th-app-l-raised, #faf6f0); --soft: var(--th-app-l-soft, #efe8dd);
    --line: var(--th-app-l-line, #e2d9cb); --line-soft: var(--th-app-l-line-soft, #ece4d8);
    --linen: var(--th-app-l-linen, #1b1714); --muted: var(--th-app-l-muted, #6b645b); --faint: var(--th-app-l-faint, #948b80);
    /* The golds are re-cut for a pale ground. --gold stays light enough to carry --gold-ink on a
       filled chip (5.1:1); --gold-text (6.2:1 on white, 5.5:1 on the page) and --gold-light
       (7.2:1 on white) are the deeper golds that text uses. Same brand hue, readable weight. */
    --gold: var(--th-app-l-gold, #a88540); --gold-text: var(--th-app-l-gold-text, #7d5c14); --gold-light: var(--th-app-l-gold-light, #6f5310); --gold-deep: var(--th-app-l-gold-deep, #7a5b1f);
    --gold-wash: var(--th-app-l-gold-wash, rgba(168, 133, 64, .12)); --gold-wash-strong: var(--th-app-l-gold-wash-strong, rgba(168, 133, 64, .16));
    --silver-ink: var(--th-app-l-silver-ink, #5f6670); --silver-line: var(--th-app-l-silver-line, #aeb4bd); --silver-bg: var(--th-app-l-silver-bg, #eef0f3);
    --pending-ink: var(--th-app-l-pending-ink, #7a4f00); --pending-bg: var(--th-app-l-pending-bg, rgba(240, 198, 116, .28));
    --chip-bg: var(--th-app-l-chip-bg, #7a5b1f); --chip-ink: var(--th-app-l-chip-ink, #ffffff);
  --flame: var(--th-app-l-flame, #d93025);
    --flame: var(--th-app-l-flame, #d93025);
    --success: var(--th-app-l-success, #1b6b3d); --danger: var(--th-app-l-danger, #b3261e);
    --shadow: var(--th-app-l-shadow, 0 14px 40px rgba(60,40,10,.12));
  }
}
:root[data-theme="light"] {
  /* Exactly the tokens above, so a customer who chose Light gets it on a dark phone too. */
  color-scheme: light;
  --lacquer: var(--th-app-l-lacquer, #f6f1ea); --lacquer-rgb: var(--th-app-l-lacquer-rgb, 246, 241, 234); --surface: var(--th-app-l-surface, #ffffff); --raised: var(--th-app-l-raised, #faf6f0); --soft: var(--th-app-l-soft, #efe8dd);
  --line: var(--th-app-l-line, #e2d9cb); --line-soft: var(--th-app-l-line-soft, #ece4d8);
  --linen: var(--th-app-l-linen, #1b1714); --muted: var(--th-app-l-muted, #6b645b); --faint: var(--th-app-l-faint, #948b80);
  --gold: var(--th-app-l-gold, #a88540); --gold-text: var(--th-app-l-gold-text, #7d5c14); --gold-light: var(--th-app-l-gold-light, #6f5310); --gold-deep: var(--th-app-l-gold-deep, #7a5b1f);
  --gold-wash: var(--th-app-l-gold-wash, rgba(168, 133, 64, .12)); --gold-wash-strong: var(--th-app-l-gold-wash-strong, rgba(168, 133, 64, .16));
  --silver-ink: var(--th-app-l-silver-ink, #5f6670); --silver-line: var(--th-app-l-silver-line, #aeb4bd); --silver-bg: var(--th-app-l-silver-bg, #eef0f3);
  --pending-ink: var(--th-app-l-pending-ink, #7a4f00); --pending-bg: var(--th-app-l-pending-bg, rgba(240, 198, 116, .28));
  --chip-bg: var(--th-app-l-chip-bg, #7a5b1f); --chip-ink: var(--th-app-l-chip-ink, #ffffff);
  --success: var(--th-app-l-success, #1b6b3d); --danger: var(--th-app-l-danger, #b3261e);
  --shadow: var(--th-app-l-shadow, 0 14px 40px rgba(60,40,10,.12));
}

*, *::before, *::after { box-sizing: border-box; }
html { height: 100%; -webkit-text-size-adjust: 100%; }
body {
  /* Shared notification controls use the app's current light/dark palette. */
  --panel: var(--lacquer); --text: var(--linen);
  margin: 0; min-height: 100%;
  background: var(--lacquer); color: var(--linen);
  font: 15px/1.45 var(--ui); font-feature-settings: "tnum" 1, "ss01" 1;
  -webkit-font-smoothing: antialiased; overscroll-behavior-y: none;
  -webkit-tap-highlight-color: transparent;
}
img { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 6px; }
.screen:focus, .screen:focus-visible { outline: none; }   /* focus moves here for screen readers; the ring is wrong on a container */
.skip-link { position: absolute; left: -999px; top: 8px; background: var(--gold); color: var(--gold-ink); padding: 8px 12px; border-radius: 8px; z-index: 100; }
.skip-link:focus { left: 8px; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- app bar: back · logo · close ---------- */
.appbar {
  position: sticky; top: 0; z-index: 40;
  display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; align-items: center;
  height: calc(var(--appbar-h) + var(--sat)); padding: var(--sat) 6px 0;
  background: rgba(var(--lacquer-rgb), .88);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.appbar-back { grid-column: 1; }
.appbar-back[hidden] { display: grid; visibility: hidden; pointer-events: none; }
.appbar-brand { grid-column: 2; justify-self: center; min-width: 0; max-width: 100%; background: none; border: 0; padding: 4px 10px; border-radius: 12px; }
.appbar-brand:active { background: var(--soft); }
.appbar-brand .logo { height: 38px; width: auto; max-width: 100%; object-fit: contain; display: block; }
.monogram { font-family: var(--display); font-size: 30px; letter-spacing: .05em; color: var(--gold-text); line-height: 1; }
.appbar-actions { grid-column: 3; display: flex; align-items: center; flex-wrap: nowrap; gap: 2px; }
.appbar-actions > button { flex: 0 0 44px; }
.appbar .vf-notification-bell { background: transparent; color: var(--linen); border: 0; border-radius: 50%; }
.appbar .vf-notification-bell:hover { background: var(--soft); color: var(--gold-text); }
.appbar .vf-notification-badge { border-color: var(--lacquer); }
.appbar-close[hidden] { display: none; }
.icon-btn {
  width: 44px; height: 44px; border: 0; background: transparent; color: var(--linen);
  border-radius: 50%; display: grid; place-items: center; font-size: 20px;
  transition: background .15s var(--ease), transform .12s var(--ease);
}
.icon-btn:active { transform: scale(.94); background: var(--soft); }
.publication-status { margin: 0; padding: 10px 16px; background: var(--raised); color: var(--gold-text); font-size: 13px; text-align: center; border-bottom: 1px solid var(--line-soft); }
.publication-status[hidden] { display: none; }

/* ---------- progress (checkout sequence) ---------- */
.progress { position: sticky; top: calc(var(--appbar-h) + var(--sat)); z-index: 39; background: var(--lacquer); padding: 10px 16px 26px; }
.progress-track { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; gap: 6px; }
.progress-track li { height: 3px; border-radius: 2px; background: var(--line); position: relative; }
.progress-track li.done { background: var(--gold-deep); }
.progress-track li.current { background: var(--gold); }
.progress-track li.current::after {
  content: attr(data-label); position: absolute; top: 8px; left: 0;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--gold-text); white-space: nowrap;
}
.progress:not([hidden]) + .screen { padding-top: 6px; }

/* ---------- screen ---------- */
.screen {
  padding: 8px 16px calc(var(--tabs-h) + var(--note-h) + var(--sab) + 24px);
  max-width: 720px; margin: 0 auto; min-height: 60vh;
  animation: screen-in .26s var(--ease);
}
.screen.back { animation-name: screen-back; }
@keyframes screen-in   { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }
@keyframes screen-back { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -.01em; }
.title { font-family: var(--display); font-weight: 400; font-size: 34px; line-height: 1.05; letter-spacing: .01em; }
.title small { display: block; font-family: var(--ui); font-size: 13px; font-weight: 500; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; margin-bottom: 8px; }
.lede { color: var(--muted); margin: 6px 0 0; }
.section { margin-top: 28px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.section-head h2 { font-size: 17px; }
.section-head a, .link { color: var(--gold-text); font-weight: 600; font-size: 14px; }
.eyebrow { font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--gold-text); }

/* ---------- rails ---------- */
.rail { display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory; padding: 4px 16px 10px; margin: 0 -16px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; flex: 0 0 auto; }

/* ---------- banners ---------- */
.banners { margin: 8px -16px 0; }
.banner-rail { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; gap: 0; }
.banner-rail::-webkit-scrollbar { display: none; }
.banner { flex: 0 0 100%; scroll-snap-align: center; padding: 0 16px; }
.banner-card {
  position: relative; display: block; aspect-ratio: 16 / 10; border-radius: var(--r-lg); overflow: hidden;
  background: var(--surface); box-shadow: var(--shadow); isolation: isolate;
}
/* The owner uploads pictures of any shape: cover crops to the 16:10 box so nothing spills or leaves a gap. */
.banner-card img { width: 100%; height: 100%; object-fit: cover; object-position: center; transform: scale(1.02); transition: transform .5s var(--ease); }
.banner-card:active img { transform: scale(1.06); }
/* The salon uploads its own photographs and some are bright, high-key studio shots, so the white
   title has to survive being laid over near-white pixels. Two scrims do it without turning dark
   photos to mud: a broad, gentle falloff over the picture (nothing at all across the top third),
   and a second one on .banner-copy that is tied to the copy itself, so a two-line title carries its
   own darkness up with it. Composited they put >5:1 under the smallest line even over pure white. */
.banner-card::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(16,13,12,0) 30%, rgba(16,13,12,.30) 58%, rgba(16,13,12,.62) 82%, rgba(16,13,12,.88) 100%); }
/* No picture (or one that will not load): a plain grey box looks broken, so show the nameplate on purpose. */
.banner-card.no-img { background: linear-gradient(150deg, var(--raised), var(--surface)); }
.banner-card.no-img::before { content: attr(data-brand); position: absolute; inset: 0 0 34% 0; display: grid; place-items: center; font-family: var(--display); font-size: 56px; color: var(--gold-text); opacity: .62; }
.banner-copy {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; padding: 30px 18px 16px; color: #f5f0e8;
  background: linear-gradient(180deg, rgba(16,13,12,0) 0, rgba(16,13,12,.62) 30px, rgba(16,13,12,.74) 100%);
  text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
/* Fixed light golds, not the token: this text always sits on the dark scrim, in either theme. */
.banner-copy .eyebrow { color: #f0dfb4; }
.banner-copy h3 { font-family: var(--display); font-weight: 400; font-size: 28px; line-height: 1.05; margin-top: 4px; }
.banner-copy p { margin: 4px 0 0; font-size: 13px; color: rgba(245,240,232,.92); }
.banner-dots { display: flex; justify-content: center; gap: 6px; margin-top: 10px; }
.banner-dots span { width: 6px; height: 6px; border-radius: 50%; background: var(--line); transition: all .2s; }
.banner-dots span.on { width: 18px; border-radius: 3px; background: var(--gold); }

/* ---------- category tiles ---------- */
.tile { width: 92px; text-align: center; background: none; border: 0; padding: 0; color: var(--linen); }
.tile-img { width: 76px; height: 76px; margin: 0 auto 8px; border-radius: 50%; overflow: hidden; background: var(--surface); border: 1px solid var(--line); position: relative; transition: transform .15s var(--ease), border-color .15s; }
.tile-img img { width: 100%; height: 100%; object-fit: cover; }
.tile-img i { position: absolute; inset: 0; display: grid; place-items: center; font-size: 26px; color: var(--gold-text); }
.tile:active .tile-img { transform: scale(.95); }
.tile.on .tile-img { border-color: var(--gold); box-shadow: 0 0 0 2px var(--lacquer), 0 0 0 3px var(--gold); }
.tile-name { font-size: 12.5px; font-weight: 600; line-height: 1.2; }
.tile-count { display: block; font-size: 11px; color: var(--muted); font-weight: 500; margin-top: 1px; }

/* ---------- treatment types: circular rail ---------- */
.subrail { display: flex; gap: 14px; overflow-x: auto; padding: 6px 16px 12px; margin: 4px -16px 0; scrollbar-width: none; scroll-snap-type: x proximity; }
.subrail::-webkit-scrollbar { display: none; }
.sub { flex: 0 0 auto; width: 74px; background: none; border: 0; padding: 0; color: var(--linen); text-align: center; scroll-snap-align: start; }
.sub-img { width: 62px; height: 62px; margin: 0 auto 6px; border-radius: 50%; overflow: hidden; background: var(--surface); border: 1px solid var(--line); display: grid; place-items: center; font-family: var(--display); font-size: 24px; color: var(--gold-text); transition: transform .15s var(--ease), box-shadow .15s; }
.sub-img img { width: 100%; height: 100%; object-fit: cover; }
.sub.on .sub-img { border-color: var(--gold); box-shadow: 0 0 0 2px var(--lacquer), 0 0 0 3px var(--gold); }
.sub:active .sub-img { transform: scale(.94); }
.sub-name { font-size: 12px; font-weight: 600; line-height: 1.15; }
.sub-count { display: block; font-size: 11px; color: var(--muted); }
.tile-badge { position: absolute; top: -4px; left: 50%; transform: translateX(-50%); white-space: nowrap; font-size: 9px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; background: var(--chip-bg); color: var(--chip-ink); padding: 3px 6px; border-radius: var(--r-pill); }
.tile-img { position: relative; overflow: visible; }
.tile-hot { position: absolute; bottom: -2px; left: -2px; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; background: var(--surface); border: 1px solid var(--gold-deep); color: var(--flame); font-size: 14px; box-shadow: 0 2px 8px rgba(0,0,0,.22); }
.tile-img > img { border-radius: 50%; }

/* ---------- shelf: a scrolling row of cards, with arrows where there is a mouse ---------- */
.shelf { position: relative; }
.shelf-arrow {
  position: absolute; top: calc(50% - 26px); z-index: 3; display: none;
  width: 40px; height: 40px; border-radius: 50%; place-items: center;
  background: var(--surface); color: var(--linen); border: 1px solid var(--line);
  box-shadow: 0 6px 20px rgba(0,0,0,.22); font-size: 17px;
  transition: opacity .15s var(--ease), transform .12s var(--ease);
}
.shelf-arrow.prev { left: -18px; }
.shelf-arrow.next { right: -18px; }
.shelf-arrow:hover { transform: scale(1.06); }
.shelf-arrow:disabled { opacity: 0; pointer-events: none; }
/* A phone has a finger; arrows there would be clutter over the cards. They appear with the
   desktop layout, and never when the row already fits and there is nothing to scroll. */
@media (min-width: 1100px) { .shelf-arrow { display: grid; } .shelf.no-scroll .shelf-arrow { display: none; } }

/* ---------- bundles: offers + packages ---------- */
.bundle-card { width: 220px; text-align: left; padding: 0; color: var(--linen); display: flex; flex-direction: column; }
.bundle-card .thumb { aspect-ratio: 16 / 10; background: var(--raised); overflow: hidden; position: relative; display: grid; place-items: center; color: var(--gold-text); font-size: 30px; }
.bundle-card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.bundle-card .thumb .tag { position: absolute; top: 10px; left: 10px; box-shadow: 0 2px 10px rgba(0,0,0,.35); }
.bundle-card .body { padding: 10px 12px 12px; display: grid; gap: 4px; }
.bundle-card .name { font-weight: 700; font-size: 14px; line-height: 1.25; }
.bundle-card .meta { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; color: var(--muted); gap: 8px; }
.bundle-card .price { font-size: 16px; }
.includes { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
.includes li { display: grid; grid-template-columns: 20px 1fr; gap: 8px; align-items: start; font-size: 14px; }
.includes li i { color: var(--success); }
.tier { display: grid; grid-template-columns: 1fr auto auto; gap: 10px; align-items: center; padding: 12px 4px; border-bottom: 1px solid var(--line-soft); }
.tier:last-child { border-bottom: 0; }
.tier .tier-identity { display: flex; align-items: center; gap: 10px; min-width: 0; }
.tier-thumb { display: grid; flex: 0 0 48px; width: 48px; height: 56px; overflow: hidden; border-radius: 8px; place-items: center; background: var(--raised); color: var(--gold-text); }
.tier-thumb img { width: 100%; height: 100%; object-fit: cover; }
.tier-copy { min-width: 0; overflow-wrap: anywhere; }
.tier-copy strong { display: block; font-size: 14px; }
.tier-copy .tag { margin: 4px 0; font-size: 9px; }
.tier-copy .link { display: inline-block; padding: 5px 0; font-size: 12px; }
@media (max-width: 480px) { .tier { grid-template-columns: minmax(0, 1fr) auto; } .tier .tier-identity { grid-column: 1 / -1; } .tier .p { text-align: left; } }

.tier .n { font-weight: 700; }
.tier .n small { display: block; font-weight: 500; color: var(--muted); font-size: 12px; }
.tier .p { text-align: right; }
.tier .p small { display: block; font-size: 11px; color: var(--muted); }

/* ---------- cards ---------- */
.card { background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); overflow: hidden; }
.svc-card { width: 168px; display: flex; flex-direction: column; text-align: left; padding: 0; color: var(--linen); }
.svc-card .thumb { aspect-ratio: 4 / 3; background: var(--raised); display: grid; place-items: center; color: var(--gold-text); font-size: 28px; overflow: hidden; }
.svc-card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.svc-card .body { padding: 10px 12px 12px; display: grid; gap: 4px; }
.svc-card .name { font-weight: 600; font-size: 14px; line-height: 1.25; }
.svc-card .meta { display: flex; justify-content: space-between; align-items: center; font-size: 13px; color: var(--muted); }
.price { color: var(--gold-light); font-weight: 700; font-variant-numeric: tabular-nums; }
.tag { display: inline-block; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--chip-ink); background: var(--chip-bg); padding: 3px 8px; border-radius: var(--r-pill); }
.offer-card { width: 240px; padding: 16px; display: grid; gap: 6px; background: linear-gradient(160deg, var(--raised), var(--surface)); }
.offer-card .big { font-family: var(--display); font-size: 30px; line-height: 1; color: var(--gold-text); }
.offer-card p { margin: 0; color: var(--muted); font-size: 13px; }

/* ---------- lists / rows ---------- */
.row {
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center;
  padding: 14px 4px; border-bottom: 1px solid var(--line-soft); text-align: left; width: 100%; background: none; border-left: 0; border-right: 0; border-top: 0; color: var(--linen);
}
.row:last-child { border-bottom: 0; }
.row .row-name { font-weight: 600; }
.row .row-sub { color: var(--muted); font-size: 13px; margin-top: 2px; display: flex; gap: 10px; flex-wrap: wrap; }
.row .row-sub i { color: var(--gold-text); margin-right: 3px; }
.row-actions { display: flex; align-items: center; gap: 10px; }
.chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px 16px 10px; margin: 0 -16px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
.chip { flex: 0 0 auto; border: 1px solid var(--line); background: var(--surface); color: var(--linen); padding: 8px 14px; border-radius: var(--r-pill); font-weight: 600; font-size: 13px; transition: all .15s var(--ease); }
.chip.on { background: var(--gold); border-color: var(--gold); color: var(--gold-ink); }
.chip:active { transform: scale(.96); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 20px; border-radius: 14px; border: 1px solid transparent;
  font-weight: 700; font-size: 15px; letter-spacing: .01em; transition: transform .12s var(--ease), background .15s, opacity .15s;
}
.btn:active { transform: scale(.98); }
.btn[disabled] { opacity: .45; cursor: not-allowed; transform: none; }
.btn-gold { background: var(--th-gold-gradient, linear-gradient(135deg, #d2b675 0%, #c1a15e 52%, #a4823a 100%)); color: var(--gold-ink); box-shadow: 0 8px 24px rgba(193,161,94,.22); }
.btn-ghost { background: transparent; border-color: var(--line); color: var(--linen); }
.btn-soft { background: var(--soft); color: var(--linen); }
.btn-block { width: 100%; }
.btn-sm { min-height: 36px; padding: 0 14px; font-size: 13px; border-radius: 10px; }
.add-btn { min-width: 72px; }
.add-btn.on { background: var(--soft); color: var(--gold-light); border-color: var(--gold-deep); }
.text-btn { background: none; border: 0; color: var(--gold-text); font-weight: 600; padding: 6px 2px; }

/* ---------- forms ---------- */
.field { display: grid; gap: 6px; margin-top: 14px; }
.field label { font-size: 13px; font-weight: 600; color: var(--muted); }
.input, .field input, .field select, .field textarea {
  width: 100%; min-height: 50px; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line);
  background: var(--surface); color: var(--linen); font-size: 16px; transition: border-color .15s, box-shadow .15s;
}
.field textarea { min-height: 96px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(193,161,94,.18); }
.field .hint { font-size: 12px; color: var(--muted); }   /* --faint is 2.4:1 on the light page: unreadable for a real instruction */
.segmented { display: grid; grid-auto-flow: column; gap: 6px; padding: 4px; background: var(--surface); border: 1px solid var(--line); border-radius: 14px; }
.segmented button { border: 0; background: transparent; color: var(--muted); padding: 10px 6px; border-radius: 10px; font-weight: 600; font-size: 14px; }
.segmented button.on { background: var(--soft); color: var(--linen); }
.msg { border-radius: 12px; padding: 12px 14px; font-size: 14px; margin-top: 14px; }
.msg-error { background: rgba(242,155,155,.12); color: var(--danger); border: 1px solid rgba(242,155,155,.3); }
.msg-ok { background: rgba(143,211,168,.12); color: var(--success); border: 1px solid rgba(143,211,168,.3); }

/* ---------- calendar ---------- */
.cal { margin-top: 10px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.cal-head h2 { font-family: var(--display); font-weight: 400; font-size: 28px; letter-spacing: .01em; }
.cal-nav { display: flex; gap: 6px; }
.cal-nav .icon-btn { width: 40px; height: 40px; border: 1px solid var(--line); background: var(--surface); }
.cal-nav .icon-btn[disabled] { opacity: .3; }
.cal-dow { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-day {
  aspect-ratio: 1; border-radius: 12px; border: 1px solid var(--line-soft); background: var(--surface); color: var(--linen);
  font-weight: 600; font-size: 15px; font-variant-numeric: tabular-nums; display: grid; place-items: center; position: relative;
  transition: transform .12s var(--ease), background .15s, color .15s;
}
.cal-day:active { transform: scale(.94); }
.cal-day.blank { visibility: hidden; }
/* 'ended' is today with every remaining start time gone by - the API sends it, and without this
   rule it painted as an ordinary, tappable day. */
.cal-day.past, .cal-day.closed, .cal-day.full, .cal-day.ended { color: var(--faint); background: transparent; border-color: transparent; cursor: not-allowed; }
.cal-day.full { text-decoration: line-through; }
.cal-day.loading { color: transparent; background: transparent; border-color: var(--line-soft); cursor: progress; pointer-events: none; }
.cal-grid > .msg { grid-column: 1 / -1; }
.cal-day.few::after { content: ""; position: absolute; bottom: 6px; width: 5px; height: 5px; border-radius: 50%; background: var(--gold); }
.cal-day.today { box-shadow: inset 0 0 0 1px var(--gold-deep); }
/* A full or elapsed today is still today, but the gold ring is the app's "tap me" mark everywhere
   else. Swap it for a plain dashed outline: still findable, no longer an invitation. */
.cal-day.today.past, .cal-day.today.closed, .cal-day.today.full, .cal-day.today.ended {
  box-shadow: none; border: 1px dashed var(--line); color: var(--faint);
}
.cal-day.on { background: var(--gold); border-color: var(--gold); color: var(--gold-ink); box-shadow: 0 6px 18px rgba(193,161,94,.25); }
.cal-day.on::after { background: var(--gold-ink); }
.cal-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 14px; font-size: 12px; color: var(--muted); }
.cal-legend span::before { content: ""; display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; border: 1px solid var(--line); }
.cal-legend .l-open::before { background: var(--surface); }
.cal-legend .l-few::before { background: var(--gold); border-color: var(--gold); }
.cal-legend .l-none::before { background: transparent; border-color: var(--faint); }
.cal-picked { margin-top: 14px; padding: 12px 14px; border-radius: 12px; background: var(--surface); border: 1px solid var(--line-soft); display: flex; justify-content: space-between; align-items: center; }
.cal-picked strong { color: var(--gold-light); }

/* ---------- time grid ---------- */
.dates { display: flex; gap: 8px; overflow-x: auto; padding: 4px 16px 10px; margin: 0 -16px; scrollbar-width: none; scroll-snap-type: x proximity; }
.dates::-webkit-scrollbar { display: none; }
.date {
  flex: 0 0 64px; scroll-snap-align: start; border: 1px solid var(--line); background: var(--surface); color: var(--linen);
  border-radius: 14px; padding: 10px 6px; display: grid; gap: 2px; text-align: center; transition: all .15s var(--ease);
}
.date .dow { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.date .dom { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.date .mon { font-size: 11px; color: var(--muted); }
.date.on { background: var(--gold); border-color: var(--gold); color: var(--gold-ink); }
.date.on .dow, .date.on .mon { color: rgba(26,20,8,.7); }
.date.closed { opacity: .38; }
.month-label { font-family: var(--display); font-size: 24px; margin: 12px 0 6px; }
.times { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 8px; }
@media (min-width: 420px) { .times { grid-template-columns: repeat(4, 1fr); } }
.time {
  min-height: 46px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); color: var(--linen);
  font-weight: 600; font-variant-numeric: tabular-nums; transition: all .15s var(--ease); position: relative;
}
.time.on { background: var(--gold); border-color: var(--gold); color: var(--gold-ink); }
.time[disabled] { opacity: .32; text-decoration: line-through; cursor: not-allowed; }
.time-group { margin-top: 18px; }
.time-group h3 { font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }

/* ---------- the appointment note: a compact bar that expands into the cart ---------- */
.note {
  position: fixed; left: 0; right: 0; bottom: calc(var(--tabs-h) + var(--sab)); z-index: 45;
  margin: 0 auto; max-width: 720px; padding: 0 10px 8px;
  animation: note-in .3s var(--ease);
}
@keyframes note-in { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.note-card {
  background: var(--raised); border: 1px solid var(--line); border-top: 2px solid var(--gold);
  border-radius: 18px; box-shadow: var(--shadow); padding: 8px 12px 10px;
}
.note-bar { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px; }
.note-summary {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 10px; min-width: 0;
  background: none; border: 0; color: var(--linen); text-align: left; padding: 6px 2px; border-radius: 10px;
}
.note-summary:active { background: var(--soft); }
.note-summary .chev { color: var(--gold-text); font-size: 18px; transition: transform .2s var(--ease); }
.note.expanded .note-summary .chev { transform: rotate(180deg); }
.note-summary .sum { display: grid; line-height: 1.15; min-width: 0; }
.note-summary .sum strong { font-size: 18px; color: var(--gold-light); font-variant-numeric: tabular-nums; }
/* "about 1 hr 30 min · 3 treatments" does not fit one line beside the button on a 375px phone:
   let it wrap onto a second line rather than cutting the word "treatments" in half. */
.note-summary .sum span { font-size: 12px; color: var(--muted); margin-top: 2px; }
.note-summary .sum span i { color: var(--gold-text); }
.note-lines { display: none; }
.note.expanded .note-lines { display: grid; gap: 6px; max-height: 38vh; overflow: auto; padding: 6px 2px 10px; margin-bottom: 8px; border-bottom: 1px solid var(--line-soft); font-size: 14px; }
.note-line { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; align-items: center; }
.note-line em { font-style: normal; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.note-line small { color: var(--muted); font-size: 12px; margin-left: 6px; }
.note-line .rm { width: 30px; height: 30px; font-size: 14px; color: var(--muted); }
.note .btn { min-height: 46px; padding: 0 18px; border-radius: 12px; white-space: nowrap; }

/* ---------- appointment card (confirmation) ---------- */
.appt {
  position: relative; margin-top: 18px; padding: 24px 22px 22px; border-radius: 22px; overflow: hidden;
  background: linear-gradient(160deg, #1f1b18, #141110 70%); border: 1px solid #3a342f; box-shadow: var(--shadow);
  color: #f5f0e8;                                  /* fixed dark card: never inherit light-mode text */
  animation: appt-in .5s var(--ease);
}
@keyframes appt-in { from { transform: translateY(26px) scale(.98); opacity: 0; } to { transform: none; opacity: 1; } }
.appt::before {
  content: ""; position: absolute; left: 22px; right: 22px; top: 78px; height: 1px;
  background: linear-gradient(90deg, #8f6c2a, #ddc88d, #8f6c2a);   /* dark-palette golds: the card is always dark */
  transform-origin: left; animation: rule-draw .9s .25s var(--ease) both;
}
@keyframes rule-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.appt .monogram { font-size: 34px; color: #c1a15e; }
.appt .appt-head { display: flex; justify-content: space-between; align-items: baseline; }
.appt .ref { font-size: 12px; letter-spacing: .14em; color: #a9a399; font-variant-numeric: tabular-nums; }
.appt .when { margin-top: 26px; font-family: var(--display); font-size: 30px; line-height: 1.05; color: #f5f0e8; }
.appt .when small { display: block; font-family: var(--ui); font-size: 14px; color: #ddc88d; margin-top: 6px; letter-spacing: .02em; }
.appt .lines { margin-top: 18px; display: grid; gap: 6px; font-size: 14px; }
.appt .total { margin-top: 14px; padding-top: 12px; border-top: 1px dashed #3a342f; display: flex; justify-content: space-between; font-weight: 700; }
.appt .total strong { color: #ddc88d; }
.appt .fine { margin-top: 16px; font-size: 12px; color: #a9a399; line-height: 1.5; }

/* ---------- misc ---------- */
.stack { display: grid; gap: 10px; }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.hero-detail { margin: 0 -16px; aspect-ratio: 16 / 9; background: var(--surface); overflow: hidden; display: grid; place-items: center; color: var(--gold-text); font-size: 44px; }
.hero-detail img { width: 100%; height: 100%; object-fit: cover; }
.kv { display: flex; gap: 18px; color: var(--muted); font-size: 14px; margin-top: 10px; }
.kv i { color: var(--gold-text); margin-right: 5px; }
.empty { text-align: center; padding: 40px 18px; color: var(--muted); }
.empty i { font-size: 40px; color: var(--gold-text); display: block; margin-bottom: 10px; }
.empty h3 { color: var(--linen); margin-bottom: 6px; }
.skeleton { background: linear-gradient(90deg, var(--surface) 25%, var(--soft) 50%, var(--surface) 75%); background-size: 200% 100%; animation: shimmer 1.3s infinite; border-radius: 12px; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.visit { display: grid; grid-template-columns: 56px 1fr auto; gap: 12px; align-items: center; padding: 14px; }
.visit .cal { text-align: center; background: var(--raised); border-radius: 12px; padding: 8px 4px; border: 1px solid var(--line-soft); }
.visit .cal b { display: block; font-size: 20px; line-height: 1; }
.visit .cal small { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
/* An appointment that did not happen. It stays in the list - people look for it, and they want to see what
   became of the points they had spent on it - but it must never be mistaken for one that is still standing. */
.visit-off { border-style: dashed; }
.visit-off .cal { opacity: .55; }
.visit-note { display: flex; align-items: flex-start; gap: 6px; margin-top: 5px; font-size: 12.5px; line-height: 1.4; color: var(--danger); }
.visit-note i { font-size: 13px; flex: none; margin-top: 1px; }
.status { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; padding: 3px 8px; border-radius: var(--r-pill); background: var(--soft); color: var(--muted); }
.status.confirmed { color: var(--success); background: rgba(143,211,168,.12); }
.status.cancelled { color: var(--danger); background: rgba(242,155,155,.12); }
.divider { height: 1px; background: var(--line-soft); margin: 18px 0; }

/* ---------- bottom tabs ---------- */
.tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; height: calc(var(--tabs-h) + var(--sab));
  padding: 6px 8px var(--sab); display: grid; grid-auto-flow: column;
  background: rgba(var(--lacquer-rgb), .92); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line-soft);
}
.tab { display: grid; place-items: center; gap: 3px; color: var(--muted); font-size: 11px; font-weight: 600; border-radius: 12px; transition: color .15s; }
.tab[hidden] { display: none; }
.tab i { font-size: 21px; transition: transform .15s var(--ease); }
.tab.on { color: var(--gold-text); }
.tab.on i { transform: translateY(-1px); }
.tab:active i { transform: scale(.9); }

/* ---------- toast ---------- */
.toast {
  position: fixed; left: 50%; top: calc(var(--appbar-h) + var(--sat) + 8px); transform: translateX(-50%);
  background: #1f6b3f; color: #eaf7ee; padding: 7px 14px; border-radius: var(--r-pill); font-weight: 600; font-size: 13px;
  box-shadow: 0 6px 18px rgba(0,0,0,.25); z-index: 60; max-width: calc(100% - 32px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: toast-in .18s var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, -6px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* =====================================================================
   TABLET and DESKTOP
   ---------------------------------------------------------------------
   This app was written phone-first because the website embeds it in a
   470px modal, and that is still exactly what the modal gets: these are
   media queries, so inside the iframe they read the modal's own width
   and never fire. Opened directly at /booking/app/ on a real screen it
   now lays itself out for that screen instead of floating a phone panel
   in the middle of a 1600px monitor.

     phone   (<760px)   unchanged: bottom tabs, horizontal rails
     tablet  (760-1099) wider measure, rails become wrapping grids
     desktop (>=1100)   left navigation rail, full grid, basket becomes
                        a floating card instead of a bottom bar
   ===================================================================== */

/* ---------- tablet ---------- */
@media (min-width: 760px) {
  .screen { max-width: 940px; padding-left: 28px; padding-right: 28px; }
  .note { max-width: 940px; padding-left: 28px; padding-right: 28px; }
  .times { grid-template-columns: repeat(5, 1fr); }

  /* Two kinds of shelf once there is room. The categories are a fixed set of eight, so they
     wrap into a grid and the whole choice is on screen at once. Offers, packages and most
     loved are open-ended lists that belong on a shelf you move through - the way an app does
     it - so those keep scrolling and gain arrows instead (see .shelf below). */
  .rail-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 14px; overflow-x: visible; margin: 0; padding: 4px 0 10px;
  }
  .rail-grid > * { width: auto; scroll-snap-align: none; }
  .rail-slide { margin: 0; padding: 4px 0 12px; gap: 16px; }
  .rail-slide .svc-card { width: 212px; }
  .rail-slide .bundle-card { width: 262px; }
  .subrail, .chips, .dates { padding-left: 0; padding-right: 0; margin-left: 0; margin-right: 0; }
  .banners { margin-left: 0; margin-right: 0; }
  .banner { padding: 0; }
  /* 16:10 is a phone shape. Held to it at 900px wide the hero is 560px tall and pushes
     everything else off the screen, so it widens as the screen does. */
  .cat-grid { grid-template-columns: repeat(3, 1fr); gap: 14px; }
  /* The circle is a fixed 76px on a phone because that is all the room there is. Given a
     290px column it has to grow, or the row reads as eight small dots adrift in white. */
  .tile { width: auto; }
  .tile-img { width: 100%; max-width: 128px; height: auto; aspect-ratio: 1; }
  .tile-name { font-size: 14px; }
  .tile-count { font-size: 12px; }
  /* The flame and the NEW chip were drawn for a 76px circle, where the flame was about a third
     of it. Growing the circle without growing them halves that share and they read as missing,
     which is why they vanished when the tiles got bigger. Same badge, same colours - just kept
     in proportion to the tile it sits on. */
  .tile-hot { width: 38px; height: 38px; font-size: 20px; bottom: -3px; left: -3px; }
  .tile-badge { font-size: 11px; padding: 4px 9px; top: -6px; }
  .banner-card { aspect-ratio: 21 / 9; }
  .banner-copy h3 { font-size: 32px; }
}

/* ---------- desktop ---------- */
@media (min-width: 1100px) {
  :root { --tabs-h: 0px; --appbar-h: 66px; }

  /* The four destinations move into the top bar. A bottom bar stretched over a wide screen
     leaves them an inch apart with nothing in between, and a standing rail down the side
     spends 230-odd pixels of the window on four links. In the header they cost nothing and
     read the way a header is expected to read. The nav is a separate element from .appbar in
     the markup, so it is laid over it rather than nested in it - the bar carries the blur and
     the border, the nav sits on top with no background of its own. */
  .appbar { padding-left: 20px; padding-right: 20px; }
  .appbar-brand { justify-self: start; }
  .appbar-actions { gap: 4px; }

  .tabs {
    top: 0; bottom: auto; left: auto; right: 176px;
    width: auto; height: calc(var(--appbar-h) + var(--sat));
    padding: var(--sat) 0 0; gap: 4px;
    grid-auto-flow: column; align-items: center;
    background: none; backdrop-filter: none; -webkit-backdrop-filter: none; border-top: 0;
  }
  .tab {
    grid-auto-flow: column; place-items: center; gap: 8px;
    padding: 9px 15px; border-radius: 999px; font-size: 14px;
    transition: background .15s var(--ease), color .15s var(--ease);
  }
  .tab i { font-size: 17px; }
  .tab:hover { color: var(--linen); background: var(--soft); }
  .tab.on { background: var(--soft); color: var(--gold-text); }
  .tab.on i { transform: none; }

  .screen { max-width: 1160px; padding-left: 36px; padding-right: 36px; padding-bottom: calc(var(--note-h) + 48px); }
  .progress { padding-left: 36px; padding-right: 36px; }

  .banner-card { aspect-ratio: auto; height: 380px; width: 100%; }
  .banner-copy { padding: 34px 26px 20px; }
  .banner-copy h3 { font-size: 34px; }
  .cat-grid { grid-template-columns: repeat(4, 1fr); gap: 18px; }
  .tile-img { max-width: 156px; }
  .tile-name { font-size: 15px; }
  .tile-hot { width: 46px; height: 46px; font-size: 24px; bottom: -4px; left: -4px; }
  .tile-badge { font-size: 12px; padding: 5px 11px; top: -8px; }
  .rail-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 18px; }
  .rail-slide { gap: 18px; }
  .rail-slide .svc-card { width: 240px; }
  .rail-slide .bundle-card { width: 292px; }
  .times { grid-template-columns: repeat(7, 1fr); }

  /* A booking step asks for one decision. Given the full 1280px measure the calendar sat in
     the top-left corner of an empty field, which reads as a broken page rather than a calm
     one; the step gets a narrower centred column and the widgets grow to fill it. The
     progress bar is shown on booking steps and only on booking steps, so it is what marks
     them out - no class plumbing needed. */
  /* Account is a form and a handful of settings. Stretched to 1160px an email field is a
     metre of empty box with a cursor in it, so this page keeps a reading measure and centres
     - the same reasoning as a booking step, for the same reason. */
  /* The account page as two columns: what the account is, and how this device behaves. A single
     660px ribbon centred on a 1440px screen reads as a phone app that nobody finished. */
  .pg-account { max-width: 1040px; margin-left: auto; margin-right: auto; }
  .pg-account > div:last-child { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,360px);
    gap: 30px; align-items: start; }
  .acct-side > .section:first-child { margin-top: 0; }
  .acct-side { position: sticky; top: 84px; }

  /* Visits is a list, and a list of appointment cards one-per-row across a wide screen wastes
     the width it was given. Two columns, and the points card stays full width above them. */
  .pg-visits .stack { grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
  /* The points card is the hero of this screen and spans the measure; the signed-out prompt
     is a short piece of copy with one button and should not. */
  .pg-visits > div > .card:not(.points-hero) { max-width: 660px; }

  body:has(.progress:not([hidden])) .screen { max-width: 880px; }
  .cal-grid, .cal-dow { max-width: 620px; margin-left: auto; margin-right: auto; }
  .cal-day { font-size: 15px; }

  /* The basket was a bar pinned across the bottom of a phone. With a mouse and
     a wide screen it becomes a card in the corner, out of the way of the page
     but never off it. */
  .note {
    left: auto; right: 28px; bottom: 28px; width: 380px; max-width: none;
    margin: 0; padding: 0;
  }
  .note-card { box-shadow: 0 24px 60px rgba(0,0,0,.55); }

}

/* Very wide: stop the measure growing past comfortable reading length. */
@media (min-width: 1500px) {
  .screen { max-width: 1280px; }
  .rail-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
}

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

/* ---------- account · points · sign-in ---------- */
.points-hero { display: block; padding: 16px 18px 18px; margin-top: 14px; color: var(--linen); background: linear-gradient(150deg, var(--raised) 0%, var(--surface) 70%); border-color: var(--gold-deep); position: relative; overflow: hidden; }
.points-hero::after { content: "★"; position: absolute; right: -6px; bottom: -22px; font-size: 96px; color: rgba(193,161,94,.08); pointer-events: none; }
.points-hero.compact { padding: 12px 16px 14px; }
.ph-top { display: flex; justify-content: space-between; align-items: center; }
.ph-balance { margin-top: 8px; font-family: var(--display); font-size: 40px; line-height: 1; letter-spacing: .01em; }
.ph-balance strong { font-weight: 400; color: var(--gold-light); font-variant-numeric: tabular-nums; }
.ph-balance span { font-family: var(--ui); font-size: 15px; color: var(--muted); }
.points-hero.compact .ph-balance { font-size: 30px; margin-top: 4px; }
.ph-value { margin-top: 6px; font-size: 13px; color: var(--muted); }
.ph-pending { color: var(--gold-text); }
.ph-tier { margin-top: 14px; }
.ph-tier small { display: block; margin-top: 6px; font-size: 12px; color: var(--muted); }
.tier-bar { height: 5px; border-radius: 3px; background: var(--line); overflow: hidden; }
.tier-bar span { display: block; height: 100%; background: linear-gradient(90deg, var(--gold-deep), var(--gold-light)); border-radius: 3px; transition: width .6s var(--ease); }
.tier-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; padding: 4px 9px; border-radius: var(--r-pill); background: var(--soft); color: var(--muted); border: 1px solid var(--line); }
.tier-badge.silver { color: var(--silver-ink); border-color: var(--silver-line); background: var(--silver-bg); }
.tier-badge.gold { color: var(--gold-ink); background: var(--gold); border-color: var(--gold); }
.tier-badge i { font-size: 11px; }
.menu { display: grid; gap: 8px; }
.menu-row, .nudge { display: grid; grid-template-columns: 24px 1fr 16px; gap: 12px; align-items: center; padding: 14px 16px; background: var(--surface); border: 1px solid var(--line-soft); border-radius: var(--r); color: var(--linen); }
.menu-row > i:first-child, .nudge > i:first-child { color: var(--gold-text); font-size: 19px; }
.menu-row > i:last-child, .nudge > i:last-child { color: var(--faint); }
.menu-row strong, .nudge strong { display: block; font-size: 15px; }
.menu-row small, .nudge small { display: block; color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.menu-row:active, .nudge:active { background: var(--raised); }
.nudge { margin-top: 14px; border-color: var(--gold-deep); }
.stat { padding: 14px 16px; }
.stat strong { display: block; font-size: 22px; color: var(--gold-light); font-variant-numeric: tabular-nums; }
.stat small { color: var(--muted); font-size: 12px; }
.guide { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.guide li { display: grid; grid-template-columns: 20px 1fr; gap: 10px; align-items: start; }
.guide li i { color: var(--gold-text); margin-top: 3px; }
.guide strong { display: block; font-size: 14.5px; }
.guide span { display: block; color: var(--muted); font-size: 13px; margin-top: 2px; line-height: 1.45; }
.tier-row { display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--line-soft); }
.tier-row:last-child { border-bottom: 0; }
.tier-row.on { background: linear-gradient(90deg, rgba(193,161,94,.08), transparent); margin: 0 -14px; padding: 12px 14px; }
.tier-row small { display: block; color: var(--muted); font-size: 12px; }
.tier-row .mult { color: var(--gold-light); font-weight: 700; font-variant-numeric: tabular-nums; }
.ledger-row { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--line-soft); }
.ledger-row:last-child { border-bottom: 0; }
.ledger-row strong { display: block; font-size: 14px; font-weight: 600; }
.ledger-row small { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
.ledger-row .pts { text-align: right; font-weight: 700; color: var(--success); font-variant-numeric: tabular-nums; }
.ledger-row .pts.neg { color: var(--danger); }
.ledger-row .pts small { color: var(--muted); font-weight: 500; }
.ledger-row.pending .pts { color: var(--gold-text); }
.ledger-row.void { opacity: .55; }
.ledger-row.void .pts { text-decoration: line-through; color: var(--muted); }
.pts-line { display: flex; align-items: center; gap: 5px; margin-top: 4px; font-size: 12.5px; font-weight: 600; color: var(--gold-light); }
.pts-line.muted { color: var(--muted); font-weight: 500; }
.pts-line i { font-size: 12px; }
.status.completed { color: var(--gold-light); background: var(--gold-wash-strong); }
.status.no_show { color: var(--danger); background: rgba(242,155,155,.12); }
.status.pending { color: var(--pending-ink); background: var(--pending-bg); }
.code-input { width: 100%; min-height: 62px; text-align: center; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 30px; letter-spacing: .42em; padding-left: .42em; border-radius: 14px; border: 1px solid var(--line); background: var(--surface); color: var(--linen); }
.code-input:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(193,161,94,.18); }
.text-btn.btn-block { display: block; width: 100%; text-align: center; margin-top: 10px; }
.two .text-btn { text-align: center; }
.switch-row { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: start; margin-top: 16px; padding: 12px 14px; border: 1px solid var(--line-soft); border-radius: 12px; background: var(--surface); }
.switch-row input { width: 22px; height: 22px; accent-color: var(--gold); margin-top: 2px; }
.switch-row strong { display: block; font-size: 14px; }
.switch-row small { display: block; color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.device-row { display: grid; grid-template-columns: 24px 1fr auto; gap: 12px; align-items: center; padding: 12px 14px; }
.device-row > i { color: var(--gold-text); font-size: 20px; }
.device-row strong { display: flex; align-items: center; gap: 8px; font-size: 14px; flex-wrap: wrap; }
.device-row small { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
.tag-soft { background: var(--soft); color: var(--gold-light); font-size: 9.5px; }
.welcome-card { padding: 14px 16px; margin-bottom: 4px; border-color: var(--gold-deep); }
.welcome-card p { margin: 6px 0 0; color: var(--muted); font-size: 14px; }
.fineprint { font-size: 12px; color: var(--muted); margin-top: 16px; text-align: center; line-height: 1.5; }
.is-busy { opacity: .6; pointer-events: none; }

/* ---------- appearance: match my phone / light / dark ---------- */
.theme-choice { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 4px; margin-top: 10px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px; }
.theme-choice button {
  border: 1px solid transparent; background: transparent; color: var(--muted); padding: 9px 4px; border-radius: 10px;
  font-family: inherit; font-weight: 600; font-size: 12.5px; line-height: 1.2; display: grid; justify-items: center; gap: 5px;
  transition: background .15s var(--ease), color .15s, transform .12s var(--ease);
}
.theme-choice button i { font-size: 17px; }
.theme-choice button.on { background: var(--soft); border-color: var(--line); color: var(--linen); }
.theme-choice button.on i { color: var(--gold-text); }
.theme-choice button:active { transform: scale(.97); }
/* points at the review step */
.redeem { padding: 14px 16px; margin-top: 10px; border-color: var(--gold-deep); }
.redeem-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.redeem-head strong { font-size: 15px; }
.redeem-head small { display: block; color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.stepper { display: grid; grid-template-columns: 44px 1fr 44px; gap: 8px; align-items: center; margin-top: 12px; }
.stepper button { min-height: 44px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); color: var(--linen); font-size: 20px; font-weight: 700; }
.stepper button[disabled] { opacity: .35; }
.stepper output { text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.stepper output small { display: block; font-weight: 500; color: var(--muted); font-size: 12px; }
.redeem input[type=range] { width: 100%; margin-top: 10px; accent-color: var(--gold); }
.earn-line { display: flex; align-items: center; gap: 8px; margin-top: 12px; padding: 10px 14px; border-radius: 12px; background: var(--gold-wash); color: var(--gold-light); font-size: 13.5px; font-weight: 600; }
.earn-line i { font-size: 14px; }
.earn-line a { color: inherit; text-decoration: underline; }

/* ---------- install sheet ----------
   A bottom sheet on a phone, a centred card on anything larger. It sits above the tab bar and
   the appointment bar, because it is asking for a decision and half-covered dialogs get dismissed
   by accident. */
.ins-wrap {
  position: fixed; inset: 0; z-index: 200; display: grid; align-items: end; justify-items: center;
  background: rgba(0,0,0,.55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0; transition: opacity .22s var(--ease);
  padding: 0 0 env(safe-area-inset-bottom, 0px);
}
.ins-wrap.open { opacity: 1; }
.ins-sheet {
  position: relative; width: 100%; max-width: 460px;
  background: var(--surface); color: var(--linen);
  border: 1px solid var(--line); border-bottom: 0;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding: 22px 20px calc(18px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -20px 60px rgba(0,0,0,.5);
  transform: translateY(14px); transition: transform .26s var(--ease);
}
.ins-wrap.open .ins-sheet { transform: none; }
@media (min-width: 700px) {
  .ins-wrap { align-items: center; padding: 24px; }
  .ins-sheet { border: 1px solid var(--line); border-radius: var(--r-lg); padding-bottom: 20px; }
}
.ins-x { position: absolute; top: 8px; right: 8px; width: 38px; height: 38px; font-size: 15px; color: var(--muted); }
.ins-head { display: grid; grid-template-columns: 56px 1fr; gap: 14px; align-items: center; padding-right: 34px; }
.ins-logo { border-radius: 13px; border: 1px solid var(--line); }
.ins-head h2 { font-family: var(--display); font-weight: 400; font-size: 22px; line-height: 1.1; }
.ins-head p { margin: 5px 0 0; font-size: 13.5px; color: var(--muted); line-height: 1.45; }

.ins-perks { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 11px; }
.ins-perks li { display: grid; grid-template-columns: 22px 1fr; gap: 10px; align-items: center; font-size: 14px; }
.ins-perks i { color: var(--gold-text); font-size: 16px; }

/* iOS: the steps ARE the feature, so they get room and a number each. */
.ins-steps { margin-top: 16px; position: relative; }
.ins-steps ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 13px; }
.ins-steps li { display: grid; grid-template-columns: 26px 1fr; gap: 11px; align-items: start; font-size: 14.5px; line-height: 1.35; }
.ins-steps .n {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--gold); color: var(--gold-ink); font-size: 13px; font-weight: 800;
}
.ins-steps small { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.ins-share { display: inline-grid; place-items: center; width: 22px; height: 22px; vertical-align: -5px; color: #0a84ff; }
.ins-share svg { width: 100%; height: 100%; }
/* A pointer towards the real toolbar, which is at the bottom on iPhone and the top on iPad. */
.ins-arrow { display: grid; place-items: center; font-size: 22px; color: var(--gold-text); margin-top: 10px; animation: ins-nudge 1.6s ease-in-out infinite; }
.ins-arrow.up { margin: 0 0 10px; }
@keyframes ins-nudge { 0%,100% { transform: translateY(0); opacity: .75 } 50% { transform: translateY(4px); opacity: 1 } }
.ins-arrow.up { animation-name: ins-nudge-up; }
@keyframes ins-nudge-up { 0%,100% { transform: translateY(0); opacity: .75 } 50% { transform: translateY(-4px); opacity: 1 } }

.ins-note { display: grid; grid-template-columns: 20px 1fr; gap: 11px; margin-top: 16px; font-size: 13.5px; line-height: 1.5; }
.ins-note i { color: var(--gold-text); font-size: 17px; }
.ins-note b { display: block; margin-bottom: 3px; }
.ins-note span { color: var(--muted); }
.ins-actions { display: grid; gap: 8px; margin-top: 18px; }
@media (prefers-reduced-motion: reduce) { .ins-arrow { animation: none; } }
