*, *::before, *::after { box-sizing: border-box; }
/* An explicit display on buttons/links would otherwise beat the browser's
   own [hidden] rule, leaving "hidden" elements on screen. */
[hidden] { display: none !important; }

/* Nunito Sans (latin subset) — the whole voice of the renovated app, weights
   400/600/700/800. No Greek subset exists, so Greek text falls through to the
   system stack, same as the old serif did. */
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/nunito-sans-400.woff2) format('woff2');
}
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/nunito-sans-600.woff2) format('woff2');
}
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/fonts/nunito-sans-700.woff2) format('woff2');
}
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url(/fonts/nunito-sans-800.woff2) format('woff2');
}

/* ============================================================
   El Soma Studio — "Studio Light"
   Neutral page, frosted chrome floating above it, wine accent.
   ============================================================ */

:root {
  color-scheme: light;

  /* ---- ramps ---- */
  --linen-50:#FDFBF8;  --linen-100:#F7F2EC; --linen-150:#F3EEE8; --linen-200:#EDE6DE;
  --linen-300:#E1D8CE; --linen-400:#C9BCAE; --linen-500:#8A7F74; --linen-600:#6F645A;
  --linen-700:#4E4640; --linen-800:#2E2924; --linen-900:#1D1A17; --linen-950:#121110;

  /* Wine, sampled from the Flow reference: 500 is its bar and button,
     600 the bottom of its hero, 700 the badge chip. */
  --wine-50:#FBEDEF;  --wine-100:#F4D6DA; --wine-200:#E8B3BA; --wine-400:#C46B77;
  --wine-500:#AC4451; --wine-600:#84343E; --wine-700:#4A1F24;

  --sage-50:#EDF2EA;  --sage-100:#DDE7D7; --sage-300:#9CC293; --sage-500:#63855C;
  --sage-600:#4F7350; --sage-700:#3B5A3D;

  --rust-50:#FCEDE8;  --rust-100:#F6D8CF; --rust-500:#CC4E3A; --rust-600:#B23D2B;

  --slate-100:#E2E8F0; --slate-500:#3F5C7D; --slate-600:#31485F;

  /* ---- surfaces (renovation: flat neutral body, brand chrome on top) ---- */
  --bg:             #F7F7F7;
  --bg-wash-warm:   transparent;
  --bg-wash-cool:   transparent;
  --surface-1:      #FFFFFF;
  --surface-2:      #FFFFFF;
  --surface-sunken: #F2F2F3;
  --press:          rgba(29, 26, 23, 0.055);

  --ink:   #292929;
  --ink-2: #4A5158;
  --muted: #66707D;            /* cool slate — the quiet signature next to clay */
  --faint: #A9AFB6;            /* decorative only — never body text */

  /* Brand chrome: the colored band at the top of every screen, and the
     near-black end of the home hero gradient. */
  --bar:            var(--wine-500);
  --hero-top:       #1F0C0F;
  --on-bar:         #FFFFFF;
  --on-bar-muted:   rgba(255, 255, 255, 0.62);
  --on-bar-chip:    rgba(255, 255, 255, 0.14);
  --on-bar-border:  rgba(255, 255, 255, 0.28);

  --hairline:        rgba(29, 26, 23, 0.10);
  --hairline-strong: rgba(29, 26, 23, 0.17);
  --highlight:       rgba(255, 255, 255, 0.75);

  --accent:        var(--wine-500);
  --accent-press:  var(--wine-600);
  --accent-ink:    #FFFFFF;
  --accent-tint:   rgba(172, 68, 81, 0.10);
  --accent-tint-2: rgba(172, 68, 81, 0.18);

  --class-ink: var(--wine-700);
  --ok:   var(--sage-600);  --ok-tint:   rgba(79, 115, 80, 0.12); --ok-edge:   var(--sage-500);
  --bad:  var(--rust-600);  --bad-tint:  rgba(204, 78, 58, 0.11); --bad-edge:  var(--rust-500);
  --info: var(--slate-500); --info-tint: rgba(63, 92, 125, 0.10); --info-edge: var(--slate-500);

  --glass-wall:  rgba(255, 255, 255, 0.30);
  --glass-wall-press: rgba(255, 255, 255, 0.68);
  --glass-clear: rgba(255, 255, 255, 0.42);
  /* Liquid Glass: the light a lens catches, per theme. */
  --lens-top:   rgba(255, 255, 255, 0.32);   /* specular crescent, top-left */
  --lens-bot:   rgba(255, 255, 255, 0.34);   /* caustic where light exits */
  --lens-edge-t:rgba(255, 255, 255, 0.85);   /* lit top hairline */
  --lens-edge-b:rgba(255, 255, 255, 0.62);   /* light bouncing back up */
  --lens-shade: rgba(0, 0, 0, 0.15);
  --lens-deep:  rgba(0, 0, 0, 0.34);
  --lens-ring: linear-gradient(155deg,
     rgba(255,255,255,1) 0%, rgba(255,255,255,.32) 24%, rgba(255,255,255,.10) 46%,
     rgba(255,255,255,.26) 64%, rgba(255,255,255,.95) 100%);
  --lens-ring-clear: linear-gradient(155deg,
     rgba(255,255,255,1) 0%, rgba(29,26,23,.09) 30%, rgba(29,26,23,.12) 58%,
     rgba(255,255,255,.92) 100%);
  --focus:      var(--wine-500);
  --focus-halo: rgba(172, 68, 81, 0.24);

  /* ---- materials (frosted chrome) ---- */
  --blur-thin: 12px; --blur-regular: 22px; --blur-thick: 26px;
  --sat: 190%;
  /* Pushed toward light so dark ink still reads once content passes under. */
  --mat-bright: 1.12;
  --mat-thin:    rgba(247, 242, 236, 0.42);
  --mat-regular: rgba(247, 242, 236, 0.50);
  --mat-thick:   rgba(250, 246, 241, 0.52);
  --mat-solid:   #F3EEE8;
  --mat-edge:    inset 0 0.5px 0 rgba(255, 255, 255, 0.80);
  --mat-under:   inset 0 -0.5px 0 rgba(29, 26, 23, 0.08);

  /* ---- elevation. Hairlines are shadows, never borders: a 1px border
         on a 3× screen is a visibly fat rule. ---- */
  --e-0: none;
  --e-1: 0 0.5px 1px rgba(29, 26, 23, 0.06), 0 1px 2px -1px rgba(29, 26, 23, 0.10);
  --e-2: 0 0.5px 1px rgba(29, 26, 23, 0.05), 0 2px 4px -2px rgba(29, 26, 23, 0.10),
         0 8px 18px -10px rgba(29, 26, 23, 0.14);
  --e-3: 0 0.5px 1px rgba(29, 26, 23, 0.05), 0 4px 10px -4px rgba(29, 26, 23, 0.12),
         0 16px 32px -14px rgba(29, 26, 23, 0.20), 0 32px 64px -32px rgba(29, 26, 23, 0.22);
  --ring:        0 0 0 0.5px var(--hairline);
  --ring-strong: 0 0 0 0.5px var(--hairline-strong);

  /* ---- radii (renovation ladder: 8 media / 14 cards / 24 sheets) ---- */
  --r-2xs:6px; --r-xs:8px; --r-sm:12px; --r-md:14px;
  --r-lg:16px; --r-xl:24px; --r-2xl:28px; --r-full:999px;
  --r-card: var(--r-md);
  --pad-card: var(--s-4);

  /* ---- space (4px base) ---- */
  --s-1:4px; --s-2:8px;  --s-3:12px; --s-4:16px; --s-5:20px; --s-6:24px;
  --s-7:28px; --s-8:32px; --s-10:40px; --s-12:48px; --s-16:64px;
  --gutter: clamp(14px, 4vw, 22px);

  /* ---- safe area & chrome ---- */
  --sa-t: env(safe-area-inset-top, 0px);
  --sa-b: env(safe-area-inset-bottom, 0px);
  --sa-l: env(safe-area-inset-left, 0px);
  --sa-r: env(safe-area-inset-right, 0px);
  --header-h: 52px;
  --tabbar-h: 56px;
  --tabbar-gap: 10px;
  --stick-top: calc(var(--header-h) + var(--sa-t));
  --content-bottom: calc(var(--tabbar-h) + var(--tabbar-gap) + var(--sa-b) + var(--s-5));

  /* ---- type ---- */
  --font-ui: 'Nunito Sans', -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", Roboto, sans-serif;
  --font-display: 'Nunito Sans', -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", Roboto, sans-serif;

  --t-2xs: clamp(10px,  9.1px + 0.24vw, 12px);
  --t-xs:  clamp(12px, 11.1px + 0.24vw, 13.5px);
  --t-sm:  clamp(13px, 12.0px + 0.28vw, 15px);
  --t-md:  clamp(15px, 14.0px + 0.28vw, 17px);
  --t-lg:  clamp(17px, 15.5px + 0.42vw, 20px);
  --t-xl:  clamp(20px, 17.7px + 0.66vw, 25px);
  --t-2xl: clamp(25px, 21.3px + 1.05vw, 33px);
  --t-3xl: clamp(31px, 25.3px + 1.62vw, 44px);

  --lh-tight:1.14; --lh-snug:1.28; --lh-body:1.5;
  --track-tight:-0.021em; --track-snug:-0.011em; --track-wide:0.055em;

  /* ---- motion ---- */
  --dur-press:110ms; --dur-1:170ms; --dur-2:240ms; --dur-3:340ms; --dur-4:460ms;
  --ease-std: cubic-bezier(.32,.72,0,1);
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-in:  cubic-bezier(.4,0,1,1);
  --spring: linear(0,.0085,.0338 2.4%,.1265 4.9%,.4187 10.6%,.6997 16.2%,.8543,
            .9636 22.4%,1.0273,1.0533,1.0655 30.3%,1.0554 34.5%,1.0192 43.2%,
            .9963 50.5%,.9944 57.8%,1.0018 76.4%,1);

  /* ---- charts ---- */
  --chart-1: var(--accent);
  --chart-2: var(--slate-500);
  --chart-grid: var(--hairline);
  --chart-text: var(--muted);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --bg:             #141312;
    --bg-wash-warm:   transparent;
    --bg-wash-cool:   transparent;
    --surface-1:      #1E1C1A;
    --surface-2:      #24211F;
    --bar:            #3A171C;
    --hero-top:       #150A0C;
    --surface-sunken: rgba(255, 255, 255, 0.055);
    --press:          rgba(255, 255, 255, 0.075);

    --ink:   #F2EDE7;
    --ink-2: #DCD4CC;
    --muted: #A79C92;
    --faint: #857B72;

    --hairline:        rgba(255, 255, 255, 0.10);
    --hairline-strong: rgba(255, 255, 255, 0.18);
    --highlight:       rgba(255, 255, 255, 0.10);

    --accent:        #E07A88;
    --accent-press:  #EA95A0;
    --accent-ink:    #2A0F13;
    --accent-tint:   rgba(224, 122, 136, 0.16);
    --accent-tint-2: rgba(224, 122, 136, 0.26);

    --class-ink: #F0B4BC;
    --ok:   var(--sage-300); --ok-tint:   rgba(156, 194, 147, 0.16); --ok-edge:   #7FA876;
    --bad:  #E79385;        --bad-tint:  rgba(231, 147, 133, 0.16); --bad-edge:  #C4685C;
    --info: #9FC0E3;        --info-tint: rgba(159, 192, 227, 0.15); --info-edge: #6E93BC;

    --glass-wall:  rgba(255, 255, 255, 0.10);
    --glass-wall-press: rgba(255, 255, 255, 0.24);
    --glass-clear: rgba(255, 255, 255, 0.08);
    --lens-top:   rgba(255, 255, 255, 0.20);
    --lens-bot:   rgba(255, 255, 255, 0.20);
    --lens-edge-t:rgba(255, 255, 255, 0.55);
    --lens-edge-b:rgba(255, 255, 255, 0.36);
    --lens-shade: rgba(0, 0, 0, 0.26);
    --lens-deep:  rgba(0, 0, 0, 0.45);
    --lens-ring: linear-gradient(155deg,
       rgba(255,255,255,.72) 0%, rgba(255,255,255,.16) 24%, rgba(255,255,255,.06) 46%,
       rgba(255,255,255,.14) 64%, rgba(255,255,255,.62) 100%);
    --lens-ring-clear: linear-gradient(155deg,
       rgba(255,255,255,.6) 0%, rgba(255,255,255,.06) 30%, rgba(255,255,255,.05) 58%,
       rgba(255,255,255,.5) 100%);
    --focus:      #E07A88;
    --focus-halo: rgba(219, 138, 102, 0.32);

    /* On dark the backdrop is pushed down instead, for the same reason. */
    --mat-bright: 0.80;
    --mat-thin:    rgba(28, 26, 24, 0.40);
    --mat-regular: rgba(24, 22, 20, 0.50);
    --mat-thick:   rgba(20, 18, 17, 0.55);
    --mat-solid:   #171514;
    --mat-edge:    inset 0 0.5px 0 rgba(255, 255, 255, 0.11);
    --mat-under:   inset 0 -0.5px 0 rgba(0, 0, 0, 0.5);

    /* On dark, elevation is mostly a lighter surface plus a lit top edge. */
    --e-1: 0 1px 2px rgba(0, 0, 0, 0.40), inset 0 0.5px 0 rgba(255, 255, 255, 0.05);
    --e-2: 0 2px 6px rgba(0, 0, 0, 0.45), 0 8px 18px -10px rgba(0, 0, 0, 0.55),
           inset 0 0.5px 0 rgba(255, 255, 255, 0.06);
    --e-3: 0 4px 12px rgba(0, 0, 0, 0.50), 0 20px 40px -16px rgba(0, 0, 0, 0.65),
           inset 0 0.5px 0 rgba(255, 255, 255, 0.08);

    --chart-1: #E07A88;
    --chart-2: #9FC0E3;
  }
}

/* iOS "Reduce Transparency": keep the geometry, drop the glass. */
@media (prefers-reduced-transparency: reduce) {
  :root {
    --blur-thin: 0px; --blur-regular: 0px; --blur-thick: 0px; --sat: 100%; --mat-bright: 1;
    --mat-thin: var(--mat-solid); --mat-regular: var(--mat-solid); --mat-thick: var(--mat-solid);
    --glass-clear: var(--surface-2);
    --glass-wall: var(--accent);
  }
  /* The lens keeps its shape and edge lighting; only the see-through goes. */
  button:not(.ev)::before, .button:not(.ev)::before { content: none; }
  button.secondary, .button.secondary, button.toggle-off, .button.toggle-off {
    background-color: var(--surface-2);
  }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root {
    --mat-thin: var(--mat-solid); --mat-regular: var(--mat-solid); --mat-thick: var(--mat-solid);
    --glass-wall: var(--accent); --glass-clear: var(--surface-2);
  }
  button:not(.ev)::before, .button:not(.ev)::before { content: none; }
}

/* ---------- Page ---------- */

html, body { overflow-x: clip; }
/* What shows through during rubber-band overscroll, behind the glass chrome. */
html { background: var(--mat-solid); }

body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--t-md);
  line-height: var(--lh-body);
  color: var(--ink);
  background: transparent;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The wash the frosted chrome refracts. Fixed, not background-attachment
   (which janks in WKWebView). */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(120% 70% at 88% -8%, var(--bg-wash-warm), transparent 62%),
    radial-gradient(100% 60% at -10% 108%, var(--bg-wash-cool), transparent 66%),
    var(--bg);
}

::selection { background: var(--accent-tint-2); color: var(--ink); }

/* ---------- Header: a translucent shelf the page slides under ---------- */

header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  height: calc(var(--header-h) + var(--sa-t));
  padding: var(--sa-t) max(var(--gutter), var(--sa-r)) 0 max(var(--gutter), var(--sa-l));
  color: var(--ink);
  background: var(--mat-regular);
  -webkit-backdrop-filter: blur(var(--blur-regular)) saturate(var(--sat)) brightness(var(--mat-bright));
          backdrop-filter: blur(var(--blur-regular)) saturate(var(--sat)) brightness(var(--mat-bright));
  box-shadow: var(--mat-edge), var(--mat-under);
  transform: translateZ(0);
}

.brand {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-lg);
  letter-spacing: var(--track-snug);
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.brand span { color: var(--muted); font-weight: 400; }

/* Tablet and up: the nav is a segmented control — one of the few places a
   fully round radius still belongs. */
nav {
  display: flex;
  gap: 2px;
  min-width: 0;
  padding: 3px;
  border-radius: var(--r-full);
  background: var(--surface-sunken);
  box-shadow: inset var(--ring);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
nav::-webkit-scrollbar { display: none; }
nav a {
  display: flex;
  align-items: center;
  min-height: 34px;
  padding: 0 var(--s-3);
  border-radius: var(--r-full);
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-1) var(--ease-std), background-color var(--dur-1) var(--ease-std);
}
nav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
  background: var(--surface-1);
  box-shadow: var(--e-1), var(--ring);
}

.who {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--muted);
  font-size: var(--t-xs);
}
.who button.link { font-size: var(--t-xs); font-weight: 600; }

/* ---------- Layout & type ---------- */

main {
  max-width: 720px;
  margin: 0 auto;
  padding: calc(var(--s-4) + var(--stick-top)) var(--gutter) var(--s-12);
  padding-left: max(var(--gutter), var(--sa-l));
  padding-right: max(var(--gutter), var(--sa-r));
}
main a { color: var(--accent); text-underline-offset: 2px; }

h1 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  margin: var(--s-2) 0 var(--s-5);
}
h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-xl);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-snug);
  margin: 0 0 var(--s-3);
}

/* ---------- Cards: physical sheets, top-lit ---------- */

.card {
  position: relative;
  background-color: var(--surface-1);
  background-image: linear-gradient(to bottom, var(--highlight), transparent 88px);
  background-repeat: no-repeat;
  border: 0;
  border-radius: var(--r-card);
  box-shadow: var(--e-1), var(--ring);
  padding: var(--pad-card);
  margin-bottom: var(--s-4);
}
@media (prefers-color-scheme: dark) {
  .card, main > .list { background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.045), transparent 88px); }
}
.card.narrow { max-width: 420px; margin: var(--s-12) auto; }
.card.narrow form > button:not(.link):not(.secondary) {
  width: 100%; min-height: 50px; border-radius: var(--r-lg); margin-top: var(--s-2);
}
.card.center { text-align: center; }
.card.raised { background-color: var(--surface-2); box-shadow: var(--e-3), var(--ring-strong); }

.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: var(--s-4); }

/* ---------- Stat tiles ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
@media (min-width: 720px) {
  .stats { grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); }
}
.card.stat, .stat {
  display: block;
  margin-bottom: 0;
  padding: var(--s-4);
  border-radius: var(--r-lg);
  text-align: left;
  color: var(--muted);
  font-size: var(--t-xs);
  font-weight: 550;
  line-height: var(--lh-snug);
}
/* The lead tile carries a clay wash so the eye lands somewhere. */
.stats > .stat:first-child {
  background-image:
    linear-gradient(to bottom, var(--accent-tint), transparent 70%),
    linear-gradient(to bottom, var(--highlight), transparent 88px);
}
.big {
  display: block;
  margin-bottom: 2px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--t-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  color: var(--ink);
  font-variant-numeric: tabular-nums lining-nums;
}
.stat a { color: var(--accent); text-decoration: none; font-weight: 600; }

.delta {
  display: inline-flex;
  align-items: center;
  margin-top: var(--s-2);
  padding: 2px var(--s-2);
  border-radius: var(--r-full);
  font-size: var(--t-2xs);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.delta.up   { background: var(--ok-tint);  color: var(--ok); }
.delta.down { background: var(--bad-tint); color: var(--bad); }
.delta.flat { background: var(--surface-sunken); color: var(--muted); }

/* ---------- Lists & tables ---------- */

.list { list-style: none; margin: 0; padding: 0; }
/* A list that isn't already inside a card becomes the card: iOS grouped
   style, one sheet with inset separators. */
main > .list {
  padding: 0 var(--pad-card);
  margin-bottom: var(--s-4);
  background-color: var(--surface-1);
  background-image: linear-gradient(to bottom, var(--highlight), transparent 88px);
  background-repeat: no-repeat;
  border-radius: var(--r-card);
  box-shadow: var(--e-1), var(--ring);
}
.list li { position: relative; display: block; padding: var(--s-3) 0; }
/* Row titles are tint-coloured to read as tappable; the underline was the
   loudest leftover from the old look. */
.list li a { text-decoration: none; }
/* iOS inset hairline: a real half-pixel, bled into the card's right padding. */
.list li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0; right: calc(var(--pad-card) * -1); bottom: 0;
  height: 1px;
  background: var(--hairline);
  transform: scaleY(0.5);
  transform-origin: bottom;
}
.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2) var(--s-4);
  flex-wrap: wrap;
  min-width: 0;
}
.row > :first-child { min-width: 0; }
/* A row that is nothing but a link somewhere: the whole row is the target and
   it carries the iOS disclosure chevron. The chevron hangs off the anchor
   because li::after is already the separator hairline. */
.list li.nav-row a {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
}
/* A long name gives way rather than shoving the badge off the row. */
.list li.nav-row a > strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list li.nav-row a::after {
  content: "";
  flex: none;
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.6px solid var(--faint);
  border-bottom: 1.6px solid var(--faint);
  transform: rotate(-45deg);
}
.member-filter { display: block; margin-bottom: var(--s-3); }
/* Filters and the create button share one row; opening the form gives it the
   full width so the fields are not squeezed in beside the pills. */
.member-bar { margin-bottom: var(--s-4); align-items: flex-start; }
.member-bar > button { font-size: var(--t-sm); }
.member-bar .add-form { margin-left: auto; }
/* An expander inside a button row gets the whole row once it is open, so its
   fields are not squeezed into whatever space the buttons left. */
.actions > .add-form[open] { flex: 1 1 100%; }
.member-bar .add-form[open] {
  margin-left: 0;
  padding: var(--pad-card);
  background-color: var(--surface-1);
  border-radius: var(--r-card);
  box-shadow: var(--e-1), var(--ring);
}
/* A badge beside the name, not a word tacked onto it. Rust text alone was too
   close to the clay of the name to read as a different thing at all — the tint
   behind it is what separates them. */
.list li.nav-row a .tag {
  flex: none;
  padding: 3px var(--s-2);
  border-radius: var(--r-full);
  background: var(--bad-tint);
  color: var(--bad);
  font-size: var(--t-2xs);
  font-weight: 650;
  letter-spacing: 0.01em;
  box-shadow: inset 0 0 0 .5px var(--bad-edge);
}

/* Label on the left, answer on the right. Its own element rather than .row,
   which .list li outranks into display:block. */
.facts { list-style: none; margin: 0; padding: 0; }
.facts li {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3) var(--s-5);
  padding: var(--s-3) 0;
  font-size: var(--t-sm);
}
.facts li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0; right: calc(var(--pad-card) * -1); bottom: 0;
  height: 1px;
  background: var(--hairline);
  transform: scaleY(0.5);
  transform-origin: bottom;
}
.facts li > span:first-child { flex: none; color: var(--muted); }
.facts li > span:last-child { text-align: right; min-width: 0; }

table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
th, td {
  text-align: left;
  padding: var(--s-3) var(--s-2);
  border-bottom: 0;
  box-shadow: inset 0 -1px 0 var(--hairline);
}
th {
  color: var(--muted);
  font-weight: 600;
  font-size: var(--t-2xs);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
}
td { font-variant-numeric: tabular-nums; }
tbody tr:hover td { background: var(--press); }

/* ---------- Forms: engraved wells ---------- */

label {
  display: block;
  margin-bottom: var(--s-3);
  font-size: var(--t-xs);
  font-weight: 550;
  color: var(--muted);
}
input, select, textarea {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-top: var(--s-1);
  padding: 10px var(--s-3);
  font: inherit;
  font-size: max(1rem, 17px); /* below 16px iOS zooms the whole viewport */
  color: var(--ink);
  background: var(--surface-sunken);
  border: 0;
  border-radius: var(--r-sm);
  box-shadow: inset var(--ring), inset 0 1px 2px rgba(29, 26, 23, 0.05);
  transition: background-color var(--dur-1) var(--ease-std), box-shadow var(--dur-1) var(--ease-std);
  -webkit-appearance: none;
  appearance: none;
}
textarea { min-height: 88px; }
input::placeholder, textarea::placeholder { color: var(--faint); }
input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--surface-1);
  box-shadow: 0 0 0 2px var(--focus), 0 0 0 6px var(--focus-halo), var(--e-1);
}

.inline-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: var(--s-3) var(--s-4);
  align-items: end;
}
.inline-form label { margin-bottom: 0; }

/* A list of things the member can be told about. It spans the whole form grid
   rather than becoming another narrow column, because each row is a sentence. */
.switches {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--s-2);
  border: 0;
  margin: 0;
  padding: var(--s-3) 0 0;
}
.switches legend {
  padding: 0;
  font-size: var(--t-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.switch {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-3);
  align-items: start;
  padding: var(--s-3);
  border-radius: var(--r-lg);
  background: var(--surface-2);
  cursor: pointer;
}
/* The form reset takes appearance off every input, which leaves a checkbox with
   nothing to draw, so the box and its tick are drawn here instead. */
.switch input {
  width: 22px;
  height: 22px;
  min-height: 0;
  margin: 1px 0 0;
  padding: 0;
  border-radius: var(--r-2xs);
  background: var(--surface-1);
  box-shadow: inset 0 0 0 1.5px var(--hairline);
  transition: background 0.15s ease, box-shadow 0.15s ease;
}
.switch input:checked {
  background: var(--accent);
  box-shadow: inset 0 0 0 1.5px var(--accent);
}
.switch input:checked::after {
  content: "";
  display: block;
  width: 5px;
  height: 10px;
  margin: 2px auto 0;
  border: solid var(--surface-1);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.switch input:focus { box-shadow: inset 0 0 0 1.5px var(--accent), 0 0 0 2px var(--focus), 0 0 0 6px var(--focus-halo); }
.switch:has(input:checked) { background: var(--surface-1); box-shadow: var(--e-1); }
.switch .tag {
  display: inline-block;
  padding: 2px var(--s-2);
  border-radius: var(--r-full);
  background: var(--accent-tint);
  color: var(--accent);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: 2px;
}

/* A line whose text is itself editable: plain text until the pencil unlocks
   it, then a shallow dent, then lifted onto the card when focused. */
.inline-edit { display: grid; gap: 2px; justify-items: start; }
.inline-edit .line { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-2); max-width: 100%; }
input.ghost {
  display: inline-block;
  width: auto;
  max-width: 100%;
  field-sizing: content;
  min-height: 32px;
  margin: 0;
  padding: 3px var(--s-2);
  font-size: inherit;
  background: transparent;
  border: 0;
  border-radius: var(--r-xs);
  box-shadow: none;
}
/* Locked, it is just text — clicks pass straight through to the row. */
input.ghost[readonly] { pointer-events: none; }
input.ghost:not([readonly]) { background: var(--surface-sunken); box-shadow: inset var(--ring); }
input.ghost:not([readonly]):hover { background: var(--press); }
input.ghost:focus {
  background: var(--surface-1);
  box-shadow: 0 0 0 2px var(--focus), 0 0 0 5px var(--focus-halo), var(--e-1);
}
input.ghost.strong { font-weight: 650; }
input.ghost.muted { color: var(--muted); }

/* ---------- Buttons: Liquid Glass ----------
   The iOS 26 material: a capsule of thick glass over a tint. The refraction
   is faked with layered gradients and a masked rim rather than a real
   backdrop-filter — the page behind a button is an almost flat linen wash, so
   sampling it buys nothing and costs an offscreen blur per button on every
   composited frame. Calendar cells (.ev) and the icon-only buttons opt out. */

button, .button {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-5);
  font: inherit;
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: var(--track-snug);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  color: var(--accent-ink);
  border: 0;
  border-radius: var(--r-full);
  /* The wall of the lens: genuinely see-through, so it refracts whatever
     passes behind it. This is the part that makes it read as glass. */
  background-color: var(--glass-wall);
  /* A shallower, hotter sample than the face would use: content stays
     recognisable through the wall instead of dissolving, which is what reads
     as thickness. Deeper blur than this and the wall goes to a flat wash;
     shallower and it picks up colour casts that fight the tint. */
  -webkit-backdrop-filter: blur(8px) saturate(220%) brightness(1.14);
          backdrop-filter: blur(8px) saturate(220%) brightness(1.14);
  box-shadow:
    inset 0 1.5px 0 var(--lens-edge-t),
    inset 0 -1.5px 0 var(--lens-edge-b),
    0 2px 6px -2px rgba(29, 26, 23, 0.22),
    var(--glow);
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-4) var(--spring), box-shadow var(--dur-1) var(--ease-std);
}
button, .button { --glow: 0 15px 28px -14px rgba(29, 26, 23, 0.42); }

/* The tinted core, floating inside the wall. Keeping the label on an opaque
   core is what lets the wall be properly transparent without the text going
   illegible — the same construction as the reference: a glass capsule with a
   solid pill inside it. */
button:where(:not(.ev):not(.link):not(.pencil-btn))::before,
.button:where(:not(.ev))::before {
  content: "";
  position: absolute;
  inset: 3.5px;
  z-index: -1;
  border-radius: var(--r-full);
  background-color: color-mix(in srgb, var(--accent) 97%, transparent);
  background-image:
    radial-gradient(150% 150% at 26% -70%, rgba(255, 255, 255, 0.30), transparent 58%),
    linear-gradient(to bottom, transparent 45%, var(--lens-shade) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    inset 0 -1px 0 rgba(255, 255, 255, 0.18),
    0 1px 3px -1px rgba(0, 0, 0, 0.30);
  transition: background-color var(--dur-1) var(--ease-std),
              transform var(--dur-press) var(--ease-out);
}

/* The specular rim tracing the wall. */
button:where(:not(.ev):not(.link):not(.pencil-btn))::after,
.button:where(:not(.ev))::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  padding: 1.6px;
  border-radius: inherit;
  pointer-events: none;
  background: var(--lens-ring);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  transition: opacity var(--dur-1) var(--ease-std);
}

/* Pressing squeezes the lens onto the page. */
/* iOS 26 presses swell rather than shrink: the glass blooms outward, brightens
   and lifts, while the core inside it pulls in slightly. */
button:not(.ev):active, .button:not(.ev):active {
  transform: scale(1.045);
  background-color: var(--glass-wall-press);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.95),
    inset 0 -2px 0 var(--lens-edge-t),
    0 4px 12px -3px rgba(29, 26, 23, 0.26),
    0 22px 40px -16px rgba(29, 26, 23, 0.45);
  transition-duration: var(--dur-press);
  transition-timing-function: var(--ease-out);
}
button:not(.ev):active::before, .button:not(.ev):active::before {
  background-color: var(--accent-press);
  transform: scale(0.97);
}
button:not(.ev):active::after, .button:not(.ev):active::after { opacity: 1; }

button.block, .button.block { width: 100%; min-height: 50px; }

/* Clear glass — Save, Reset link, Pause, an unselected segment. No core at
   all, so the card behind shows straight through. .danger changes only ink. */
button.secondary, .button.secondary,
.button.toggle-off, button.toggle-off {
  color: var(--ink-2);
  --glow: 0 10px 22px -14px rgba(29, 26, 23, 0.35);
  background-color: var(--glass-clear);
  -webkit-backdrop-filter: blur(18px) saturate(200%) brightness(1.08);
          backdrop-filter: blur(18px) saturate(200%) brightness(1.08);
}
button.secondary::before, .button.secondary::before,
.button.toggle-off::before, button.toggle-off::before { content: none; }
button.secondary::after, .button.secondary::after,
.button.toggle-off::after, button.toggle-off::after { background: var(--lens-ring-clear); }
button.secondary:active, .button.secondary:active,
.button.toggle-off:active, button.toggle-off:active {
  background-color: var(--glass-wall-press);
}
.button.toggle-off, button.toggle-off { font-weight: 500; }
button.danger, .button.danger { color: var(--bad); }

button.link {
  color: var(--accent);
  background: none;
  background-image: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  font-weight: 550;
  min-height: 44px;
  padding: 0 var(--s-2);
  margin: 0 calc(var(--s-2) * -1);
}
button.link:active { background: none; box-shadow: none; color: var(--accent-press); }
header button.link { color: var(--accent); }

.pencil-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  min-height: 0;
  margin: -6px;
  padding: 0;
  color: var(--faint);
  background: none;
  background-image: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  border-radius: var(--r-full);
}
.pencil-btn svg { width: 15px; height: 15px; display: block; }
.pencil-btn:hover { color: var(--accent); }
.pencil-btn:active { background: var(--press); color: var(--accent); }

/* One real focus ring for everything; outline follows border-radius in WebKit. */
:where(a, button, .button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}

/* A create form kept out of the way behind its own button. */
.add-form > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
  list-style: none;
  cursor: pointer;
  font-weight: 600;
}
/* Most of these summaries carry .button and are already clay-on-white; a
   bare one is a quiet text action. */
.add-form > summary:not(.button) { color: var(--accent); }
.add-form > summary::-webkit-details-marker { display: none; }
.add-form[open] > summary { margin-bottom: var(--s-3); }
.add-form[open] .inline-form {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--dur-2) var(--ease-std), transform var(--dur-2) var(--ease-out);
}
@starting-style {
  .add-form[open] .inline-form { opacity: 0; transform: translateY(-6px); }
}

.actions { display: flex; gap: var(--s-2); flex-wrap: wrap; align-items: center; position: relative; min-width: 0; }

/* Little month calendar under the Day pill. Never blurred: a backdrop-filter
   ancestor would clip it and sample the wrong backdrop. */
.day-pop {
  position: absolute;
  right: 0;
  top: calc(100% + var(--s-2));
  z-index: 30;
  width: 232px;
  padding: var(--s-3);
  background: var(--surface-2);
  border: 0;
  border-radius: var(--r-lg);
  box-shadow: var(--e-3), var(--ring-strong);
}
.day-pop-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--s-2); }
.day-pop-head strong { font-size: var(--t-sm); }
.day-pop-head button {
  min-height: 34px; padding: 0 var(--s-3); font-size: var(--t-lg);
  color: var(--accent); background: none; background-image: none; box-shadow: none;
}
.day-pop-head button:active { background: var(--press); }
/* Bare glyphs, not lenses: the tinted core would otherwise paint clay behind a
   clay arrow and make it disappear. */
.day-pop-head button::after, .day-pop-head button::before { content: none; }
.day-pop-dow, .day-pop-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 2px; text-align: center; }
.day-pop-dow span { font-size: var(--t-2xs); color: var(--muted); padding: 2px 0; }
.day-pop-grid a {
  display: flex; align-items: center; justify-content: center;
  min-height: 34px;
  border-radius: var(--r-xs);
  text-decoration: none !important;
  color: var(--ink);
  font-size: var(--t-sm);
}
.day-pop-grid a:hover { background: var(--accent-tint); color: var(--accent); }
.day-pop-grid a.today { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

@media (max-width: 400px) { th, td { padding: var(--s-3) var(--s-1); } }

@media (max-width: 720px) {
  /* Toolbar pills stay compact so five of them still fit a 320px screen. */
  .actions button, .actions .button { min-height: 40px; padding: 0 var(--s-3); font-size: var(--t-sm); }
  .actions .pencil-btn { min-height: 0; padding: 0; }
  .row { flex-direction: column; align-items: stretch; }
  .row > .actions { width: 100%; }
  /* A lone button in a row keeps its own width rather than stretching. */
  .row > .button, .row > form > .button { align-self: flex-start; }
  /* An edit form inside an action group gets its own full-width line. */
  .actions > .inline-form { flex: 1 1 100%; }
}

/* ---------- Flash: a notification card hanging under the header ---------- */

.flash {
  position: sticky;
  top: calc(var(--stick-top) + var(--s-2));
  z-index: 20;
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
  border: 0;
  border-radius: var(--r-md);
  color: var(--ink);
  font-size: var(--t-sm);
  font-weight: 500;
  background-color: var(--mat-thick);
  -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
          backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
  box-shadow: var(--e-2), var(--mat-edge), var(--ring-strong);
  animation: flash-in var(--dur-3) var(--spring) both;
}
.flash::before {
  content: "";
  flex: none;
  width: 10px; height: 10px;
  margin-top: 5px;
  border-radius: var(--r-full);
  background: var(--flash-dot);
}
.flash.ok  { --flash-dot: var(--ok);  background-image: linear-gradient(var(--ok-tint), var(--ok-tint)); }
.flash.bad { --flash-dot: var(--bad); background-image: linear-gradient(var(--bad-tint), var(--bad-tint)); }
@keyframes flash-in { from { opacity: 0; transform: translateY(-8px) scale(0.97); } }

.ok-text { color: var(--ok); font-weight: 600; }
.bad-text { color: var(--bad); font-weight: 600; }
.muted { color: var(--muted); }
.overdue { color: var(--bad); font-weight: 600; }

code {
  background: var(--surface-sunken);
  border: 0;
  padding: 2px var(--s-1);
  border-radius: var(--r-2xs);
  font-size: 0.86em;
  word-break: break-all;
}

/* ---------- QR & camera ---------- */

/* The QR itself stays on white in both themes so scanners read it. */
.qr {
  display: inline-block;
  background: #ffffff;
  padding: var(--s-4);
  border-radius: var(--r-lg);
  border: 0;
  box-shadow: var(--e-2), var(--ring);
}
.qr svg { display: block; width: min(260px, 70vw); height: auto; }

.cam-wrap { background: #000; border-radius: var(--r-lg); overflow: hidden; margin-bottom: var(--s-3); }
.cam-wrap video { display: block; width: 100%; max-height: 320px; object-fit: cover; }

/* ---------- Charts ---------- */

.chart-legend { display: flex; gap: var(--s-4); font-size: var(--t-xs); color: var(--muted); margin-bottom: var(--s-2); }
.chart-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: var(--s-1); }
.chart-scroll { overflow-x: auto; }
/* Wide data tables scroll inside their card. Without this the page-level
   overflow-x: clip would cut the last columns off with no way to reach them. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll table { min-width: max-content; }

/* ---------- Calendar ----------
   Structure is untouched: flex columns, grid rows pinned at 44px. The 44px
   also lives inline in src/routes/{admin,member}.js — the row height and the
   gradient below must always change together. */

/* Week and Day sit left; stepping through time sits right, on the same row. */
.cal-nav { display: inline-flex; align-items: center; gap: var(--s-2); margin-left: auto; }

/* Which days are on screen, in words. */
.cal-when {
  margin: 0 0 var(--s-3);
  font-size: var(--t-sm);
  font-weight: 650;
  color: var(--ink-2);
}
/* How full the days on screen are. */
.cal-load { margin: calc(var(--s-3) * -1) 0 var(--s-3); font-size: var(--t-sm); color: var(--ink-2); }
.cal-wrap { --pad-card: var(--s-2); padding: var(--s-2); overflow: visible; }
.cal { display: flex; min-width: 0; }
.cal-times {
  width: 42px;
  flex: none;
  padding-right: var(--s-1);
  color: var(--faint);
  font-size: var(--t-2xs);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.cal-day { flex: 1 1 0; min-width: 0; box-shadow: inset 1px 0 0 var(--hairline); }
.cal-day.today { background: linear-gradient(to bottom, var(--accent-tint), transparent 55%); }
.cal-day.today .cal-head { color: var(--accent); }

/* The day names stay put while the hours scroll past. Opaque rather than
   frosted: seven blurred layers would cost frames for no visible gain on a
   card that is already an opaque sheet. */
.cal-head {
  position: sticky;
  top: calc(var(--stick-top) + var(--s-2));
  z-index: 2;
  display: block;
  text-align: center;
  padding: var(--s-2) 2px;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background: var(--surface-1);
  box-shadow: var(--mat-under);
}
/* The times column has an empty header; give it the same height as the day
   names so the first hour starts under that row, not beside it. */
.cal-times .cal-head::after { content: "\00a0"; }
a.cal-head { color: inherit; text-decoration: none; }
a.cal-head:hover { color: var(--accent); }

.cal-grid {
  display: grid;
  grid-auto-rows: 44px;
  position: relative;
  border-radius: var(--r-sm);
  background-image: linear-gradient(to bottom, var(--hairline) 0 1px, transparent 1px);
  background-size: 100% 44px;
  background-position: 0 -1px;
}
@media (min-resolution: 2dppx) {
  .cal-grid {
    background-image: linear-gradient(to bottom,
      color-mix(in srgb, var(--hairline) 60%, transparent) 0 1px, transparent 1px);
  }
}

/* Event blocks: small tinted sheets with a coloured leading edge. */
.ev {
  grid-column: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  min-height: 0;
  margin: 2px;
  padding: 3px var(--s-2) 3px 7px;
  border: 0;
  border-radius: var(--r-2xs);
  font-size: var(--t-2xs);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: 0;
  text-align: left;
  text-decoration: none;
  overflow: hidden;
  white-space: normal;
  background-image: none;
  box-shadow: inset 2.5px 0 0 var(--ev-edge, transparent), inset var(--ring);
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-1) var(--ease-std);
}
.ev strong { width: 100%; font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ev span { color: inherit; opacity: 0.8; font-variant-numeric: tabular-nums; }
/* A bookable slot: the form is only a wrapper, the button fills the cell. */
.ev-slot { grid-column: 1; display: block; min-width: 0; overflow: hidden; }
.ev-slot .ev { width: calc(100% - 4px); height: calc(100% - 4px); min-width: 0; cursor: pointer; }
.ev:active { transform: scale(0.97); }

.ev-class { background-color: var(--accent-tint); color: var(--class-ink); --ev-edge: var(--accent); }
.ev-appt  { background-color: var(--info-tint);   color: var(--info);      --ev-edge: var(--info-edge); }
.ev-free  { background-color: var(--ok-tint);     color: var(--ok);        --ev-edge: var(--ok-edge); }
/* Full, and someone else's private hour: both simply mean "not yours". */
.ev-full, .ev-taken { background-color: var(--bad-tint); color: var(--bad); --ev-edge: var(--bad-edge); }
/* The one solid block on the grid: the class you are actually in. */
.ev-mine {
  background-color: var(--accent);
  color: var(--accent-ink);
  --ev-edge: transparent;
  box-shadow: var(--e-1), inset 0 0.5px 0 rgba(255, 255, 255, 0.25);
}
.ev-past { background-color: transparent; color: var(--faint); opacity: 0.55; box-shadow: inset var(--ring); }
/* Blocked reads as texture rather than colour — no hue spent on "nothing here". */
.ev-blocked {
  background-color: transparent;
  background-image: repeating-linear-gradient(135deg, var(--hairline) 0 1px, transparent 1px 6px);
  color: var(--faint);
  align-items: center;
  justify-content: center;
  box-shadow: inset var(--ring);
}
/* A free hour: quiet until touched, then it is a private-lesson request. */
.ev-open {
  background-color: transparent;
  color: var(--faint);
  align-items: center;
  justify-content: center;
  box-shadow: none;
}
.ev-open strong, .ev-open span { display: none; }
.ev-open::after {
  content: "+";
  font-size: 15px;
  line-height: 1;
  opacity: 0.28;
  transition: opacity var(--dur-1) var(--ease-std);
}
.ev-open:hover, .ev-open:active { background-color: var(--accent-tint); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-tint-2); }
.ev-open:hover::after, .ev-open:active::after { opacity: 1; }
.ev.is-selected { outline: 2px solid var(--accent); outline-offset: -2px; box-shadow: var(--e-2); }

@media (max-width: 700px) {
  .cal-head { font-size: var(--t-2xs); }
  .ev { padding-left: 6px; padding-right: var(--s-1); }
}

.cal-key {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-1) var(--s-4);
  margin: var(--s-3) 0 0;
  font-size: var(--t-xs);
  color: var(--muted);
}
.cal-key .key {
  display: inline-block;
  width: 12px; height: 12px;
  margin-right: var(--s-1);
  border-radius: 4px;
  vertical-align: -2px;
  box-shadow: inset 2.5px 0 0 var(--ev-edge, transparent), inset var(--ring);
}
.key-free { background: var(--ok-tint);  --ev-edge: var(--ok-edge); }
.key-full { background: var(--bad-tint); --ev-edge: var(--bad-edge); }
.key-mine { background: var(--accent);   --ev-edge: transparent; }
.key-open { background: transparent;     --ev-edge: transparent; }

/* ---------- Leads kanban ---------- */

.board { display: flex; gap: var(--s-3); overflow-x: auto; align-items: flex-start; }
.board-col {
  flex: 1;
  min-width: 230px;
  padding: var(--s-3);
  background: var(--surface-sunken);
  border: 0;
  border-radius: var(--r-lg);
  box-shadow: inset var(--ring);
}
.board-col h3 {
  margin: 0 0 var(--s-3);
  font-size: var(--t-2xs);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--muted);
}
.lead {
  padding: var(--s-3);
  margin-bottom: var(--s-3);
  background: var(--surface-1);
  border: 0;
  border-radius: var(--r-md);
  box-shadow: var(--e-1), var(--ring);
  font-size: var(--t-sm);
}
.lead .muted { font-size: var(--t-xs); }
.lead form { display: inline; }
.lead .lead-actions { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-top: var(--s-2); }
.lead .lead-actions button, .lead .lead-actions .button { min-height: 32px; padding: 0 var(--s-3); font-size: var(--t-2xs); }

/* A web view is not a web page. Everything in one is selectable by default, so
   pressing and holding anywhere — a calendar slot, a tab, a heading — starts a
   text selection and raises the Copy/Translate bar. No native app does that,
   and it also pre-empts any press-and-drag gesture of our own. Off by default;
   back on wherever the content is genuinely worth copying. */
body {
  -webkit-user-select: none;
          user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
}
/* user-drag is not inherited, so the elements that can actually be dragged
   have to opt out by name. */
a, button, .button, img, svg { -webkit-user-drag: none; }
input, textarea, select, code, .selectable {
  -webkit-user-select: text;
          user-select: text;
  -webkit-touch-callout: default;
}

/* ---------- Phone navigation: a floating capsule plus a detached button ----
   The iOS 26 split — the destinations you switch between most sit in the
   capsule, and one detached button beside it opens everything else.
   Nothing on .tabdock may create a backdrop root (no transform, no filter,
   no opacity < 1) or the glass on its children stops sampling the page. */

.tabdock, .tabbar { display: none; }
/* When the native shell draws its own tab bar it owns the bottom of the screen
   entirely: the web dock steps aside, and the bar's height already arrives as
   part of the safe-area inset, so the content padding must not add it twice. */
html.native-tabs .tabdock { display: none !important; }
html.native-tabs { --content-bottom: calc(var(--sa-b) + var(--s-5)); }
@media (max-width: 720px) {
  body.has-tabbar header nav { display: none; }
  body.has-tabbar main { padding-bottom: var(--content-bottom); }

  body.has-tabbar .tabdock {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    position: fixed;
    z-index: 40;
    bottom: calc(var(--sa-b) + var(--tabbar-gap));
    left: max(var(--s-3), var(--sa-l));
    right: max(var(--s-3), var(--sa-r));
    transition: transform var(--dur-2) var(--ease-std), opacity var(--dur-2) var(--ease-std);
  }

  .tabbar a, .tabmenu { -webkit-tap-highlight-color: transparent; }

  body.has-tabbar .tabbar {
    display: flex;
    position: relative;
    /* the bar owns horizontal gestures; the page must not steal the drag */
    touch-action: none;
    flex: 1 1 auto;
    min-width: 0;
    height: var(--tabbar-h);
    padding: 3px;
    border-radius: var(--r-xl);
    background: var(--mat-thick);
    -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
            backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
    box-shadow: var(--e-3), var(--mat-edge), var(--ring-strong);
    transform: translateZ(0);
  }
  .tabbar a {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    height: 50px;
    border-radius: calc(var(--r-xl) - 3px);
    font-size: var(--t-2xs);
    font-weight: 600;
    letter-spacing: 0;
    color: var(--ink-2);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
  }
  .tabbar a svg { width: 24px; height: 24px; stroke-width: 1.8; }
  /* One travelling indicator, not a highlight per tab. JS sizes it to a tab
     and drives translateX; scaleX is the liquid stretch while it moves. */
  /* The indicator is a lens sitting ON TOP of the tabs, not a tint behind
     them: it refracts what passes under it and is free to bulge past the ends
     of the bar, the way the iOS 26 one does. */
  .tabbubble {
    position: absolute;
    top: 3px;
    left: 3px;
    height: 50px;
    z-index: 2;
    border-radius: calc(var(--r-xl) - 3px);
    background: var(--accent-tint);
    -webkit-backdrop-filter: blur(0.6px) saturate(190%) brightness(1.07);
            backdrop-filter: blur(0.6px) saturate(190%) brightness(1.07);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.65),
      inset 0 -1px 0 rgba(255, 255, 255, 0.32),
      0 2px 6px -3px rgba(29, 26, 23, 0.28);
    pointer-events: none;
    transform-origin: center;
    will-change: transform;
    transition: transform var(--dur-3) var(--spring);
  }
  /* Under the lens the tab is magnified, which is the other half of the cue. */
  .tabbar a svg { transition: transform var(--dur-2) var(--spring); }
  .tabbar a[aria-current="page"] svg, .tabbar a.is-target svg { transform: scale(1.1); }
  .tabbar.is-dragging .tabbubble { transition: none; }
  .tabbubble.is-settling { transition: transform var(--dur-4) var(--spring); }

  .tabbar a::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--press);
    opacity: 0;
    transition: opacity var(--dur-1) var(--ease-std);
  }
  .tabbar a:active::before { opacity: 1; }
  .tabbar a[aria-current="page"] { color: var(--accent); font-weight: 650; }
  .tabbar a[aria-current="page"] svg { stroke-width: 2.1; }
  /* whichever tab the finger is over while dragging previews as selected */
  .tabbar a.is-target { color: var(--accent); }
  .tabbar a.is-target svg { stroke-width: 2.1; }

  /* The detached button: its own pane of the same material, no tinted core. */
  .tabmenu {
    flex: none;
    width: var(--tabbar-h);
    height: var(--tabbar-h);
    min-height: 0;
    padding: 0;
    border-radius: var(--r-full);
    color: var(--ink-2);
    background-color: var(--mat-thick);
    background-image: none;
    -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
            backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
    box-shadow: var(--e-3), var(--mat-edge), var(--ring-strong);
    transform: translateZ(0);
  }
  .tabmenu::before { content: none; }
  .tabmenu::after { background: var(--lens-ring-clear); }
  .tabmenu svg { width: 24px; height: 24px; }
  .tabmenu.is-active, .tabmenu[aria-expanded="true"] { color: var(--accent); }
  .tabmenu:active { transform: translateZ(0) scale(1.06); }

  /* The sheet of everything else, hanging above the dock. */
  .tabsheet {
    position: absolute;
    right: 0;
    bottom: calc(100% + var(--s-2));
    z-index: 41;
    display: grid;
    gap: 1px;
    min-width: 208px;
    max-width: min(320px, calc(100vw - var(--s-6)));
    /* The developer role has twelve destinations; on a short phone the sheet
       scrolls rather than running off the top of the screen. */
    max-height: calc(100vh - var(--stick-top) - var(--tabbar-h) - var(--tabbar-gap) - var(--sa-b) - var(--s-8));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: var(--s-2);
    border-radius: var(--r-lg);
    background: var(--mat-thick);
    -webkit-backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
            backdrop-filter: blur(var(--blur-thick)) saturate(var(--sat)) brightness(var(--mat-bright));
    box-shadow: var(--e-3), var(--mat-edge), var(--ring-strong);
    transform-origin: bottom right;
    animation: sheet-in var(--dur-2) var(--spring) both;
  }
  .tabsheet a, .tabsheet button.link {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    min-height: 42px;
    margin: 0;
    padding: 0 var(--s-3);
    border-radius: var(--r-sm);
    font-size: var(--t-sm);
    font-weight: 550;
    color: var(--ink);
    text-decoration: none;
    text-align: left;
  }
  .tabsheet a[aria-current="page"] { color: var(--accent); font-weight: 650; background: var(--accent-tint); }
  .tabsheet a:active, .tabsheet button.link:active { background: var(--press); }
  .tabsheet form { display: block; }
  .tabsheet button.link {
    width: 100%;
    color: var(--bad);
    box-shadow: inset 0 1px 0 var(--hairline);
    border-radius: 0 0 var(--r-sm) var(--r-sm);
    margin-top: var(--s-1);
    padding-top: var(--s-1);
  }
  @keyframes sheet-in { from { opacity: 0; transform: translateY(8px) scale(0.94); } }

  /* Keyboard up: get the whole dock out of the way. */
  body.has-tabbar:has(input:focus, textarea:focus) .tabdock {
    transform: translateY(calc(100% + var(--sa-b) + var(--tabbar-gap)));
    opacity: 0;
  }
}

/* ---------- Reduced motion ----------
   Nothing translates, scales or springs; colour and shadow still change so
   every control still confirms the tap. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
  :where(a, button, .button, input, textarea, select, .ev, .list li) {
    transition-property: background-color, color, box-shadow, outline-color !important;
    transition-duration: 100ms !important;
    transition-timing-function: linear !important;
  }
  button:active, .button:active, .ev:active { transform: none !important; }
  .flash { animation: none !important; }
  .tabbubble { transition-duration: 1ms !important; }
  .tabsheet { animation: none !important; }
}

/* ---------- Member bookings ---------- */
.bk-list { list-style: none; margin: 0; padding: 0; }
.bk-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) 0;
}
.bk-row:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0; right: calc(var(--pad-card) * -1); bottom: 0;
  height: 1px;
  background: var(--hairline);
  transform: scaleY(0.5);
  transform-origin: bottom;
}
/* The date reads like a torn-off calendar leaf; today's is clay-tinted. */
.bk-date {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 54px;
  padding: var(--s-2) 0 7px;
  border-radius: var(--r-sm);
  background: var(--surface-sunken);
  line-height: 1.05;
}
.bk-dow {
  font-size: var(--t-2xs);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
}
.bk-num {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums lining-nums;
}
.bk-mon { font-size: var(--t-2xs); color: var(--muted); }
.bk-date.today { background: var(--accent-tint); }
.bk-date.today .bk-dow, .bk-date.today .bk-mon { color: var(--accent); }
.bk-date.today .bk-num { color: var(--class-ink); }
.bk-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bk-main strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-pill {
  display: inline-block;
  padding: 2px var(--s-2);
  border-radius: var(--r-full);
  font-size: var(--t-2xs);
  font-weight: 650;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.bk-main .bk-pill { align-self: flex-start; }
.bk-pill.ok    { background: var(--ok-tint); color: var(--ok); }
.bk-pill.bad   { background: var(--bad-tint); color: var(--bad); }
.bk-pill.wait  { background: var(--accent-tint); color: var(--accent); }
.bk-pill.muted { background: var(--surface-sunken); color: var(--muted); }
.bk-act { flex: none; }
.bk-past .bk-date { opacity: 0.72; }
.bk-past .bk-main strong { color: var(--ink-2); }
.bk-empty {
  display: grid;
  justify-items: center;
  gap: var(--s-1);
  padding: var(--s-8) var(--s-4);
  text-align: center;
}
.bk-empty svg { width: 44px; height: 44px; color: var(--faint); margin-bottom: var(--s-2); }
.bk-empty .button { margin-top: var(--s-3); }

/* ---------- Native calendar sync panel (iOS app only) ---------- */
.ncal-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  font-weight: 600;
  margin-bottom: var(--s-2);
}
/* An iOS-style switch, clay when on. The site's base input rule sizes for
   text fields (full width, 44px minimum, inner shadow); every bit of that
   must be undone here or the switch renders as a padded blob. */
.ncal-toggle {
  appearance: none;
  -webkit-appearance: none;
  display: inline-block;
  flex: none;
  width: 51px;
  height: 31px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border-radius: var(--r-full);
  background: var(--linen-300);
  box-shadow: none;
  position: relative;
  transition: background 0.2s ease;
}
.ncal-toggle::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 27px; height: 27px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--e-1);
  transition: transform 0.2s ease;
}
.ncal-toggle:checked { background: var(--accent); }
.ncal-toggle:checked::after { transform: translateX(20px); }
.ncal-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-3) 0;
}
.ncal-row:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0; right: calc(var(--pad-card) * -1); bottom: 0;
  height: 1px;
  background: var(--hairline);
  transform: scaleY(0.5);
  transform-origin: bottom;
}
.ncal-row input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  display: inline-block;
  flex: none;
  width: 24px; height: 24px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border-radius: 50%;
  background: var(--surface-1);
  box-shadow: inset 0 0 0 1.5px var(--hairline-strong);
}
.ncal-row input[type="radio"]:checked {
  box-shadow: inset 0 0 0 8px var(--accent);
}

/* ---------- Header language globe (members) ---------- */
/* Rides on .pencil-btn to shed the clay button chrome. */
.lang-btn {
  flex: none;
  width: 36px;
  height: 36px;
  margin: 0;
  border-radius: var(--r-full);
  background: var(--surface-sunken);
  color: var(--ink-2);
}
.lang-btn:active { background: var(--press); }
.lang-btn svg { width: 20px; height: 20px; }

/* ============================================================
   RENOVATION LAYER — the Flow-derived architecture in El Soma clay.
   Appended last so it wins the cascade over the old glass styling;
   everything above stays as the structural base.
   ============================================================ */

/* ---------- Chrome: solid brand bar, white type ---------- */
html { background: var(--bar); }
body { background: var(--bg); }
header {
  color: var(--on-bar);
  background: var(--bar);
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  box-shadow: none;
}
.brand { color: var(--on-bar); font-weight: 800; }
.brand span { color: var(--on-bar-muted); font-weight: 400; }
nav { background: rgba(0, 0, 0, 0.12); box-shadow: none; }
nav a { color: var(--on-bar-muted); }
nav a[aria-current="page"] {
  color: var(--bar);
  background: var(--on-bar);
  box-shadow: none;
}
.who { color: var(--on-bar-muted); }
.who span { color: var(--on-bar); }
.who button.link { color: var(--on-bar); }
.lang-btn { background: var(--on-bar-chip); color: var(--on-bar); }
.lang-btn:active { background: var(--on-bar-border); }

/* The home hero: header goes transparent and sits on the gradient that the
   page itself paints, so the seam disappears. */
body.has-hero header { background: transparent; }
/* Full-bleed brand bands: escape main's column, keep content aligned to it. */
.hero, .sched-head, .id-head, .page-head {
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding-left: max(var(--gutter), calc(50vw - 360px + var(--gutter)));
  padding-right: max(var(--gutter), calc(50vw - 360px + var(--gutter)));
}

/* ---------- Flat buttons: the lens era ends here ---------- */
button:where(:not(.ev):not(.link):not(.pencil-btn))::before,
button:where(:not(.ev):not(.link):not(.pencil-btn))::after,
.button:where(:not(.ev):not(.link):not(.pencil-btn))::before,
.button:where(:not(.ev):not(.link):not(.pencil-btn))::after { content: none; }
button:not(.ev):not(.link):not(.pencil-btn), .button:not(.ev):not(.link):not(.pencil-btn) {
  border-radius: var(--r-sm);
  background-image: none;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}
button:not(.ev):not(.link):not(.pencil-btn):not(.secondary):not(.toggle-off),
.button:not(.ev):not(.link):not(.pencil-btn):not(.secondary):not(.toggle-off) { box-shadow: none; }
/* Outlined secondary — repeated class beats the flattening selector above. */
button.secondary.secondary.secondary, .button.secondary.secondary.secondary,
button.toggle-off.toggle-off.toggle-off, .button.toggle-off.toggle-off.toggle-off {
  background-color: var(--surface-1);
  color: var(--ink);
  box-shadow: inset 0 0 0 1.5px var(--hairline-strong);
}
button.secondary.secondary.danger, .button.secondary.secondary.danger { color: var(--bad); }
/* .id-avatar / .mini-avatar opt out: avatar buttons are tiles, not CTAs. */
button:not(.ev):not(.link):not(.pencil-btn):not(.secondary):not(.toggle-off):not(.id-avatar):not(.mini-avatar),
.button:not(.ev):not(.link):not(.pencil-btn):not(.secondary):not(.toggle-off) {
  background-color: var(--accent);
  color: #fff;
}
button.secondary, .button.secondary, button.toggle-off, .button.toggle-off {
  background-color: var(--surface-1);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--hairline-strong);
}
button.secondary.danger, .button.secondary.danger { color: var(--bad); }

/* ---------- Cards: flat white on grey, whisper of a shadow ---------- */
.card, main > .list {
  background-image: none;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}

/* ---------- Floating pill tab bar, reference-style ---------- */
@media (max-width: 767px) {
  .tabbar {
    background: #FCFCFC;
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
  }
  .tabbar a {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .tabbar a[aria-current="page"] { color: var(--accent); }
  .tabbubble {
    background: var(--accent-tint);
    box-shadow: none;
  }
  .tabmenu {
    background: #FCFCFC;
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10);
    color: var(--muted);
  }
  .tabmenu.is-active { color: var(--accent); }
}

/* ---------- Headings: bold sans, tighter ---------- */
h1 { font-weight: 800; }
h2 { font-weight: 700; }

/* ---------- Section header with trailing "see all" chevron ---------- */
.sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: var(--s-6) 0 var(--s-3);
}
.sec-head h2 { margin: 0; font-size: var(--t-lg); font-weight: 800; }
.sec-head a {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  color: var(--muted);
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
}
.sec-head a::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 2px solid currentColor;
  border-top: 2px solid currentColor;
  transform: rotate(45deg);
}

/* ---------- Horizontal carousels that bleed off the right edge ---------- */
.rail {
  display: flex;
  gap: var(--s-3);
  margin: 0 calc(-1 * var(--gutter));
  padding: 2px var(--gutter) var(--s-2);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { flex: none; scroll-snap-align: start; }

/* ---------- Brand media tile: the arc-pattern photo stand-in ---------- */
.tile {
  position: relative;
  display: block;
  width: 150px;
  border-radius: var(--r-xs);
  overflow: hidden;
  text-decoration: none;
  color: var(--ink);
}
.tile-art {
  position: relative;
  display: block;
  height: 110px;
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--wine-500);
}
/* Two translucent quarter-arcs, offset per-tile via --seed (0..5). */
.tile-art::before, .tile-art::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
}
.tile-art::before {
  width: 130px; height: 130px;
  right: -40px; top: calc(-58px + var(--seed, 0) * 6px);
}
.tile-art::after {
  width: 78px; height: 78px;
  left: calc(-26px + var(--seed, 0) * 4px); bottom: -30px;
  background: rgba(255, 255, 255, 0.10);
}
.tile-art > span {
  position: absolute;
  left: 10px; bottom: 8px;
  z-index: 1;
  color: #fff;
  font-size: var(--t-2xs);
  font-weight: 700;
  letter-spacing: 0.04em;
}
.tile-name {
  display: block;
  margin-top: var(--s-2);
  font-size: var(--t-sm);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tile-meta { display: block; font-size: var(--t-xs); color: var(--muted); }

/* Hue variants keyed by name hash so the rail isn't a wall of one color. */
.tile-art.v1 { background: #84343E; }
.tile-art.v2 { background: #6B2A33; }
.tile-art.v3 { background: #AC4451; }
.tile-art.v4 { background: #4A1F24; }
.tile-art.v5 { background: #93404B; }

/* ---------- Home hero ---------- */
.hero {
  margin-top: calc(-1 * (var(--s-4) + var(--stick-top)));
  margin-bottom: var(--s-2);
  padding-top: calc(var(--header-h) + var(--sa-t) + var(--s-4));
  padding-bottom: var(--s-6);
  background: linear-gradient(180deg, var(--hero-top) 0%, #37161A 45%, #6B2A33 78%, #84343E 100%);
  color: #fff;
}
.hero-greet {
  margin: 0 0 var(--s-4);
  font-size: var(--t-2xl);
  font-weight: 800;
  color: #fff;
  letter-spacing: var(--track-tight);
}
/* Attendance strip: last N days, today first. */
.streak {
  display: flex;
  gap: var(--s-3);
  margin: 0 calc(-1 * var(--gutter)) var(--s-4);
  padding: 0 var(--gutter);
  overflow-x: auto;
  scrollbar-width: none;
}
.streak::-webkit-scrollbar { display: none; }
.streak-day {
  flex: none;
  display: grid;
  justify-items: center;
  gap: 4px;
  font-size: var(--t-2xs);
  color: var(--on-bar-muted);
}
.streak-dot {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.10);
  color: rgba(255, 255, 255, 0.55);
  font-size: var(--t-xs);
  font-weight: 700;
}
.streak-day.went .streak-dot { background: rgba(255, 255, 255, 0.92); color: var(--wine-600); }
.streak-day.today .streak-dot { box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.85); }
/* Glass stat tiles riding on the gradient. */
.hero-tiles {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: var(--s-3);
}
.hero-tile {
  padding: var(--s-4);
  border-radius: var(--r-card);
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  text-decoration: none;
}
.hero-tile .label { display: block; font-size: var(--t-xs); font-weight: 700; color: var(--on-bar-muted); }
.hero-tile .big-line {
  display: block;
  margin-top: 2px;
  font-size: var(--t-xl);
  font-weight: 800;
  line-height: var(--lh-tight);
  color: #fff;
}
.hero-tile .sub { display: block; margin-top: 2px; font-size: var(--t-xs); color: var(--on-bar-muted); }
.hero-tile .bar-track {
  display: block;
  margin-top: var(--s-3);
  height: 4px;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.22);
  overflow: hidden;
}
.hero-tile .bar-fill { display: block; height: 100%; border-radius: var(--r-full); background: #fff; }
/* The milestone hexagon. */
.hex {
  width: 44px; height: 40px;
  display: grid;
  place-items: center;
  margin-bottom: var(--s-2);
  clip-path: polygon(50% 0%, 96% 25%, 96% 75%, 50% 100%, 4% 75%, 4% 25%);
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  font-weight: 800;
  font-size: var(--t-md);
}

/* ---------- Schedule: day strip + class list ---------- */
.sched-head {
  margin-top: calc(-1 * (var(--s-4) + var(--stick-top)));
  margin-bottom: var(--s-4);
  padding-top: calc(var(--header-h) + var(--sa-t) + var(--s-2));
  padding-bottom: var(--s-4);
  background: var(--bar);
  color: #fff;
}
.daystrip {
  display: flex;
  gap: var(--s-2);
  margin: 0 calc(-1 * var(--gutter));
  padding: var(--s-2) var(--gutter) 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.daystrip::-webkit-scrollbar { display: none; }
.day-chip {
  flex: none;
  display: grid;
  justify-items: center;
  gap: 1px;
  min-width: 46px;
  padding: 7px 4px 6px;
  border-radius: var(--r-lg);
  text-decoration: none;
  color: var(--on-bar-muted);
  font-size: var(--t-2xs);
  font-weight: 600;
}
.day-chip strong { font-size: var(--t-lg); font-weight: 800; color: #fff; line-height: 1.1; }
.day-chip.is-today { box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.85); }
.day-chip.is-selected { background: #fff; color: var(--wine-600); }
.day-chip.is-selected strong { color: var(--wine-600); }
.day-chip .dot { width: 4px; height: 4px; border-radius: 50%; background: rgba(255,255,255,.55); }
.day-chip.no-classes .dot { background: transparent; }
.day-chip.is-selected .dot { background: var(--wine-500); }
.sched-nav { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.sched-nav h1 { margin: 0; color: #fff; font-size: var(--t-xl); }
.sched-nav .cal-nav a { background: var(--on-bar-chip); color: #fff; box-shadow: none; }

/* Centered date chip between header and list. */
.date-chip {
  display: block;
  width: fit-content;
  margin: 0 auto var(--s-4);
  padding: 5px var(--s-4);
  border-radius: var(--r-full);
  background: var(--surface-1);
  box-shadow: 0 1px 4px rgba(0,0,0,0.05);
  color: var(--muted);
  font-size: var(--t-sm);
  font-weight: 600;
}

/* Class cards: media-left rows. */
.cls-card {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-3);
  margin-bottom: var(--s-3);
  border-radius: var(--r-card);
  background: var(--surface-1);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}
.cls-art {
  flex: none;
  width: 76px; height: 76px;
  border-radius: var(--r-xs);
  position: relative;
  overflow: hidden;
  background: var(--wine-500);
}
.cls-art::before {
  content: "";
  position: absolute;
  width: 84px; height: 84px;
  right: -30px; top: calc(-38px + var(--seed, 0) * 5px);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
}
.cls-main { flex: 1; min-width: 0; }
.cls-time { font-size: var(--t-sm); }
.cls-time strong { font-size: var(--t-md); font-weight: 800; }
.cls-time span { color: var(--muted); }
.cls-title {
  display: block;
  font-size: var(--t-md);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cls-meta { display: block; font-size: var(--t-xs); color: var(--muted); }
.cls-side {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-2);
}
.cls-spots { font-size: var(--t-xs); font-weight: 700; color: #C24034; }
.cls-spots.full { color: #4A1F24; }
.cls-spots.mine { color: var(--ok); }
.cls-side form { margin: 0; }
.cls-side button, .cls-side .button {
  min-height: 34px;
  padding: 0 var(--s-4);
  font-size: var(--t-sm);
}

/* ---------- Two-tone product card (shop) ---------- */
.pack-card {
  border-radius: var(--r-card);
  overflow: hidden;
  background: var(--surface-1);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
  margin-bottom: var(--s-3);
}
.pack-band {
  position: relative;
  padding: var(--s-4);
  background: var(--wine-500);
  color: #fff;
  overflow: hidden;
}
.pack-band::after {
  content: "";
  position: absolute;
  width: 120px; height: 120px;
  right: -36px; top: -52px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.13);
}
.pack-band .n { font-size: 30px; font-weight: 800; line-height: 1; }
.pack-band .w { font-size: var(--t-sm); font-weight: 600; margin-left: 4px; }
.pack-body { padding: var(--s-4); }
.pack-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.pack-name { font-size: var(--t-md); font-weight: 700; }
.pack-price { font-size: var(--t-lg); font-weight: 800; }
.pack-chip {
  display: inline-block;
  margin-top: var(--s-1);
  padding: 2px var(--s-2);
  border-radius: var(--r-full);
  background: var(--surface-sunken);
  color: var(--ink-2);
  font-size: var(--t-2xs);
  font-weight: 700;
}
.pack-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-3); }

/* ---------- Profile-style identity header (settings) ---------- */
.id-head {
  margin-top: calc(-1 * (var(--s-4) + var(--stick-top)));
  margin-bottom: var(--s-4);
  padding-top: calc(var(--header-h) + var(--sa-t) + var(--s-4));
  padding-bottom: var(--s-5);
  background: var(--bar);
  color: #fff;
  display: flex;
  align-items: center;
  gap: var(--s-4);
}
.id-avatar {
  flex: none;
  width: 64px; height: 64px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--on-bar-chip);
  color: #fff;
  font-size: var(--t-xl);
  font-weight: 800;
}
.id-avatar img, .mini-avatar img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}
/* The Settings avatar is a real button; strip the whole glass-capsule kit
   (wall, core, rim, press swell — their selectors run up to (0,3,1)) so it
   stays the same square tile, and hang a small camera chip on the corner as
   the "this is tappable" hint. */
button.id-avatar.id-avatar.id-avatar {
  position: relative;
  overflow: visible;
  display: grid;
  place-items: center;
  width: 64px; height: 64px;
  padding: 0;
  min-height: 0;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--on-bar-chip);
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  box-shadow: none;
  color: #fff;
  font: inherit;
  font-size: var(--t-xl);
  font-weight: 800;
}
button.id-avatar.id-avatar.id-avatar::before,
button.id-avatar.id-avatar.id-avatar::after { content: none; }
button.id-avatar.id-avatar.id-avatar:active {
  transform: scale(0.97);
  background: var(--on-bar-chip);
  box-shadow: none;
}
button.id-avatar img { border-radius: var(--r-sm); }

/* Full-screen framing step after picking a photo: a square window on a dark
   stage, the photo panning/zooming behind it, Cancel/Choose underneath. */
.crop-wrap {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: #141210;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
  padding: var(--s-4);
  padding-bottom: max(var(--s-4), env(safe-area-inset-bottom));
}
.crop-frame {
  position: relative;
  width: min(80vw, 340px, 55vh);
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--r-md);
  outline: 1.5px solid rgba(255, 255, 255, 0.4);
  touch-action: none;
  cursor: grab;
  background: #000;
}
.crop-frame img {
  position: absolute;
  left: 0; top: 0;
  max-width: none;
  will-change: transform;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}
.crop-hint { color: rgba(255, 255, 255, 0.7); font-size: var(--t-sm); margin: 0; }
.crop-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  width: min(80vw, 340px);
}
.crop-actions button.link { color: #fff; }
.cam-badge {
  position: absolute;
  right: -6px; bottom: -6px;
  width: 24px; height: 24px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #fff;
  color: var(--bar);
  box-shadow: 0 1px 4px rgb(0 0 0 / 25%);
}
/* Same affordance at list-row size (staff page mini avatars). */
button.mini-avatar.mini-avatar.mini-avatar {
  position: relative;
  overflow: visible;
  display: inline-grid;
  place-items: center;
  width: 34px; height: 34px;
  padding: 0;
  min-height: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent-tint);
  box-shadow: none;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  color: var(--accent);
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 800;
  cursor: pointer;
}
button.mini-avatar.mini-avatar.mini-avatar:active { transform: scale(0.95); }
button.mini-avatar.mini-avatar.mini-avatar::before,
button.mini-avatar.mini-avatar.mini-avatar::after { content: none; }
.cam-badge-sm {
  right: -4px; bottom: -4px;
  width: 16px; height: 16px;
}
/* Tiny round trainer photo inline with the instructor name on class cards. */
.tr-chip {
  width: 18px; height: 18px;
  border-radius: 50%;
  object-fit: cover;
  vertical-align: -4px;
  margin-right: 4px;
}
.id-head .who-name { font-size: var(--t-lg); font-weight: 800; }
.id-head .who-mail { font-size: var(--t-xs); color: var(--on-bar-muted); }
/* Reference-style edit pencil: a soft chip square pinned to the right. */
.id-head .id-edit {
  margin-left: auto;
  flex: none;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--on-bar-chip);
  color: #fff;
}
.id-head .id-edit svg { width: 18px; height: 18px; }
.id-head .id-edit:active { background: rgba(255, 255, 255, 0.28); }

/* Full-bleed hairline row list (reference profile style). */
.plain-list { list-style: none; margin: 0 calc(-1 * var(--gutter)); padding: 0; background: var(--surface-1); }
.plain-list li { position: relative; }
.plain-list li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--hairline);
}
.plain-list a, .plain-list button.link {
  display: block;
  width: 100%;
  padding: var(--s-4) var(--gutter);
  color: var(--ink);
  font-size: var(--t-md);
  font-weight: 500;
  text-align: left;
  text-decoration: none;
}

/* Connect / info card with tinted round icon. */
.connect-card {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4);
  border-radius: var(--r-card);
  background: var(--surface-1);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
}
.connect-card .ic {
  flex: none;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
}
.connect-card .tt { font-size: var(--t-sm); font-weight: 700; }
.connect-card .ss { font-size: var(--t-xs); color: var(--muted); }

/* ---------- Language flags ---------- */
.lang-btn { font-size: 19px; line-height: 1; }
.lang-link { display: inline-flex; align-items: center; gap: 6px; }
.lang-link .flag { font-size: 18px; line-height: 1; }
.lang-btn, .lang-link { text-decoration: none; }

/* ---------- Header action chips & the Contact us sheet ---------- */
.head-actions { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
.scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(0, 0, 0, 0.45);
}
.sheet {
  position: fixed;
  left: 50%;
  bottom: 0;
  z-index: 61;
  width: min(100%, 720px);
  transform: translateX(-50%);
  padding: var(--s-3) var(--gutter) calc(var(--s-8) + var(--sa-b));
  background: var(--surface-1);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: 0 -12px 48px rgba(0, 0, 0, 0.18);
  /* A tall sheet scrolls inside itself; the page behind stays where it is. */
  max-height: calc(100dvh - var(--sa-t) - 40px);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.sheet h2 { margin: 0 0 var(--s-1); font-size: var(--t-xl); font-weight: 800; }
.sheet .connect-card { margin-top: var(--s-3); box-shadow: inset 0 0 0 1px var(--hairline); }
.grabber {
  display: block;
  width: 40px;
  height: 5px;
  margin: 0 auto var(--s-4);
  border-radius: var(--r-full);
  background: var(--hairline-strong);
}
.connect-card, .connect-card .tt { color: var(--ink); text-decoration: none; }
.connect-card .ss { text-decoration: none; }


/* ---------- Staff page-head: the flat clay title band ---------- */
.page-head {
  margin-top: calc(-1 * (var(--s-4) + var(--stick-top)));
  margin-bottom: var(--s-4);
  padding-top: calc(var(--header-h) + var(--sa-t) + var(--s-4));
  padding-bottom: var(--s-4);
  background: var(--bar);
  color: #fff;
}
.page-head h1 { margin: 0; color: #fff; font-size: var(--t-xl); }
.page-head p, .page-head .muted, .page-head .cal-when, .page-head .cal-load {
  color: var(--on-bar-muted);
  margin: var(--s-1) 0 0;
}
.page-head .cal-load strong, .page-head p strong { color: #fff; }
.page-head .cal-load .bad-text, .page-head .cal-load .ok-text { color: #fff; font-weight: 700; }
/* Controls riding on the band become translucent chips; the active one is a
   solid white pill, same grammar as the day strip. */
.page-head .button, .page-head button:not(.link) {
  background: var(--on-bar-chip);
  color: #fff;
  box-shadow: none;
}
.page-head .button[aria-current="true"], .page-head .day-chip.is-selected {
  background: #fff;
  color: var(--bar);
}
.page-head .row { align-items: center; }
/* Dashboard tiles inside the band reuse the hero-tile glass. */
.page-head .hero-tiles {
  margin-top: var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}
.page-head .hero-tile .delta { background: rgba(255, 255, 255, 0.16); color: #fff; }
/* The month picker popover keeps its light surface even inside the band. */
.page-head .day-pop { color: var(--ink); }
.page-head .day-pop button { background: transparent; color: var(--ink); }

/* Small avatar chip for people rows. */
.mini-avatar {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-right: var(--s-2);
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--accent);
  font-size: var(--t-sm);
  font-weight: 800;
  flex: none;
}
/* Inside the band, inactive toggles must stay chips — outrank the tripled
   white secondary rule. */
.page-head .button.toggle-off.toggle-off.toggle-off,
.page-head button.toggle-off.toggle-off.toggle-off,
.page-head button.secondary.secondary.secondary {
  background: var(--on-bar-chip);
  color: #fff;
  box-shadow: none;
}

/* ---------- Progress: goal ring, month calendar, badges ---------- */
.prog-hero {
  margin-top: calc(-1 * (var(--s-4) + var(--stick-top)));
  margin-bottom: var(--s-4);
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding: calc(var(--header-h) + var(--sa-t) + var(--s-4)) max(var(--gutter), calc(50vw - 360px + var(--gutter))) var(--s-6);
  background: linear-gradient(180deg, var(--hero-top) 0%, #4A1F24 55%, #84343E 100%);
  color: #fff;
  text-align: center;
}
.prog-tabs { display: flex; justify-content: center; gap: var(--s-6); margin-bottom: var(--s-4); }
.prog-tabs a { color: rgba(255,255,255,.55); font-size: var(--t-lg); font-weight: 600; text-decoration: none; }
.prog-tabs a.is-active { color: #fff; font-weight: 800; }
.prog-ring { position: relative; display: inline-block; margin: var(--s-2) auto; }
.prog-center {
  position: absolute; inset: 0;
  display: grid; place-content: center; gap: 2px;
}
.prog-center strong { font-size: 44px; font-weight: 800; line-height: 1; }
.prog-center .pc-of { font-size: var(--t-lg); color: rgba(255,255,255,.6); }
.prog-center .pc-sub { font-size: var(--t-xs); color: rgba(255,255,255,.65); }
.prog-center .flame { font-size: 22px; }
.prog-edit {
  display: inline-block;
  margin-top: var(--s-3);
  background: none !important;
  color: #fff !important;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  box-shadow: none !important;
  min-height: 0;
  padding: var(--s-2);
}
.goal-tile .ring { display: block; margin-bottom: var(--s-2); }
.hex-big {
  width: 92px; height: 84px;
  font-size: var(--t-2xl);
  margin: var(--s-2) auto;
  background: rgba(255,255,255,.14);
}
.hex-big.earned { background: rgba(255,255,255,.92); color: var(--wine-600); }
.prog-caption { margin: var(--s-2) 0 0; color: #fff; font-weight: 700; }
.prog-caption.sub { color: rgba(255,255,255,.65); font-weight: 400; font-size: var(--t-sm); }
.prog-bar { max-width: 300px; margin: var(--s-3) auto 0; display: block; }
.mc-dow, .mc-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; justify-items: center; }
.mc-dow { color: var(--muted); font-size: var(--t-xs); font-weight: 700; margin-bottom: var(--s-2); }
.mc-day {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface-sunken);
  color: var(--ink-2);
  font-size: var(--t-sm);
  font-weight: 600;
}
.mc-day.went { background: var(--accent); color: #fff; }
.mc-day.today { box-shadow: inset 0 0 0 1.5px var(--accent); color: var(--accent); }
.mc-day.future { color: var(--faint); background: transparent; }
.badge-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-4); }
.badge { display: grid; justify-items: center; gap: 4px; font-size: var(--t-2xs); color: var(--muted); font-weight: 600; }
.badge .hex { background: var(--surface-sunken); color: var(--faint); margin: 0; }
.badge.earned .hex { background: var(--accent); color: #fff; outline: none; }
.badge.earned { color: var(--ink); }
.tier-emoji { font-size: 40px; display: block; }

/* ---------- Class photos, detail page, filters ---------- */
.tile-art img, .cls-art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tile-art > span { z-index: 1; text-shadow: 0 1px 6px rgba(0,0,0,.45); }
.cls-art { display: block; }
.cls-main { text-decoration: none; color: var(--ink); }
.filter-row {
  display: flex;
  gap: var(--s-2);
  margin-top: var(--s-3);
  overflow-x: auto;
  scrollbar-width: none;
}
.filter-row::-webkit-scrollbar { display: none; }
.filter-pill {
  flex: none;
  min-height: 34px;
  padding: 0 var(--s-4);
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.16) !important;
  color: #fff !important;
  font-size: var(--t-sm);
  font-weight: 600;
  box-shadow: none !important;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.f-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-3) 0;
}
.f-row:not(:last-of-type) { border-bottom: 1px solid var(--hairline); }
.f-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 24px; height: 24px;
  min-height: 0;
  margin: 0; padding: 0;
  border-radius: 50%;
  background: var(--surface-sunken);
  color: var(--accent);
  display: grid;
  place-items: center;
}
.f-row input[type="checkbox"]:checked::after {
  content: "✓";
  color: var(--accent);
  font-weight: 800;
}
.cls-hero {
  position: relative;
  margin: calc(-1 * (var(--s-4) + var(--stick-top))) calc(50% - 50vw) 0;
  height: 280px;
  overflow: hidden;
}
.cls-hero img { width: 100%; height: 100%; object-fit: cover; }
.hero-btn {
  position: absolute;
  top: calc(var(--sa-t) + var(--header-h) + 2px);
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  min-height: 0;
  padding: 0;
  border-radius: var(--r-xs);
  background: rgba(0, 0, 0, 0.34) !important;
  color: #fff !important;
  font-size: 20px;
  text-decoration: none;
  box-shadow: none !important;
  right: var(--gutter);
}
.hero-btn.back { left: var(--gutter); right: auto; }
.cls-sheet {
  position: relative;
  margin: -28px calc(-1 * var(--gutter)) 0;
  padding: var(--s-6) var(--gutter) var(--s-8);
  background: var(--surface-1);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
}
.eyebrow {
  font-size: var(--t-2xs);
  font-weight: 700;
  letter-spacing: 0.09em;
  color: var(--muted);
}
.hairline { border: 0; height: 1px; background: var(--hairline); margin: var(--s-4) 0; }
.inst-row { display: flex; align-items: center; margin: 0; font-weight: 600; }
.cls-cta { margin-top: var(--s-6); }
.toast {
  position: fixed;
  top: calc(var(--sa-t) + var(--header-h) + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 80;
  padding: 10px 18px;
  border-radius: var(--r-full);
  background: #1A1A1A;
  color: #fff;
  font-size: var(--t-sm);
  font-weight: 600;
}

/* ---------- Studio page & referral ---------- */
.studio-photo { height: 190px; border-radius: var(--r-card); }
.refer-code {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-sm);
  background: var(--surface-sunken);
  font-size: var(--t-lg);
  letter-spacing: 0.12em;
}

/* ---------- Shop hub, store, cart, gifts ---------- */
.shop-nav { display: flex; gap: var(--s-2); margin-bottom: var(--s-4); flex-wrap: wrap; }
.shop-tab {
  padding: 8px var(--s-4);
  border-radius: var(--r-full);
  background: var(--surface-1);
  box-shadow: 0 1px 4px rgba(0,0,0,.05);
  color: var(--muted);
  font-weight: 700;
  font-size: var(--t-sm);
  text-decoration: none;
}
.shop-tab.is-active { background: var(--accent); color: #fff; }
.shop-tab.cart { margin-left: auto; }
.gift-grid, .prod-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.gift-grid .pack-card { margin: 0; text-decoration: none; color: var(--ink); }
.gift-grid .pack-band::after { width: 90px; height: 90px; right: -26px; top: -40px; }
.prod-card {
  background: var(--surface-1);
  border-radius: var(--r-card);
  box-shadow: 0 1px 4px rgba(0,0,0,.04);
  overflow: hidden;
  text-decoration: none;
  color: var(--ink);
  display: block;
  padding-bottom: var(--s-3);
}
.prod-img { display: block; height: 150px; overflow: hidden; }
.prod-img img { width: 100%; height: 100%; object-fit: cover; }
.prod-img.sm { width: 56px; height: 56px; border-radius: var(--r-xs); flex: none; }
.prod-name { display: block; padding: var(--s-2) var(--s-3) 0; font-weight: 700; font-size: var(--t-sm); }
.prod-price { display: block; padding: 0 var(--s-3); font-weight: 800; }
.store-search input { margin-bottom: var(--s-4); }
.cart-line { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.qty-form { display: flex; align-items: center; gap: var(--s-2); }
.qty-form button { min-height: 34px; width: 34px; padding: 0; }
.qty-form span { min-width: 20px; text-align: center; font-weight: 700; }

/* ---------- Onboarding walkthrough (bare full-screen page) ---------- */
.obf-body { background: #1F0C0F; overflow: hidden; }
.obf-rail {
  display: flex;
  height: 100dvh;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.obf-rail::-webkit-scrollbar { display: none; }
.obf-slide {
  position: relative;
  flex: none;
  width: 100vw;
  height: 100%;
  scroll-snap-align: center;
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: flex-end;
}
.obf-slide::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(20,10,6,0.15) 30%, rgba(20,10,6,0.82) 100%);
}
.obf-text {
  position: relative;
  z-index: 1;
  padding: 0 var(--gutter) calc(120px + var(--sa-b));
  color: #fff;
}
.obf-text h2 { font-size: 27px; font-weight: 800; margin: 0 0 var(--s-2); }
.obf-text p { margin: 0; color: rgba(255,255,255,0.78); font-size: var(--t-md); line-height: 1.5; }
.obf-foot {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--s-6) + var(--sa-b));
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--gutter);
}
.obf-foot a { text-decoration: none; }
#ob-skip { color: rgba(255,255,255,0.65); font-weight: 600; font-size: var(--t-sm); }
.obf-next {
  min-width: 108px;
  padding: 12px var(--s-5);
  border-radius: var(--r-full);
  background: #fff;
  color: var(--wine-600);
  font-weight: 800;
  text-align: center;
}
.ob-dots { display: flex; gap: 7px; }
.ob-dots i { width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,0.35); }
.ob-dots i.on { background: #fff; }

/* ---------- Updates: Home inbox and the archive page ---------- */
/* On Home each unread update is one tappable row: title, a single truncated
   line of body, the time. The row is the link, in ink rather than tint, so
   three of them read as an inbox and not as three buttons. */
.upd-list li a { display: block; color: inherit; text-decoration: none; }
.upd-list strong { display: block; font-weight: 700; }
.upd-body {
  display: block;
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.upd-text { display: block; color: var(--ink-2); }
.upd-when { display: block; margin-top: 2px; color: var(--muted); font-size: var(--t-sm); }
.upd-more {
  display: block;
  padding: var(--s-3) 0 var(--s-1);
  color: var(--muted);
  font-size: var(--t-sm);
  font-weight: 650;
  text-decoration: none;
}
/* Archive: a clay dot marks what is new on this visit. */
.list li.upd-row { padding-left: var(--s-4); }
.upd-row.upd-new::before {
  content: "";
  position: absolute;
  left: 0; top: calc(var(--s-3) + 0.55em);
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
.upd-row:not(.upd-new) { color: var(--muted); }
.upd-row:not(.upd-new) .upd-text { color: var(--muted); }

/* ---------- Staff dashboard ---------- */
/* KPI tiles wrap to two per row on phones, three on wider screens. */
.page-head .kpi-tiles { grid-template-columns: 1fr 1fr; }
@media (min-width: 720px) { .page-head .kpi-tiles { grid-template-columns: repeat(3, 1fr); } }
.kpi-tiles .hero-tile .delta { margin-top: var(--s-1); }
/* One row of the things a desk does most; the news form drops open below. */
.quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-4);
}
.quick-actions .add-form[open] {
  flex: 1 1 100%;
  padding: var(--pad-card);
  background-color: var(--surface-1);
  border-radius: var(--r-card);
  box-shadow: var(--e-1), var(--ring);
}
.quick-actions .add-form[open] summary { margin-bottom: var(--s-3); }
/* Needs attention: a count bubble, a plain sentence, names underneath. */
.att-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 40px;
  color: inherit;
  text-decoration: none;
}
a.att-row::after {
  content: "";
  flex: none;
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 1.6px solid var(--faint);
  border-bottom: 1.6px solid var(--faint);
  transform: rotate(-45deg);
}
.att-count {
  flex: none;
  min-width: 30px;
  padding: 0 var(--s-2);
  height: 30px;
  display: inline-grid;
  place-items: center;
  border-radius: var(--r-full);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 800;
  font-size: var(--t-sm);
}
.att-label { font-weight: 650; }
.att-detail { margin: 0 0 var(--s-1) calc(30px + var(--s-3)); font-size: var(--t-sm); color: var(--ink-2); }
.att-detail a { font-weight: 650; text-decoration: none; }
/* Today / Tomorrow rows: time, title and trainer, a fill bar, a note. */
.list li.cls-row { padding: 0; }
.cls-row a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  color: inherit;
  text-decoration: none;
}
.cls-time {
  flex: none;
  width: 50px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.cls-past .cls-time { color: var(--muted); }
.cls-main { flex: 1; min-width: 0; display: block; }
.cls-main strong { display: block; }
.cls-main .muted { display: block; font-size: var(--t-sm); }
.fill-track {
  display: block;
  margin-top: var(--s-2);
  height: 5px;
  border-radius: var(--r-full);
  background: var(--surface-sunken);
  overflow: hidden;
}
.fill-fill { display: block; height: 100%; border-radius: var(--r-full); background: var(--accent); }
.fill-fill.full { background: var(--ok); }
.cls-past .fill-fill { background: var(--faint); }
/* The viewer's own classes: a soft accent wash across the row. */
.list li.cls-mine { margin: 0 calc(-1 * var(--pad-card)); padding: 0 var(--pad-card); background: var(--accent-tint); }
.list li.cls-mine::after { display: none; }
.pill {
  flex: none;
  padding: 3px var(--s-2);
  border-radius: var(--r-full);
  font-size: var(--t-2xs);
  font-weight: 700;
  white-space: nowrap;
}
.pill.warn { background: var(--bad-tint); color: var(--bad); }
.pill.info { background: var(--info-tint); color: var(--info); }
/* Sub-headings inside a card. */
.sub-h {
  margin: var(--s-4) 0 var(--s-1);
  font-size: var(--t-2xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.card h2 + .sub-h { margin-top: var(--s-2); }
/* Ranked bars: the top item fills the track, the rest are relative to it. */
.rank-list { list-style: none; margin: 0; padding: 0; }
.rank-list li {
  display: grid;
  grid-template-columns: minmax(90px, 38%) 1fr auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) 0;
}
.rank-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 650; }
.rank-track { display: block; height: 8px; border-radius: var(--r-full); background: var(--surface-sunken); overflow: hidden; }
.rank-bar { display: block; height: 100%; border-radius: var(--r-full); background: var(--chart-1); }
.rank-n { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--ink-2); }
.feed li { font-size: var(--t-sm); }
.feed a { text-decoration: none; }

/* Every band fades like the home hero, members and staff alike; the header
   sits transparent on top of it. */
body.has-hero .page-head, body.has-hero .sched-head, body.has-hero .id-head {
  background: linear-gradient(180deg, var(--hero-top) 0%, #37161A 45%, #6B2A33 78%, #84343E 100%);
}
.page-head.dash-head { padding-bottom: var(--s-6); }
/* ---------- Logged-out stage: photo under the fade, card on top ---------- */
/* The photo lives on a fixed pseudo-element behind everything; html and body
   stay transparent so nothing paints over it. */
html.auth-root, body.auth-page { background: transparent; }
body.auth-page::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(31, 12, 15, 0.80) 0%, rgba(55, 22, 26, 0.55) 40%, rgba(107, 42, 51, 0.62) 72%, rgba(132, 52, 62, 0.88) 100%),
    var(--hero-top) url("/img/studio.jpg") center / cover no-repeat;
}
body.auth-page main { min-height: 100dvh; display: flex; flex-direction: column; }
.auth-hero {
  margin-top: calc(var(--header-h) + var(--sa-t) + var(--s-8));
  margin-bottom: var(--s-5);
  color: #fff;
}
.auth-hero h1 { margin: 0; font-size: clamp(30px, 8vw, 40px); line-height: 1.05; letter-spacing: -0.01em; }
.auth-hero p { margin: var(--s-2) 0 0; font-size: var(--t-md); color: rgba(255, 255, 255, 0.72); }
body.auth-page .card.narrow { margin: 0 auto; width: 100%; }
body.auth-page .flash { margin-top: var(--s-4); }
.auth-foot {
  margin-top: auto;
  padding: var(--s-8) 0 calc(var(--s-6) + var(--sa-b, 0px));
  text-align: center;
  color: rgba(255, 255, 255, 0.7);
  font-size: var(--t-sm);
}
.auth-foot p { margin: 0 0 var(--s-3); }
.auth-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); }
.auth-chips a {
  padding: 8px 14px;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  color: #fff;
  font-weight: 650;
  text-decoration: none;
}
@media (min-width: 720px) {
  .auth-hero { text-align: center; }
}

/* ---------- Shop: one card per lesson type, sizes in a chooser ---------- */
.size-seg { display: flex; gap: var(--s-2); margin-bottom: var(--s-3); }
.size-seg .size-opt.secondary.secondary.secondary {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-height: 52px;
  padding: var(--s-2) var(--s-1);
  border-radius: var(--r-lg);
  background: var(--surface-sunken);
  color: var(--ink);
  box-shadow: none;
}
.size-seg .size-opt b { font-size: var(--t-lg); font-weight: 800; line-height: 1; }
.size-seg .size-opt small { font-size: var(--t-2xs); font-weight: 650; color: var(--muted); }
.size-seg .size-opt.is-on.is-on.is-on { background: var(--accent); color: var(--accent-ink); }
.size-seg .size-opt.is-on small { color: rgba(255, 255, 255, 0.78); }
.pack-pick .pack-buy { width: 100%; margin-top: var(--s-3); }
.sheet .inline-form { display: flex; flex-direction: column; gap: var(--s-2); align-items: stretch; }
.sheet .inline-form label { width: 100%; flex: none; }
.sheet .inline-form select, .sheet .inline-form input, .sheet .inline-form button { width: 100%; }
/* Photo header: the lesson type's own picture, its name in the corner. */
.pack-photo { position: relative; height: 128px; overflow: hidden; background: var(--wine-600); }
.pack-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pack-photo::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(31, 12, 15, 0) 35%, rgba(31, 12, 15, 0.72) 100%);
}
.pack-photo .pack-type {
  position: absolute; left: var(--s-4); bottom: var(--s-3); z-index: 1;
  color: #fff; font-size: var(--t-lg); font-weight: 800; letter-spacing: -0.01em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}
.pack-pick + .pack-pick { margin-top: var(--s-4); }

/* ---------- Weekly schedule board ---------- */
.wk-board { display: grid; gap: var(--s-3); }
@media (min-width: 720px) { .wk-board { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1400px) { .wk-board { grid-template-columns: repeat(6, 1fr); } }
.wk-day {
  padding: var(--s-3);
  border-radius: var(--r-card);
  background: var(--surface-1);
  box-shadow: var(--e-1), var(--ring);
}
/* The day header is the fold: tap to open or close. */
.wk-day > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  list-style: none; cursor: pointer; min-height: 32px; user-select: none;
}
.wk-day > summary::-webkit-details-marker { display: none; }
.wk-day > summary::after {
  content: ""; flex: none; width: 8px; height: 8px; margin-left: auto;
  border-right: 1.6px solid var(--faint); border-bottom: 1.6px solid var(--faint);
  transform: rotate(45deg); transition: transform .15s;
}
.wk-day[open] > summary::after { transform: rotate(-135deg); }
.wk-day[open] > summary { margin-bottom: var(--s-2); }
.wk-day-name { font-size: var(--t-md); font-weight: 800; }
.wk-day > summary .muted { font-weight: 600; font-size: var(--t-sm); }
.wk-empty { margin: 0; }
/* A chip is a whole class: time, title, and the small facts. */
/* Chips ride .secondary to escape the filled-button rule, then restyle. */
.wk-chip.secondary.secondary.secondary.secondary {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: var(--s-2);
  align-items: baseline;
  width: 100%;
  margin: 0 0 var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-lg);
  background: var(--surface-sunken);
  color: var(--ink);
  text-align: left;
  box-shadow: none;
}
.wk-chip b { grid-row: 1 / 3; font-variant-numeric: tabular-nums; color: var(--accent); }
.wk-chip span { font-weight: 700; line-height: 1.2; }
.wk-chip small { font-size: var(--t-2xs); color: var(--muted); }
.wk-chip.is-paused.is-paused.is-paused.is-paused { opacity: 0.55; background: repeating-linear-gradient(135deg, var(--surface-sunken) 0 8px, transparent 8px 12px); }
/* Day tick-boxes for creating or copying a class on several days. */
.day-boxes { display: flex; flex-wrap: wrap; gap: var(--s-2); width: 100%; }
.day-box { position: relative; }
.day-box input { position: absolute; opacity: 0; inset: 0; }
.day-box span {
  display: inline-block;
  padding: 6px 12px;
  border-radius: var(--r-full);
  background: var(--surface-sunken);
  font-weight: 700;
  font-size: var(--t-sm);
}
.day-box input:checked + span { background: var(--accent); color: var(--accent-ink); }
.day-box input:disabled + span { opacity: 0.4; }
.day-box input:focus-visible + span { outline: 2px solid var(--focus); }
/* Member picker in the schedule sheet: a short scrolling list of tick rows. */
.pick-list { width: 100%; max-height: 220px; overflow-y: auto; border-radius: var(--r-lg); background: var(--surface-sunken); padding: var(--s-1) 0; }
.pick-row { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-3); cursor: pointer; }
.sheet .inline-form .pick-row input[type="checkbox"], .pick-row input[type="checkbox"] {
  appearance: auto; -webkit-appearance: checkbox;
  flex: none; width: 22px; height: 22px; min-height: 0; margin: 0; padding: 0;
  border: 0; background: none; box-shadow: none; border-radius: 4px;
  accent-color: var(--accent);
}
.pick-row span { flex: 1; min-width: 0; }
.sub-h #tpl-reg-count { text-transform: none; letter-spacing: 0; font-weight: 600; }
.pick-row.is-off { opacity: 0.45; }
.sheet .inline-form #tpl-reg-filter { width: 100%; }

/* Google / Apple sign-in on the logged-out screens */
.oauth-or { display: flex; align-items: center; gap: var(--s-3); margin: var(--s-4) 0 var(--s-3); color: var(--muted); font-size: var(--t-sm); }
.oauth-or::before, .oauth-or::after { content: ""; flex: 1; height: 1px; background: var(--line, rgba(0,0,0,0.12)); }
.oauth-btns { display: grid; gap: var(--s-2); }
.oauth-btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 46px;
  border-radius: 12px; font-weight: 600; font-size: var(--t-md); text-decoration: none; border: 1px solid rgba(0,0,0,0.16); }
.oauth-btn svg { width: 18px; height: 18px; flex: none; }
.oauth-btn.google { background: #fff; color: #1f1f1f; }
.oauth-btn.apple { background: #000; color: #fff; border-color: #000; }
