/* ============================================================
   AeroCut design system — v3 "NIGHT SHOP"
   Black leather, chrome, brass and a neon sign at 9pm.

   Same class contracts as v2 — restyle freely, rename never.

   THE RULE THAT SHAPES THE PALETTE: blue is a GUEST, not the host.
   v2 was navy-on-navy-on-navy and read cold and corporate. Here the
   room is warm near-black, the metal is brass, the action is neon
   red, and the only true blue left in the system is one stripe of
   the barber pole — where it's earned.

   The moves:
   · a fixed color field that DRIFTS on its own and SHIFTS with scroll
   · surfaces are warm charcoal glass with hairline chrome edges
   · RED is neon: actions and selections glow like a lit sign
   · money is BRASS in display numerals — the loudest thing on screen
   · icons are heavy-stroked; the active tab lights from BELOW
   ============================================================ */

:root {
  /* --- the room --- */
  --bg: #0A0807;                 /* warm near-black, not blue-black */
  --graphite: #221E1B;           /* chrome-lit charcoal — replaces navy for surfaces */
  --graphite-lift: #322C28;
  --card: rgba(28, 24, 22, .84);
  --glass: rgba(14, 12, 11, .76);
  --glass-brd: rgba(255, 255, 255, .13);

  /* --- ink: warm, high contrast --- */
  --ink: #FCFAF7;                /* warm white — brighter than v2's blue-white */
  --ink-2: #A99E95;              /* warm gray; v2's #8FA0BE was the biggest blue offender */
  --line: rgba(255, 255, 255, .10);
  --line-strong: rgba(255, 255, 255, .20);

  /* --- the neon --- */
  --red: #FF3B2F;
  --red-hot: #FF5C4D;
  --red-deep: #C4241A;
  --red-soft: rgba(255, 59, 47, .16);

  /* --- the brass: money, premium, founding --- */
  --gold: #F2C75C;
  --gold-deep: #C9932E;
  --gold-soft: rgba(242, 199, 92, .15);

  /* --- status --- */
  --ok: #3ECF8E;
  --ok-soft: rgba(62, 207, 142, .16);
  --warn: #E8A33D;
  --warn-soft: rgba(232, 163, 61, .16);
  /* Text sitting ON a tinted pill needs its own token. On dark it lifts
     BRIGHTER than the base colour; on light it must go darker instead —
     the dark-mode values measured 1.35:1 on paper, which is invisible. */
  --ok-ink: #6BE3AE;
  --red-ink: #FF8377;
  --warn-ink: #F3BE6E;

  /* The ONLY blue in the system. It exists for one reason: a barber pole
     with no blue stripe isn't a barber pole. */
  --pole-blue: #2F6FD9;

  /* v2 compat — .badge.navy, .done-mark.alt and friends still ask for these
     names. Repointed at brass/graphite so nothing renders blue by accident. */
  --navy: var(--graphite);
  --navy-deep: #16120F;
  --navy-soft: rgba(242, 199, 92, .12);
  --navy-ghost: rgba(255, 255, 255, .06);
  --steel: var(--gold);

  --font-display: "Clash Display", "Avenir Next", system-ui, sans-serif;
  --font-ui: "Switzer", "Segoe UI", system-ui, sans-serif;

  --r-lg: 20px;
  --r: 16px;
  --r-sm: 12px;

  --e1: 0 1px 2px rgba(0, 0, 0, .45), 0 6px 20px rgba(0, 0, 0, .38);
  --e2: 0 2px 4px rgba(0, 0, 0, .50), 0 12px 32px rgba(0, 0, 0, .45);
  --e3: 0 4px 10px rgba(0, 0, 0, .55), 0 22px 52px rgba(0, 0, 0, .62);
  --glow-red: 0 0 0 1px rgba(255, 59, 47, .34), 0 6px 26px rgba(255, 59, 47, .48);
  --glow-gold: 0 0 0 1px rgba(242, 199, 92, .30), 0 6px 24px rgba(242, 199, 92, .34);
  --glow-navy: 0 6px 22px rgba(0, 0, 0, .5);

  --spring: cubic-bezier(.34, 1.56, .64, 1);
  --ease-out: cubic-bezier(.22, 1, .36, 1);

  --tap: 48px;
  --pad: 16px;
  --max: 560px;
}

/* ============================================================
   DAY SHOP — the light theme.
   Not "the dark one with the colors flipped": the same room with the
   lights on and the blinds open. Warm paper instead of grey office
   stock, the SAME neon red and brass so the brand never changes
   temperature, and ink that is warm near-black rather than blue-black.

   Only the tokens change. Every component below is written once and
   works in both — that is the whole reason the palette lives up here.
   ============================================================ */
:root[data-theme="light"] {
  --bg: #F6F2ED;                 /* warm paper */
  --graphite: #FFFFFF;
  --graphite-lift: #FFFFFF;
  --card: rgba(255, 255, 255, .88);
  --glass: rgba(255, 252, 248, .82);
  --glass-brd: rgba(26, 20, 16, .10);

  --ink: #1A1410;                /* warm near-black */
  --ink-2: #6E635A;              /* warm grey — never blue */
  --line: rgba(26, 20, 16, .11);
  --line-strong: rgba(26, 20, 16, .20);

  /* Red and gold hold their identity but darken enough to pass contrast
     on paper — neon that reads at night is too pale to read at noon. */
  --red: #D62D1F;
  --red-hot: #E84032;
  --red-deep: #A81D12;
  --red-soft: rgba(214, 45, 31, .10);

  --gold: #8A6516;               /* brass, darkened for legibility on light */
  --gold-deep: #6B4E0F;
  --gold-soft: rgba(138, 101, 22, .11);

  --ok: #0F7B57;
  --ok-soft: rgba(15, 123, 87, .11);
  --warn: #9A6A11;
  --warn-soft: rgba(154, 106, 17, .12);
  --ok-ink: #0B6144;
  --red-ink: #A81D12;
  --warn-ink: #7C5509;

  --navy: var(--graphite);
  --navy-deep: #1A1410;
  --navy-soft: rgba(138, 101, 22, .11);
  --navy-ghost: rgba(26, 20, 16, .05);
  --steel: var(--gold);

  --e1: 0 1px 2px rgba(26, 20, 16, .05), 0 4px 16px rgba(26, 20, 16, .07);
  --e2: 0 2px 4px rgba(26, 20, 16, .07), 0 10px 28px rgba(26, 20, 16, .11);
  --e3: 0 4px 8px rgba(26, 20, 16, .09), 0 18px 44px rgba(26, 20, 16, .16);
  --glow-red: 0 0 0 1px rgba(214, 45, 31, .22), 0 6px 20px rgba(214, 45, 31, .30);
  --glow-gold: 0 0 0 1px rgba(138, 101, 22, .22), 0 6px 18px rgba(138, 101, 22, .22);
  --glow-navy: 0 4px 14px rgba(26, 20, 16, .16);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-ui);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.45;
  min-height: 100dvh;
  background: var(--bg);
}

/* ---------- the color field ----------
   Two fixed layers behind everything. Fixed (not background-attachment,
   which iOS Safari ignores) so the page scrolls OVER the room.

   Layer 1 drifts on its own — a slow ember breathing at the top right —
   and rakes as you scroll: feel.js writes --sy (0→1 through the page).

   ⚠️ PERFORMANCE — READ BEFORE CHANGING THIS.
   --sy used to be interpolated INTO the gradient centres (`at calc(104% -
   var(--sy) * 26%) ...`). That changes the gradient's DEFINITION, so every
   scrolled frame regenerated three full-viewport radial gradients on the
   main thread — the single most expensive thing on the page, and the reason
   scrolling and swiping felt laggy on real phones.

   Now the centres are STATIC (set to the midpoint of the old travel, so the
   room looks the same at rest) and --sy drives `translate` instead. Both
   `translate` and `transform` are GPU-composited: the layer MOVES rather
   than being redrawn, and the scroll costs a style recalc on one element
   instead of a full-viewport repaint.

   The trade is honest and deliberate: the three lights used to drift in
   different directions, and now they move as one rigid field. The feel —
   light raking across the room as you scroll — is intact.

   🔑 Two rules if this is ever touched again:
   · NEVER put var(--sy) inside `background` — that is the original bug.
   · The overscan (`inset`) must stay larger than the largest translate,
     or the page edge shows through at the extremes of the scroll. */
body::before {
  content: ""; position: fixed; inset: -12%; z-index: -2;
  background:
    radial-gradient(900px 560px at 91% 8%,   rgba(255, 59, 47, .22), transparent 58%),
    radial-gradient(780px 620px at 2% 29%,   rgba(242, 199, 92, .11), transparent 60%),
    radial-gradient(900px 720px at 50% 103%, rgba(255, 59, 47, .12), transparent 62%),
    var(--bg);
  /* The scroll rake — composited. Separate from `transform` below so the
     two motions compose instead of overwriting each other. */
  translate: calc(var(--sy, 0) * -2.5%) calc(var(--sy, 0) * 6%);
  animation: emberbreath 24s ease-in-out infinite alternate;
  will-change: transform;
}
/* The idle drift. Was `background-position`, which forced a repaint on every
   frame of a permanently-running 24s animation. Now a composited transform. */
@keyframes emberbreath {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-1.4%, .9%, 0) scale(1.035); }
}

/* Daylight: the same three lights, dialled right down. On paper these read
   as warmth in the corners rather than neon — push them any harder and the
   page looks tinted instead of lit. The scroll rake still works. */
:root[data-theme="light"] body::before {
  background:
    radial-gradient(900px 560px at 91% 8%,   rgba(214, 45, 31, .09), transparent 58%),
    radial-gradient(780px 620px at 2% 29%,   rgba(138, 101, 22, .07), transparent 60%),
    radial-gradient(900px 720px at 50% 103%, rgba(214, 45, 31, .05), transparent 62%),
    var(--bg);
}

/* Layer 2: grain + the 45° clipper-guard pinstripe, straight off the logo. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .055 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(-45deg, rgba(255, 255, 255, .015) 0 1px, transparent 1px 9px);
}

::selection { background: rgba(255, 59, 47, .48); color: #fff; }

h1, h2, h3, .stat .v, .svc .price {
  font-family: var(--font-display);
  letter-spacing: .01em;
}

.wrap { max-width: var(--max); margin: 0 auto; padding: var(--pad); padding-bottom: 118px; }

/* ---------- header ---------- */
/* ⚠️ PERFORMANCE: this used to carry `backdrop-filter: blur(18px)`. The appbar
   and the tab dock are the only two chrome elements on screen at ALL times, so
   between them the compositor was re-blurring two full-width strips on every
   scrolled frame. The dock keeps its blur — frosted glass floating over the
   work is the signature of the design. The appbar gives its up, and loses
   almost nothing: --glass is already 76–86% opaque, so at these values the
   blur behind it was barely legible.

   The gradient trick paints the semi-transparent glass over an opaque --bg,
   which yields the same colour the blur version resolved to, in every theme,
   without needing a second token per theme. */
.appbar {
  position: sticky; top: 0; z-index: 30;
  background: linear-gradient(var(--glass), var(--glass)), var(--bg);
  border-bottom: 1px solid var(--line);
}
.appbar-inner {
  max-width: var(--max); margin: 0 auto;
  display: flex; align-items: center; gap: 10px;
  padding: 10px var(--pad);
}
.logo-mark {
  width: 40px; height: 40px; flex: none;
  display: block; object-fit: contain;
  /* The mark is flat navy (#002255), drawn for light pages — on Night Shop it
     vanishes. brightness(0) invert(1) re-inks it white; the drop-shadow sits
     AFTER the inversion so the glow stays red instead of flipping to cyan. */
  filter: brightness(0) invert(1) drop-shadow(0 0 11px rgba(255, 59, 47, .45));
}
/* On paper the mark needs no help — it was drawn in navy for exactly this. */
:root[data-theme="light"] .logo-mark {
  filter: drop-shadow(0 2px 5px rgba(26, 20, 16, .22));
}
.appbar h1 {
  font-size: 22px; font-weight: 700; letter-spacing: .015em;
  color: var(--ink);
}
.appbar .sub {
  font-size: 11px; color: var(--ink-2); margin-top: -3px;
  letter-spacing: .08em; text-transform: uppercase; font-weight: 600;
}
.appbar .spacer { flex: 1; }

/* ---------- cards ---------- */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--e1), inset 0 1px 0 rgba(255, 255, 255, .06);
  padding: var(--pad);
  margin-bottom: 14px;
  position: relative;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.card h2 {
  font-size: 17px; font-weight: 600; margin-bottom: 10px;
  color: var(--ink);
  display: flex; align-items: center; gap: 8px;
}
.card h2 .ic { color: var(--gold); }

@media (prefers-reduced-motion: no-preference) {
  .wrap > .card, .wrap > .stat-grid, .wrap > .btn-row, #today-content > *,
  #appts-content > *, #clients-content > *, #more-content > * {
    animation: rise .42s var(--ease-out) both;
  }
  .wrap > :nth-child(2), #today-content > :nth-child(2), #more-content > :nth-child(2) { animation-delay: .05s; }
  .wrap > :nth-child(3), #today-content > :nth-child(3), #more-content > :nth-child(3) { animation-delay: .10s; }
  .wrap > :nth-child(4), #today-content > :nth-child(4), #more-content > :nth-child(4) { animation-delay: .15s; }
  .wrap > :nth-child(5), #today-content > :nth-child(5), #more-content > :nth-child(5) { animation-delay: .20s; }
  .wrap > :nth-child(n+6), #today-content > :nth-child(n+6), #more-content > :nth-child(n+6) { animation-delay: .24s; }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.section-label {
  font-size: 11.5px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-2);
  margin: 18px 0 8px;
}
.muted { color: var(--ink-2); font-size: 14px; }
.small { font-size: 12.5px; }

/* ---------- icons: GUARD FADE set ----------
   Blade-sharp: square caps, mitered joins.
   ⚠ No stroke-width here, ever — each icon bakes its own layer weights
   (primary 2.2 / secondary 2 / whisper 1.8) as path attributes, and a CSS
   width would flatten every fade layer to one uniform stroke. */
.ic {
  width: 1.2em; height: 1.2em; flex: none;
  stroke: currentColor; fill: none;
  stroke-linecap: square; stroke-linejoin: miter;
  vertical-align: -.22em;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--tap);
  padding: 0 18px;
  border: 0; border-radius: 14px;
  background: linear-gradient(180deg, var(--graphite-lift), var(--graphite) 60%);
  color: var(--ink);
  font-size: 15.5px; font-weight: 600; font-family: var(--font-ui);
  cursor: pointer; text-decoration: none;
  box-shadow: var(--e1), inset 0 1px 0 rgba(255, 255, 255, .12);
  transition: transform .16s var(--spring), box-shadow .16s, filter .16s;
  -webkit-tap-highlight-color: transparent;
  position: relative;
}
.btn:active {
  transform: translateY(1px) scale(.97);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .12);
  filter: brightness(1.18);
}
.btn.block { display: flex; width: 100%; }
/* the lit sign */
.btn.red {
  background: linear-gradient(180deg, var(--red-hot), var(--red-deep) 64%);
  color: var(--on-accent, #fff);
  box-shadow: var(--glow-red), inset 0 1px 0 rgba(255, 255, 255, .3);
  text-shadow: 0 1px 10px rgba(0, 0, 0, .3);
}
.btn.red:active { box-shadow: 0 2px 12px rgba(255, 59, 47, .4), inset 0 1px 0 rgba(255, 255, 255, .3); }
.btn.ghost {
  background: transparent; color: var(--ink);
  border: 1.5px solid var(--line-strong);
  box-shadow: none;
}
.btn.ghost:active { border-color: var(--gold); background: var(--navy-ghost); }
.btn.soft {
  background: rgba(255, 255, 255, .08); color: var(--ink);
  border: 1px solid var(--glass-brd);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  backdrop-filter: blur(10px) saturate(1.2);
  box-shadow: var(--e1), inset 0 1px 0 rgba(255, 255, 255, .12);
}
.btn.soft:active { box-shadow: none; }
.btn.sm { min-height: 40px; padding: 0 14px; font-size: 14px; border-radius: 12px; }
.btn:disabled { opacity: .45; pointer-events: none; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- forms ---------- */
label.field { display: block; margin-bottom: 12px; }
label.field > span {
  display: block; font-size: 12.5px; font-weight: 600;
  letter-spacing: .05em;
  color: var(--ink-2); margin-bottom: 6px;
}
/* Field surfaces are tokens, not literals — a hardcoded black here left
   light mode with black input boxes. --field-* flip with the theme. */
:root { --field: rgba(0, 0, 0, .42); --field-on: rgba(0, 0, 0, .6); --scheme: dark; }
:root[data-theme="light"] { --field: #FFFFFF; --field-on: #FFFFFF; --scheme: light; }

input, select, textarea {
  width: 100%; min-height: var(--tap);
  padding: 10px 14px;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--field); color: var(--ink);
  font-size: 16px; font-family: var(--font-ui);
  transition: border-color .15s, box-shadow .15s;
  color-scheme: var(--scheme);      /* native date/time pickers match the room */
}
input::placeholder, textarea::placeholder { color: var(--ink-2); opacity: .72; }
textarea { min-height: 84px; resize: vertical; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--red);
  box-shadow: 0 0 0 4px var(--red-soft);
  background: var(--field-on);
}
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* toggle */
.toggle { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; }
.toggle .lbl { font-weight: 600; font-size: 15px; }
.toggle .hint { font-size: 12.5px; color: var(--ink-2); }
.switch { position: relative; width: 50px; height: 30px; flex: none; }
.switch input { position: absolute; opacity: 0; inset: 0; margin: 0; min-height: 0; cursor: pointer; z-index: 2; }
.switch .track {
  position: absolute; inset: 0; border-radius: 999px;
  background: rgba(255, 255, 255, .18); transition: background .2s;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .5);
}
/* An off switch has to look OFF. White-on-white doesn't. */
:root[data-theme="light"] .switch .track {
  background: rgba(26, 20, 16, .18);
  box-shadow: inset 0 1px 3px rgba(26, 20, 16, .22);
}
.switch .track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .6);
  transition: left .2s var(--spring);
}
.switch input:checked + .track { background: var(--ok); }
.switch input:checked + .track::after { left: 23px; }

/* ---------- chips / badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 700; letter-spacing: .03em;
  padding: 4px 11px; border-radius: 999px;
  border: 1px solid transparent;
}
.badge.ok   { background: var(--ok-soft);   color: var(--ok-ink);   border-color: rgba(62, 207, 142, .42); }
.badge.warn { background: var(--warn-soft); color: var(--warn-ink); border-color: rgba(232, 163, 61, .42); }
.badge.red  { background: var(--red-soft);  color: var(--red-ink);  border-color: rgba(255, 59, 47, .45); }
.badge.navy { background: var(--gold-soft); color: var(--gold); border-color: rgba(242, 199, 92, .38); }

/* ---------- list rows ---------- */
.rowitem {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.rowitem:last-child { border-bottom: 0; }
.rowitem .grow { flex: 1; min-width: 0; }
.rowitem .title { font-weight: 600; font-size: 15.5px; color: var(--ink); }
.rowitem .sub { font-size: 13px; color: var(--ink-2); }
.avatar {
  width: 44px; height: 44px; border-radius: 14px; flex: none;
  background: linear-gradient(145deg, var(--graphite-lift), #171310);
  color: var(--gold);
  display: grid; place-items: center;
  font-family: var(--font-display);
  font-weight: 700; font-size: 16px;
  border: 1px solid rgba(242, 199, 92, .22);
  box-shadow: var(--e1), inset 0 1px 0 rgba(255, 255, 255, .1);
  position: relative; overflow: hidden;
}
/* blade glint, echoing the shears */
.avatar::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(-45deg, transparent 46%, rgba(255, 255, 255, .16) 50%, transparent 54%);
}

/* ---------- floating glass dock ---------- */
.tabbar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 40;
  padding: 0 14px calc(12px + env(safe-area-inset-bottom));
  pointer-events: none;
  background: linear-gradient(to top, rgba(10, 8, 7, .96), transparent);
}
.tabbar-inner {
  max-width: calc(var(--max) - 28px); margin: 0 auto;
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  pointer-events: auto;
  background: var(--glass);
  /* Kept — this is the signature element. Trimmed from 20px because blur cost
     scales with radius and the dock recomposites on every scrolled frame;
     at this size the difference is invisible and the saving is not. */
  -webkit-backdrop-filter: blur(12px) saturate(1.25);
  backdrop-filter: blur(12px) saturate(1.25);
  border: 1px solid var(--glass-brd);
  border-radius: 22px;
  box-shadow: var(--e3), inset 0 1px 0 rgba(255, 255, 255, .12);
  overflow: hidden;
}
.tab {
  min-height: 58px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em;
  color: var(--ink-2);
  background: none; border: 0; cursor: pointer; font-family: var(--font-ui);
  -webkit-tap-highlight-color: transparent;
  transition: color .18s;
  position: relative;
}
.tab .ico { line-height: 1; display: grid; place-items: center; position: relative; }
.tab .ico .ic { width: 24px; height: 24px; transition: transform .22s var(--spring); }
.tab.active { color: var(--ink); }
.tab.active .ico .ic { transform: translateY(-1px) scale(1.1); }
/* the icon lights up from behind, like a sign switching on */
.tab.active .ico::before {
  content: ""; position: absolute; width: 34px; height: 34px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 59, 47, .38), transparent 70%);
}
/* THE BAR SITS UNDER THE ICON — a lit strip on the floor, not a ceiling rail */
.tab.active::after {
  content: ""; position: absolute; bottom: 7px;
  width: 22px; height: 3px; border-radius: 2px;
  background: var(--red);
  box-shadow: 0 0 12px rgba(255, 59, 47, .95), 0 0 3px rgba(255, 59, 47, 1);
  animation: dockdot .3s var(--spring) both;
}
@keyframes dockdot { from { transform: scaleX(.2); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- slot grid ---------- */
.slot-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }
.slot {
  min-height: var(--tap);
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .06); color: var(--ink);
  font-size: 15px; font-weight: 600; font-family: var(--font-ui);
  cursor: pointer;
  transition: transform .16s var(--spring), box-shadow .16s, border-color .16s;
}
.slot:active { transform: scale(.95); }
.slot.sel {
  background: linear-gradient(180deg, var(--red-hot), var(--red-deep));
  border-color: transparent; color: var(--on-accent, #fff);
  box-shadow: var(--glow-red);
  transform: scale(1.04);
}

/* day strip */
.day-strip { display: flex; gap: 8px; overflow-x: auto; padding: 4px 2px 6px; scrollbar-width: none; }
.day-strip::-webkit-scrollbar { display: none; }
.day {
  flex: none; width: 64px; min-height: 74px;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .06); color: var(--ink);
  font-family: var(--font-ui); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  transition: transform .16s var(--spring), box-shadow .16s;
}
.day:active { transform: scale(.95); }
.day .dow { font-size: 11px; font-weight: 700; color: var(--ink-2); text-transform: uppercase; letter-spacing: .07em; }
.day .num { font-size: 23px; font-weight: 700; font-family: var(--font-display); }
.day .mon { font-size: 11px; color: var(--ink-2); }
.day.sel {
  background: linear-gradient(180deg, var(--red-hot), var(--red-deep));
  border-color: transparent;
  box-shadow: var(--glow-red);
  transform: scale(1.04);
}
.day.sel .dow, .day.sel .num, .day.sel .mon { color: var(--on-accent, #fff); }
.day.closed { opacity: .35; }

/* service cards — the price is BRASS and proud */
.svc {
  width: 100%; text-align: left; font-family: var(--font-ui); cursor: pointer;
  display: flex; align-items: center; gap: 12px;
  padding: 14px 15px; margin-bottom: 9px;
  background: var(--card); border: 1.5px solid var(--line); border-radius: var(--r);
  box-shadow: var(--e1), inset 0 1px 0 rgba(255, 255, 255, .05);
  color: var(--ink);
  transition: transform .16s var(--spring), border-color .16s, box-shadow .16s;
}
.svc:active { transform: scale(.98); }
.svc.sel {
  border-color: rgba(255, 59, 47, .6);
  background: linear-gradient(180deg, rgba(255, 59, 47, .14), rgba(255, 59, 47, .05)), var(--card);
  box-shadow: var(--glow-red);
}
.svc .nm { font-weight: 600; font-size: 15.5px; }
.svc .meta { font-size: 13px; color: var(--ink-2); }
.svc .price {
  margin-left: auto; font-weight: 700; font-size: 21px; color: var(--gold);
  text-shadow: 0 0 20px rgba(242, 199, 92, .38);
  font-variant-numeric: tabular-nums;
}

/* ---------- misc ---------- */
.banner {
  border-radius: var(--r-sm); padding: 11px 14px;
  font-size: 14px; font-weight: 500; margin-bottom: 12px;
  border: 1px solid transparent;
}
.banner.ok   { background: var(--ok-soft);   color: var(--ok-ink);  border-color: rgba(62, 207, 142, .34); }

/* The no-fee promise — the product's entire wedge, so it stays on the page,
   but as a QUIET line rather than an alert slab.

   It used to be a filled green `.banner.ok` box directly ABOVE the cover
   photo. Two things went wrong there: the cover's negative top margin pulled
   it up into the banner so the two collided, and a saturated green box is
   off-palette on a page wearing the barber's own shop theme — it read as a
   system message interrupting their storefront, not as part of it. */
.nofee {
  display: flex; align-items: flex-start; justify-content: center; gap: 8px;
  margin: 4px 0 18px; padding: 0 4px;
  color: var(--ink-2); font-size: 13.5px; font-weight: 500;
  line-height: 1.5; text-align: center;
}
.nofee .ic { color: var(--ok); width: 17px; height: 17px; flex-shrink: 0; margin-top: 2px; }
.nofee strong { color: var(--ink); font-weight: 600; }
/* Without this the sentence drops a single orphaned word onto line two. */
.nofee > span { text-wrap: pretty; max-width: 46ch; }
.banner.red  { background: var(--red-soft);  color: var(--red-ink); border-color: rgba(255, 59, 47, .38); }
.banner.navy { background: var(--gold-soft); color: var(--gold); border-color: rgba(242, 199, 92, .32); }

/* ============================================================
   PROFILE TAB — the barber's page, loud.
   The hero wears the BARBER'S shop palette via inline custom props
   (--prb bg · --pri ink · --pri2 muted · --pra accent), never the app
   theme — same rule as book.html. Everything painted here must use
   those four, or it will break on one of the 12 shop themes.
   ============================================================ */
/* The derived tints (--pra26 accent glow, --pra45 ring halo, --pri10/--pri22
   chip fills) are hex+alpha values computed in renderProfile, NOT color-mix()
   — color-mix silently invalidates the whole declaration on pre-2023 Safari,
   which would leave the hero transparent on exactly the phones that already
   struggle. Hex+alpha works everywhere the app runs. */
.pr-hero {
  position: relative; overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  background:
    radial-gradient(120% 90% at 50% -20%, var(--pra26), transparent 60%),
    var(--prb);
  padding: 30px 18px 18px;
  margin-bottom: 14px;
  text-align: center;
  box-shadow: var(--e2);
}
.pr-bgimg {
  position: absolute; inset: 0; width: 100%; height: 58%;
  object-fit: cover; z-index: 0;
  /* Same trick as .pf-cover: the scrim is what makes ANY upload safe to put
     type near — the photo fades into the page colour before text starts. */
  -webkit-mask-image: linear-gradient(to bottom, black 30%, transparent 96%);
  mask-image: linear-gradient(to bottom, black 30%, transparent 96%);
  opacity: .8;
}
.pr-body { position: relative; z-index: 1; }
.pr-face {
  width: 92px; height: 92px; border-radius: 50%;
  object-fit: cover; margin: 0 auto 12px; display: block;
  border: 3px solid var(--prb);
  box-shadow: 0 0 0 3px var(--pra), 0 0 34px var(--pra45);
}
.pr-face.rounded { border-radius: 30px; }
.pr-face.square { border-radius: 18px; }
.pr-face.initials {
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(var(--pra26), var(--pra26)), var(--prb);
  color: var(--pri); font: 700 30px var(--font-display);
}
.pr-name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(30px, 9vw, 40px); line-height: 1.04;
  color: var(--pri); letter-spacing: .01em; margin: 0;
}
.pr-tagline {
  color: var(--pra); font-weight: 700; font-size: 13px;
  letter-spacing: .12em; text-transform: uppercase; margin-top: 7px;
}
.pr-sub { color: var(--pri2); font-size: 14.5px; margin-top: 6px; }
.pr-chips { display: flex; gap: 8px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }
.pr-chip {
  display: inline-flex; align-items: center;
  font-size: 12.5px; font-weight: 600; text-decoration: none;
  color: var(--pri);
  background: var(--pri10);
  border: 1px solid var(--pri22);
  border-radius: 999px; padding: 6px 12px;
}
/* Brass carries the founding brand, but GOLD TEXT dies on light shop themes
   (Classic, Clean, Marble) — so the ink is the hero's own, and brass stays in
   the fill, border and check mark, where it doesn't have to pass AA. */
.pr-founding {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 14px; padding: 7px 14px; border-radius: 999px;
  font-size: 12.5px; font-weight: 700;
  color: var(--pri); background: rgba(242, 199, 92, .16);
  border: 1px solid rgba(201, 147, 46, .5);
}
.pr-founding .ic { width: 15px; height: 15px; color: var(--gold-deep); }

/* Buttons inside the hero sit on the SHOP palette, so app-theme .btn tokens
   are wrong there by definition — a light storefront was rendering white
   text on white pills. Only .btn.red keeps its fixed red/white, which holds
   on every theme. */
.pr-hero .btn.soft {
  background: var(--pri10); color: var(--pri);
  border-color: var(--pri22); box-shadow: none;
}
/* Share is THE action of this tab, so it owns a full row; the quieter pair
   splits the second. Three-across clipped "Share my page" at 375px. */
.pr-actions {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 8px; margin-top: 20px;
}
.pr-actions .btn { min-width: 0; white-space: nowrap; }
.pr-actions .btn.red { grid-column: 1 / -1; }

/* Five tabs now share the dock. The labels clear 360px-wide phones at 10px;
   below that, tighten rather than wrap — a two-line tab label reads broken. */
@media (max-width: 359px) {
  .tab { font-size: 9.5px; letter-spacing: 0; }
}

/* The "optional" aside inside a field label — quieter than the label itself,
   so required-by-default stays the visual rule. */
.field .opt { font-style: normal; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ink-2); opacity: .8; }

/* "Booking as Marcus — not you?" above the details form. Deliberately visible
   rather than a silent prefill: a phone can be shared, and booking under the
   wrong name puts a stranger in the barber's chair. */
.known-chip {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 0 0 12px; padding: 9px 12px;
  background: var(--ok-soft); border: 1px solid rgba(62, 207, 142, .3);
  border-radius: var(--r-sm);
  font-size: 13.5px; color: var(--ink-2);
}
.known-chip strong { color: var(--ink); font-weight: 600; }
.known-chip button {
  background: none; border: 0; padding: 4px 2px; cursor: pointer;
  font: 600 13px var(--font-ui); color: var(--red-ink);
  text-decoration: underline; text-underline-offset: 2px;
  flex-shrink: 0;
}

/* Maps link under the address on a booking confirmation. Inherits the shop
   theme's accent so it belongs to the barber's page, not to AeroCut. */
.addr-map {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 5px;
  font-size: 13px; font-weight: 600; color: var(--red); text-decoration: none;
}
.addr-map .ic { width: 14px; height: 14px; }

/* ============================================================
   CALENDAR — month grid + week list in the Bookings tab.
   Hand-rolled: a 7-column grid, density dots, and three day states
   (booked · closed · time off). No library, no second visual language.
   ============================================================ */
.cal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 12px;
}
.cal-head .btn { min-width: 44px; }   /* thumb-sized month flippers */
.cal-title { font: 600 18px var(--font-display); letter-spacing: .01em; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-dow {
  margin-bottom: 6px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-2); text-align: center;
}
.cal-day {
  position: relative;
  aspect-ratio: 1; border-radius: 10px;
  border: 1px solid transparent; background: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 0; cursor: pointer;
  color: var(--ink); font: 500 14px var(--font-ui);
}
.cal-day.blank { visibility: hidden; }
.cal-day .n { line-height: 1; }
/* Closed reads as recessed, not forbidden — a barber can still book a
   closed day by hand, so it stays tappable. */
.cal-day.closed { color: var(--ink-2); opacity: .45; }
.cal-day.today { border-color: var(--red); }
.cal-day.sel { background: var(--red-soft); border-color: var(--red); font-weight: 700; }
.cal-dots { display: flex; gap: 2.5px; height: 4px; }
.cal-dots i { width: 4px; height: 4px; border-radius: 50%; background: var(--red); display: block; }
.cal-day.sel .cal-dots i { background: var(--red-ink); }
/* Time off wears brass, matching the founding/premium meaning of "yours". */
.cal-off-bar { width: 14px; height: 3px; border-radius: 2px; background: var(--gold-deep); display: block; }
.cal-day.off .n { color: var(--ink-2); }
.cal-legend {
  display: flex; gap: 14px; margin-top: 10px; align-items: center;
  font-size: 11.5px; color: var(--ink-2);
}
.cal-legend > span { display: inline-flex; align-items: center; gap: 5px; }
.cal-legend .cal-off-bar.demo { width: 10px; }
.cal-legend .dim { opacity: .7; }

/* ---- week list ---- */
.wk-day { border-top: 1px solid var(--line); padding: 10px 0 6px; }
.wk-day:first-of-type { border-top: 0; }
.wk-head { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.wk-name { font: 600 14px var(--font-ui); color: var(--ink-2); flex: 1; }
.wk-name b { font: 700 16px var(--font-display); color: var(--ink); margin-left: 2px; }
.wk-today-tag {
  margin-left: 8px; font-size: 10px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--red-ink);
  background: var(--red-soft); border-radius: 4px; padding: 2px 6px;
}
.wk-count { font-size: 12.5px; font-weight: 600; color: var(--gold); }
.wk-add {
  width: 30px; height: 30px; border-radius: 8px;
  border: 1px dashed var(--line-strong); background: none;
  color: var(--ink-2); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.wk-add .ic { width: 15px; height: 15px; }
.wk-add:active { border-color: var(--red); color: var(--red); }
.wk-empty { color: var(--ink-2); font-size: 13px; opacity: .7; padding: 4px 0 6px; }
.wk-day.today .wk-name b { color: var(--red-ink); }

/* Group headings on the More list — the three-drawer structure is the
   feature, so they read a size up from .section-label. */
.more-group { font-size: 13px; margin: 18px 2px 10px; color: var(--ink-2); }
.more-group:first-child { margin-top: 2px; }

/* Destructive actions live below a hairline, visually apart from the work
   buttons — a thumb aiming for "Save" must never graze a delete. The armed
   state is the second half of the tap-twice pattern (same as time-off's
   clash confirm): first tap arms and says what will happen, second commits. */
.danger-zone { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.btn.danger { color: var(--red-ink); border-color: rgba(255, 59, 47, .3); }
.btn.danger.armed {
  background: var(--red-soft); color: var(--red-ink);
  border-color: rgba(255, 59, 47, .55);
}

.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* The whole grid is one tap target for the earnings sheet. Button reset —
   otherwise UA styles centre the text and shrink-wrap the width. */
button.stat-tap {
  width: 100%; border: 0; padding: 0; background: none;
  text-align: left; font: inherit; color: inherit; cursor: pointer;
  position: relative;
}
.stat-hint {
  grid-column: 1 / -1; justify-self: end;
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11.5px; font-weight: 600; color: var(--ink-2);
}
.stat-hint .ic { width: 12px; height: 12px; }

/* Weekday bar chart in the earnings sheet. Pure CSS columns — the numbers
   are small integers, a charting lib would be absurd here. */
.earn-bars {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px;
  align-items: end; height: 96px; padding: 4px 2px 0;
}
.eb { display: flex; flex-direction: column; align-items: center; gap: 5px; height: 100%; justify-content: flex-end; }
.eb i {
  width: 100%; max-width: 30px; border-radius: 6px 6px 2px 2px;
  background: var(--graphite-lift); display: block;
}
.eb i.top { background: linear-gradient(180deg, var(--gold), var(--gold-deep)); }
.eb span { font-size: 10.5px; font-weight: 700; color: var(--ink-2); }
.stat {
  background: linear-gradient(160deg, rgba(242, 199, 92, .07), transparent 60%), var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r); padding: 14px 15px;
  box-shadow: var(--e1), inset 0 1px 0 rgba(255, 255, 255, .06);
  position: relative; overflow: hidden;
}
.stat::after {
  content: ""; position: absolute; top: -14px; right: -14px;
  width: 44px; height: 44px;
  background: linear-gradient(-45deg, transparent 48%, rgba(242, 199, 92, .16) 48% 52%, transparent 52%);
}
.stat .k { font-size: 11px; font-weight: 700; color: var(--ink-2); text-transform: uppercase; letter-spacing: .12em; }
.stat .v {
  font-size: 34px; font-weight: 700; margin-top: 2px; color: var(--gold);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
  text-shadow: 0 0 26px rgba(242, 199, 92, .35);
}

.cutnote {
  margin: -4px 0 10px 56px;
  padding: 10px 13px;
  background: rgba(242, 199, 92, .08);
  border-left: 3px solid var(--gold);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 13.5px;
  color: #E8DCC8;
  line-height: 1.45;
}

/* confirmation seal */
.done-mark {
  width: 76px; height: 76px; margin: 4px auto 0;
  border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(160deg, #46E39C, #17A06C);
  box-shadow: 0 0 0 1px rgba(62, 207, 142, .4), 0 8px 36px rgba(62, 207, 142, .5), inset 0 1px 0 rgba(255, 255, 255, .4);
  animation: seal .5s var(--spring) both;
}
.done-mark.alt {
  background: linear-gradient(160deg, var(--gold), var(--gold-deep));
  box-shadow: 0 0 0 1px rgba(242, 199, 92, .4), 0 8px 32px rgba(242, 199, 92, .45), inset 0 1px 0 rgba(255, 255, 255, .4);
}
.done-mark .ic { width: 38px; height: 38px; color: #0A0807; }
@keyframes seal {
  from { transform: scale(.4) rotate(-12deg); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* empty/loading states carry the shop's own sign: a turning barber pole.
   This is the one place blue is allowed — a pole without it isn't a pole. */
.empty {
  text-align: center; color: var(--ink-2);
  padding: 30px 10px; font-size: 14.5px;
}
.empty::before {
  content: ""; display: block;
  width: 62px; height: 8px; margin: 0 auto 14px;
  border-radius: 4px;
  background: repeating-linear-gradient(-55deg,
    var(--red) 0 8px, #F7F4F0 8px 16px, var(--pole-blue) 16px 24px);
  background-size: 200% 100%;
  box-shadow: 0 0 16px rgba(255, 59, 47, .3), inset 0 0 0 1px rgba(255, 255, 255, .18);
  animation: pole 1.1s linear infinite;
}
@keyframes pole { to { background-position: -24px 0; } }
.empty .big { font-size: 34px; margin-bottom: 8px; }
.empty .big .ic { width: 40px; height: 40px; color: var(--gold); opacity: .65; }

.hidden { display: none !important; }

/* toast */
#toast {
  position: fixed; left: 50%; bottom: 100px; transform: translateX(-50%) translateY(20px);
  background: rgba(0, 0, 0, .93);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: #fff;
  padding: 12px 20px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .18);
  font-size: 14px; font-weight: 500;
  box-shadow: var(--e3);
  opacity: 0; pointer-events: none;
  transition: opacity .25s, transform .25s var(--spring);
  z-index: 90; max-width: 88vw; text-align: center;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* modal sheet */
.sheet-back {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, .68);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  z-index: 60; display: flex; align-items: flex-end; justify-content: center;
  animation: fadein .2s ease both;
}
@keyframes fadein { from { opacity: 0; } }
:root[data-theme="light"] .sheet-back { background: rgba(26, 20, 16, .38); }
:root[data-theme="light"] .sheet { background: #FFFDFA; }
:root[data-theme="light"] #toast {
  background: rgba(26, 20, 16, .94);
  border-color: rgba(255, 255, 255, .14);
}
:root[data-theme="light"] .avatar { color: var(--gold); }
:root[data-theme="light"] .cutnote { color: #4A3A1E; }
:root[data-theme="light"] .pf-face { border-color: #FFFDFA; }
:root[data-theme="light"] .done-mark .ic,
:root[data-theme="light"] .done-mark.alt .ic { color: #FFFDFA; }
:root[data-theme="light"] .btn { color: var(--ink); }
:root[data-theme="light"] .btn.red { color: #fff; }
:root[data-theme="light"] .tabbar {
  background: linear-gradient(to top, rgba(246, 242, 237, .96), transparent);
}

.sheet {
  background: #15110F; width: 100%; max-width: var(--max);
  border: 1px solid var(--line); border-bottom: 0;
  border-radius: 24px 24px 0 0;
  padding: 18px var(--pad) calc(18px + env(safe-area-inset-bottom));
  max-height: 88dvh; overflow-y: auto;
  box-shadow: var(--e3);
  animation: sheetup .34s var(--spring) both;
}
@keyframes sheetup { from { transform: translateY(48px); opacity: .4; } to { transform: none; opacity: 1; } }
.sheet h3 {
  font-size: 19px; font-weight: 600; margin-bottom: 12px; color: var(--ink);
}
.sheet .grab { width: 40px; height: 4px; border-radius: 2px; background: rgba(255, 255, 255, .24); margin: 0 auto 14px; }

@media (min-width: 720px) {
  .sheet-back { align-items: center; }
  .sheet { border-radius: 24px; border-bottom: 1px solid var(--line); animation-name: sheetpop; }
  @keyframes sheetpop { from { transform: scale(.96) translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
}

/* Swipe navigation: the incoming view slides in from the side the gesture
   came from. Applied to the <main>, so the card stagger inside still runs
   on top of it. */
.swipe-l { animation: swipeL .26s var(--ease-out) both; }
.swipe-r { animation: swipeR .26s var(--ease-out) both; }
@keyframes swipeL { from { opacity: .3; transform: translateX(26px); } }
@keyframes swipeR { from { opacity: .3; transform: translateX(-26px); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ============================================================
   Landing — the pitch IS the product's look
   ============================================================ */
.land-hero { padding: 22px 4px 18px; }
.land-kicker {
  font: 700 11px/1 var(--font-ui); letter-spacing: .18em;
  text-transform: uppercase; color: var(--red); margin-bottom: 10px;
  text-shadow: 0 0 18px rgba(255, 59, 47, .6);
}
.land-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(34px, 9.5vw, 44px); line-height: 1.02;
  letter-spacing: -.015em; color: var(--ink); margin-bottom: 12px;
}
.land-title .hl { color: var(--red); text-shadow: 0 0 30px rgba(255, 59, 47, .5); }
.land-sub {
  color: var(--ink-2); font-size: 15.5px; line-height: 1.55;
  margin-bottom: 20px; max-width: 42ch;
}
.land-founding {
  display: flex; align-items: center; gap: 14px;
  text-decoration: none; border-left: 3px solid var(--red);
}
.land-founding .n {
  font-family: var(--font-display); font-size: 32px; font-weight: 700;
  color: var(--gold); min-width: 44px; text-align: center;
  text-shadow: 0 0 22px rgba(242, 199, 92, .4);
}
.land-founding .t { font-weight: 600; color: var(--ink); font-size: 15px; }
.land-founding .s { color: var(--ink-2); font-size: 13px; }
.land-founding .grow { flex: 1; }
.land-ic { color: var(--gold); flex-shrink: 0; }

/* ============================================================
   Storefront
   ============================================================ */
.pf-card { display: flex; gap: 14px; align-items: center; }
.pf-face {
  width: 68px; height: 68px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
  box-shadow: 0 0 0 2px rgba(255, 59, 47, .65), 0 0 26px rgba(255, 59, 47, .35), var(--e1);
  border: 2px solid #15110F;
}
.pf-face.sm { width: 44px; height: 44px; }
.pf-bio { color: var(--ink-2); font-size: 14px; line-height: 1.5; margin-top: 2px; }
.pf-strip {
  display: flex; gap: 10px; overflow-x: auto;
  padding-bottom: 6px; margin-bottom: 16px;
  -webkit-overflow-scrolling: touch;
}
.pf-strip img {
  height: 132px; border-radius: var(--r-sm);
  flex-shrink: 0; box-shadow: var(--e2);
  border: 1px solid rgba(255, 255, 255, .14);
}
.pf-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 8px; margin: 10px 0 14px;
}
.pf-grid .ph { position: relative; }
.pf-grid img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--r-sm); display: block;
  border: 1px solid rgba(255, 255, 255, .14);
}
.pf-grid .del {
  position: absolute; top: 4px; right: 4px;
  width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .2);
  background: rgba(0, 0, 0, .82); color: #fff;
  font-size: 16px; line-height: 1; cursor: pointer;
}
.pf-add {
  aspect-ratio: 1; border-radius: var(--r-sm);
  border: 2px dashed var(--line-strong); background: none;
  color: var(--ink-2); font: 600 13px var(--font-ui);
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 4px; cursor: pointer;
}
.pf-add:active { border-color: var(--red); color: var(--red); }

/* A photo whose storage object has gone missing. The cell deliberately stays
   put and keeps its × button — the barber is the only one who can clear the
   dead row, so hiding it would strand them. On the PUBLIC page the same photo
   is removed outright instead; a client should never see our plumbing. */
.pf-grid .ph.missing {
  aspect-ratio: 1; border-radius: var(--r-sm);
  border: 1px dashed var(--line-strong);
  background: var(--navy-ghost);
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 6px;
}
.ph-gone { color: var(--ink-2); font: 500 12px var(--font-ui); line-height: 1.3; }

/* ============================================================
   SHOP STYLE — the barber's public page themes.

   Applied as data-shop-theme on <body> of book.html only.

   These OVERRIDE the viewer's light/dark toggle on purpose. This is the
   barber's storefront: it should look the same to every client, the way a
   website does. The APP still follows the user's own toggle — only the
   public page is branded.

   Each theme re-points the SAME tokens the components already use, so
   nothing below the token layer needs to know a theme exists. Adding a
   ninth is a block here plus one entry in SHOP_THEMES (app.js) — no
   migration, because shop_theme is unconstrained and the renderer falls
   back to 'night'.
   ============================================================ */

/* 1 · NIGHT SHOP — the house look, matches the app */
body[data-shop-theme="night"] {
  --bg: #0A0807; --card: rgba(28,24,22,.84); --glass: rgba(14,12,11,.76);
  --ink: #FCFAF7; --ink-2: #A99E95;
  --line: rgba(255,255,255,.10); --line-strong: rgba(255,255,255,.20);
  --red: #FF3B2F; --red-hot: #FF5C4D; --red-deep: #C4241A; --red-soft: rgba(255,59,47,.16);
  --gold: #F2C75C; --field: rgba(0,0,0,.42); --field-on: rgba(0,0,0,.6); --scheme: dark;
  --ok-ink: #6BE3AE; --red-ink: #FF8377;
}

/* 2 · CLASSIC POLE — cream, navy and barber red. The traditional shop. */
body[data-shop-theme="classic"] {
  --bg: #F5F1E8; --card: #FFFFFF; --glass: rgba(255,253,248,.86);
  --ink: #14213D; --ink-2: #5B6478;
  --line: rgba(20,33,61,.12); --line-strong: rgba(20,33,61,.22);
  --red: #C1121F; --red-hot: #D62828; --red-deep: #9A0E18; --red-soft: rgba(193,18,31,.10);
  --gold: #14213D; --field: #FFFFFF; --field-on: #FFFFFF; --scheme: light;
  --ok-ink: #0B6144; --red-ink: #9A0E18;
}

/* 3 · BLACKOUT — true black and gold. High-end, appointment-only energy. */
body[data-shop-theme="blackout"] {
  --bg: #000000; --card: rgba(20,20,20,.9); --glass: rgba(8,8,8,.82);
  --ink: #FFFFFF; --ink-2: #9E9A93;
  --line: rgba(212,175,55,.20); --line-strong: rgba(212,175,55,.38);
  --red: #D4AF37; --red-hot: #E8C458; --red-deep: #A8862A; --red-soft: rgba(212,175,55,.14);
  --gold: #E8C458; --field: rgba(0,0,0,.6); --field-on: #000; --scheme: dark;
  --ok-ink: #6BE3AE; --red-ink: #E8C458;
}

/* 4 · FRESH FADE — charcoal and mint. Modern, clean, younger clientele. */
body[data-shop-theme="fade"] {
  --bg: #12171A; --card: rgba(26,34,38,.86); --glass: rgba(16,22,25,.8);
  --ink: #F0F5F5; --ink-2: #93A3A8;
  --line: rgba(255,255,255,.09); --line-strong: rgba(255,255,255,.18);
  --red: #2DD4A8; --red-hot: #4FE6BF; --red-deep: #1BA383; --red-soft: rgba(45,212,168,.14);
  --gold: #7DE8CE; --field: rgba(0,0,0,.4); --field-on: rgba(0,0,0,.58); --scheme: dark;
  --ok-ink: #7DE8CE; --red-ink: #4FE6BF;
}

/* 5 · BRASS — warm brown and heavy gold. Old-school, leather-and-wood. */
body[data-shop-theme="brass"] {
  --bg: #1A120B; --card: rgba(42,30,20,.88); --glass: rgba(26,18,11,.8);
  --ink: #F7EEE2; --ink-2: #B09A80;
  --line: rgba(212,160,90,.18); --line-strong: rgba(212,160,90,.34);
  --red: #C8873A; --red-hot: #E0A055; --red-deep: #9C6526; --red-soft: rgba(200,135,58,.15);
  --gold: #E8C08A; --field: rgba(0,0,0,.4); --field-on: rgba(0,0,0,.58); --scheme: dark;
  --ok-ink: #8FD9B0; --red-ink: #E0A055;
}

/* 6 · CLEAN CUT — white and near-black. Editorial, minimal, no ornament. */
body[data-shop-theme="clean"] {
  --bg: #FAFAFA; --card: #FFFFFF; --glass: rgba(255,255,255,.88);
  --ink: #0F0F0F; --ink-2: #6B6B6B;
  --line: rgba(0,0,0,.10); --line-strong: rgba(0,0,0,.20);
  --red: #0F0F0F; --red-hot: #2B2B2B; --red-deep: #000000; --red-soft: rgba(0,0,0,.06);
  --gold: #0F0F0F; --field: #FFFFFF; --field-on: #FFFFFF; --scheme: light;
  --ok-ink: #0B6144; --red-ink: #0F0F0F;
}

/* 7 · NEON — indigo and hot pink. Built for the TikTok crowd. */
body[data-shop-theme="neon"] {
  --bg: #0D0A1F; --card: rgba(26,20,54,.86); --glass: rgba(13,10,31,.8);
  --ink: #F4F0FF; --ink-2: #9F96C4;
  --line: rgba(168,85,247,.20); --line-strong: rgba(168,85,247,.40);
  --red: #F72585; --red-hot: #FF4D9D; --red-deep: #C4106A; --red-soft: rgba(247,37,133,.16);
  --gold: #4CC9F0; --field: rgba(0,0,0,.42); --field-on: rgba(0,0,0,.6); --scheme: dark;
  --ok-ink: #4CC9F0; --red-ink: #FF6FAF;
}

/* 8 · SUNSET — warm dusk into coral. Softer than Night Shop, still dark. */
body[data-shop-theme="sunset"] {
  --bg: #1A0F14; --card: rgba(42,24,30,.86); --glass: rgba(26,15,20,.8);
  --ink: #FDF2EC; --ink-2: #BC9A94;
  --line: rgba(255,138,101,.16); --line-strong: rgba(255,138,101,.32);
  --red: #FF6B4A; --red-hot: #FF8A65; --red-deep: #D9482A; --red-soft: rgba(255,107,74,.15);
  --gold: #FFB088; --field: rgba(0,0,0,.4); --field-on: rgba(0,0,0,.58); --scheme: dark;
  --ok-ink: #8FD9B0; --red-ink: #FF8A65;
}

/* ---------- storefront chrome ---------- */
/* Cover banner. Bleeds past .wrap's padding so it reaches both edges. */
.pf-cover {
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 0;
  height: 150px; position: relative; overflow: hidden;
}
.pf-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The fade is what lets the name sit on ANY photo a barber uploads without
   us knowing whether it is bright or dark. */
.pf-cover::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, transparent 30%, var(--bg));
}
/* With a cover present the profile card rides up over its lower edge. */
.pf-cover + .pf-card { margin-top: -42px; position: relative; z-index: 2; }

.pf-face.square { border-radius: 16px; }
.pf-face.rounded { border-radius: 26px; }

.pf-tagline {
  color: var(--red); font-weight: 700; font-size: 12.5px;
  letter-spacing: .1em; text-transform: uppercase; margin-top: 3px;
}
.pf-social { display: flex; gap: 8px; margin-top: 10px; }
.pf-social a {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 600; text-decoration: none;
  color: var(--ink); background: rgba(128,128,128,.12);
  border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px;
}

/* ---------- theme picker (in the app's More tab) ---------- */
.th-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 9px; margin-top: 6px; }
.th {
  border: 2px solid transparent; border-radius: 14px; padding: 0;
  cursor: pointer; overflow: hidden; background: none; font-family: var(--font-ui);
  transition: transform .16s var(--spring);
}
.th:active { transform: scale(.95); }
.th.sel { border-color: var(--red); box-shadow: var(--glow-red); }
/* A swatch is a miniature of the real page — surface, text, action button —
   not a colour chip. Barbers pick what they can already picture. */
.th .sw {
  height: 56px; border-radius: 10px; position: relative;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 6px; gap: 3px;
}
.th .sw i { display: block; height: 4px; border-radius: 2px; }
.th .sw .b { height: 12px; border-radius: 4px; width: 62%; }
.th .nm {
  display: block; font-size: 10px; font-weight: 700; letter-spacing: .04em;
  color: var(--ink-2); padding: 5px 2px 3px; text-align: center;
}
.th.sel .nm { color: var(--ink); }

/* ============================================================
   PREMIUM SHOP STYLES
   The free four (night · classic · clean · fade) are a complete,
   dignified set on purpose: these pages carry "Booking by AeroCut"
   in front of every client a barber has, so a cheap-looking free
   tier costs the brand more than it earns.

   Premium buys DISTINCTIVENESS, not quality. The four below add
   MATERIAL — woven carbon, brushed steel, marble veining, velvet
   nap — rendered in pure CSS so there is no image to load on the
   most important page in the funnel.
   ============================================================ */

/* 9 · CARBON — woven carbon fibre, racing red. */
body[data-shop-theme="carbon"] {
  --bg: #0B0C0E; --card: rgba(23,26,30,.88); --glass: rgba(9,10,12,.82);
  --ink: #F2F4F6; --ink-2: #949BA3;
  --line: rgba(255,255,255,.09); --line-strong: rgba(255,255,255,.18);
  --red: #E01E28; --red-hot: #FF3742; --red-deep: #A8121A; --red-soft: rgba(224,30,40,.15);
  --gold: #C9D1D9; --field: rgba(0,0,0,.45); --field-on: rgba(0,0,0,.62); --scheme: dark;
  --ok-ink: #6BE3AE; --red-ink: #FF6B72;
}
body[data-shop-theme="carbon"]::before {
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,.030) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,.030) 0 2px, transparent 2px 5px),
    radial-gradient(700px 420px at 50% -8%, rgba(224,30,40,.16), transparent 62%),
    var(--bg);
  animation: none;
}

/* 10 · CHROME — brushed steel with a sheen that travels on scroll. */
body[data-shop-theme="chrome"] {
  --bg: #14161A; --card: rgba(32,36,42,.86); --glass: rgba(16,18,22,.8);
  --ink: #F7F9FC; --ink-2: #9AA4B2;
  --line: rgba(255,255,255,.12); --line-strong: rgba(255,255,255,.24);
  --red: #9FB3C8; --red-hot: #C3D3E3; --red-deep: #6E8299; --red-soft: rgba(159,179,200,.16);
  --gold: #DCE6F0; --field: rgba(0,0,0,.42); --field-on: rgba(0,0,0,.6); --scheme: dark;
  --ok-ink: #7DE8CE; --red-ink: #C3D3E3;
}
body[data-shop-theme="chrome"]::before {
  background:
    repeating-linear-gradient(92deg, rgba(255,255,255,.020) 0 1px, transparent 1px 3px),
    linear-gradient(100deg, transparent 18%, rgba(255,255,255,.05) 40%,
      rgba(255,255,255,.10) 50%, rgba(255,255,255,.05) 60%, transparent 82%),
    var(--bg);
  /* The highlight rides the scroll — steel catching the light as you move. */
  background-position: 0 0, calc(var(--sy, 0) * 60% - 20%) 0, 0 0;
  animation: none;
}

/* 11 · MARBLE — white stone with gold veining. The luxury LIGHT option. */
body[data-shop-theme="marble"] {
  --bg: #F7F5F1; --card: rgba(255,255,255,.90); --glass: rgba(255,255,255,.86);
  --ink: #17150F; --ink-2: #6A6355;
  --line: rgba(23,21,15,.11); --line-strong: rgba(23,21,15,.20);
  --red: #8A6D2F; --red-hot: #A5842F; --red-deep: #6B5320; --red-soft: rgba(138,109,47,.10);
  --gold: #8A6D2F; --field: #FFFFFF; --field-on: #FFFFFF; --scheme: light;
  --ok-ink: #0B6144; --red-ink: #6B5320;
}
body[data-shop-theme="marble"]::before {
  background:
    linear-gradient(114deg, transparent 44%, rgba(150,124,66,.20) 47%, transparent 50%),
    linear-gradient(96deg, transparent 62%, rgba(150,124,66,.13) 65%, transparent 67%),
    radial-gradient(ellipse 70% 34% at 18% 26%, rgba(120,112,98,.13), transparent 62%),
    radial-gradient(ellipse 56% 28% at 78% 68%, rgba(120,112,98,.10), transparent 62%),
    var(--bg);
  animation: none;
}

/* 12 · VELVET — deep wine with a soft nap and gold. */
body[data-shop-theme="velvet"] {
  --bg: #1B0A14; --card: rgba(45,16,32,.88); --glass: rgba(27,10,20,.82);
  --ink: #FBEFF4; --ink-2: #BC94A6;
  --line: rgba(224,168,110,.16); --line-strong: rgba(224,168,110,.32);
  --red: #D9A353; --red-hot: #EFBE72; --red-deep: #A87A32; --red-soft: rgba(217,163,83,.14);
  --gold: #EFBE72; --field: rgba(0,0,0,.4); --field-on: rgba(0,0,0,.58); --scheme: dark;
  --ok-ink: #8FD9B0; --red-ink: #EFBE72;
}
body[data-shop-theme="velvet"]::before {
  background:
    radial-gradient(circle at 50% -10%, rgba(255,214,170,.10), transparent 58%),
    repeating-linear-gradient(88deg, rgba(255,255,255,.014) 0 1px, transparent 1px 4px),
    radial-gradient(ellipse 120% 70% at 50% 120%, rgba(0,0,0,.55), transparent 60%),
    var(--bg);
  animation: none;
}

/* ---------- locked themes in the picker ---------- */
.th.locked .sw { opacity: .55; }
.th.locked { position: relative; }
.th .lock {
  position: absolute; top: 5px; right: 5px;
  width: 20px; height: 20px; border-radius: 50%;
  background: rgba(0,0,0,.72); border: 1px solid rgba(255,255,255,.28);
  display: grid; place-items: center;
}
.th .lock .ic { width: 11px; height: 11px; color: var(--gold); }
.th-tier {
  display: flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--gold);
  margin: 16px 0 6px;
}
.th-tier::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ---------- CUSTOM STUDIO (premium) ----------
   The barber's own background, accent, font and button shape, written as
   inline CSS vars by applyCustomStyle() in db.js. Nothing is hardcoded here
   because every value is theirs — this block only wires their choices into
   the same tokens the presets use. */
body[data-shop-theme="custom"] {
  background: var(--custom-bg, var(--bg));
  background-attachment: fixed;
}
/* Their background IS the atmosphere. The house ember layer would fight it. */
body[data-shop-theme="custom"]::before { display: none; }
body[data-shop-theme="custom"]::after { opacity: .5; }

/* Button shape is a real choice, so it needs its own token — --r is used by
   cards and inputs too, and pinning those to a pill looks broken. */
.btn { border-radius: var(--btn-r, 14px); }
.slot, .day { border-radius: var(--btn-r, 12px); }

/* ---------- the studio editor ---------- */
.cs-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; }
.cs-row .lbl { flex: 1; font-weight: 600; font-size: 14.5px; }
.cs-swatch {
  width: 42px; height: 32px; border-radius: 9px; padding: 0;
  border: 2px solid var(--line-strong); cursor: pointer; overflow: hidden;
}
.cs-swatch input {
  width: 200%; height: 200%; margin: -25%; padding: 0; border: 0;
  min-height: 0; cursor: pointer; background: none;
}
.cs-seg { display: flex; gap: 6px; flex-wrap: wrap; }
.cs-seg button {
  flex: 1; min-width: 68px; min-height: 38px; padding: 0 10px;
  border-radius: 10px; border: 1.5px solid var(--line-strong);
  background: transparent; color: var(--ink-2);
  font: 600 13px var(--font-ui); cursor: pointer;
}
.cs-seg button.on { border-color: var(--red); color: var(--ink); background: var(--red-soft); }
.cs-range { width: 100%; min-height: 0; padding: 0; background: none; border: 0; }

/* Live preview — a real miniature of the booking page, not a colour chip.
   `contain` stops the preview's own vars leaking into the editor around it. */
.cs-prev {
  border-radius: 16px; overflow: hidden; border: 1px solid var(--line-strong);
  box-shadow: var(--e2); margin: 10px 0 4px; contain: paint style;
  background: var(--custom-bg, var(--bg));
}
.cs-prev .in { padding: 14px; display: grid; gap: 9px; }
.cs-prev .nm { font-family: var(--font-display); font-weight: 700; font-size: 17px; color: var(--ink); }
.cs-prev .tg { font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--red); }
.cs-prev .cd {
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  padding: 10px 12px; display: flex; align-items: center; gap: 10px;
}
.cs-prev .cd .t { flex: 1; font-size: 13px; font-weight: 600; color: var(--ink); }
.cs-prev .cd .p { font-family: var(--font-display); font-weight: 700; color: var(--gold); }
.cs-prev .bt {
  background: var(--red); color: var(--on-accent, #fff); text-align: center;
  padding: 10px; border-radius: var(--btn-r, 14px);
  font-weight: 600; font-size: 14px;
}
.cs-warn {
  display: flex; gap: 8px; align-items: flex-start;
  font-size: 12.5px; line-height: 1.45; margin-top: 8px;
  color: var(--warn-ink); background: var(--warn-soft);
  border: 1px solid rgba(232,163,61,.34); border-radius: 10px; padding: 9px 11px;
}
