/* ══════════════════════════════════════════════════════════════════════════
   FITNATION — the app layer.

   Loaded AFTER styles.css / book.css / member.css, so it refines what is
   already there rather than replacing it. Nothing in here changes what a
   control does; it changes how it feels.

   Written for the phone first, because that is where nine customers in ten
   are. Every animation moves only `transform` and `opacity` — the two things
   a phone GPU can do for free — so a mid-range Android stays at 60fps.
   ══════════════════════════════════════════════════════════════════════════ */

:root{
  /* Motion. One set of curves for the whole app, so everything moves like it
     belongs to the same thing. */
  --ease-out:  cubic-bezier(.22,.68,.28,1);      /* things arriving          */
  --ease-in:   cubic-bezier(.55,.06,.68,.19);    /* things leaving           */
  --ease-spring:cubic-bezier(.34,1.42,.52,1);    /* a little overshoot       */
  --t-fast: 140ms;
  --t-base: 240ms;
  --t-slow: 420ms;

  /* Depth. A dark app needs light to read as layered, not flat. */
  --lift-1: 0 1px 2px rgba(0,0,0,.5), 0 4px 14px rgba(0,0,0,.32);
  --lift-2: 0 2px 6px rgba(0,0,0,.5), 0 12px 34px rgba(0,0,0,.42);
  --lift-3: 0 8px 20px rgba(0,0,0,.5), 0 30px 70px rgba(0,0,0,.5);
  --glow-gold: 0 6px 26px rgba(245,197,24,.34);
  --sheen: linear-gradient(150deg, rgba(255,255,255,.09), rgba(255,255,255,0) 42%);

  /* The gold, as a surface rather than a flat fill. */
  --gold-grad: linear-gradient(145deg,#ffd95e 0%,#f5c518 46%,#e0ac00 100%);

  /* Phone chrome: notch at the top, home indicator at the bottom. */
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
  --tabbar-h: 62px;
}

/* ───────────────────────────────────────────── the basics, sharpened ───── */

body{ text-rendering:optimizeLegibility; }

/* Momentum scrolling that stops at the edges instead of bouncing the page. */
html{ overscroll-behavior-y:none; }

/* Nothing on a touch screen should show a grey flash box when tapped. */
*{ -webkit-tap-highlight-color:transparent; }

/* Selecting text by accident while tapping fast is a small, constant
   annoyance on a booking screen. Controls opt out; prose keeps it. */
button, .slot, .fcard, .tabbtn, .navtab, .chip{ user-select:none; -webkit-user-select:none; }

/* ────────────────────────────────────────────────── arriving on screen ─── */
/* Anything marked data-reveal fades and lifts in when it scrolls into view.
   Set once by app.js; the CSS does the moving.

   NOTE the html.js-motion gate. Hiding content in CSS and revealing it with
   JavaScript means that if the script ever fails to load — a bad deploy, a
   flaky connection on the road — the page renders BLANK. So the hiding only
   happens once the script has run and proved it is there. No script, no
   animation, everything visible. */
html.js-motion [data-reveal]{
  opacity:0;
  transform:translate3d(0,18px,0);
  transition:opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out);
  will-change:opacity, transform;
}
html.js-motion [data-reveal].is-in{ opacity:1; transform:none; will-change:auto; }
html.js-motion [data-reveal="left"] { transform:translate3d(-22px,0,0); }
html.js-motion [data-reveal="right"]{ transform:translate3d(22px,0,0); }
html.js-motion [data-reveal="zoom"] { transform:scale(.94); }

/* Lists arrive one after another rather than all at once. */
html.js-motion [data-stagger] > *{
  opacity:0; transform:translate3d(0,16px,0);
  transition:opacity var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-out);
}
html.js-motion [data-stagger].is-in > *{ opacity:1; transform:none; }
[data-stagger].is-in > *:nth-child(1){ transition-delay:0ms }
[data-stagger].is-in > *:nth-child(2){ transition-delay:55ms }
[data-stagger].is-in > *:nth-child(3){ transition-delay:110ms }
[data-stagger].is-in > *:nth-child(4){ transition-delay:165ms }
[data-stagger].is-in > *:nth-child(5){ transition-delay:220ms }
[data-stagger].is-in > *:nth-child(6){ transition-delay:275ms }
[data-stagger].is-in > *:nth-child(7){ transition-delay:330ms }
[data-stagger].is-in > *:nth-child(8){ transition-delay:385ms }
[data-stagger].is-in > *:nth-child(n+9){ transition-delay:420ms }

/* ─────────────────────────────────────────────────────── tap feedback ─── */
/* A press should be felt instantly, before any network call. */
.btn, .tabbtn, .cancel, .linkbtn, .slot, .fcard, .navtab{
  transition:transform var(--t-fast) var(--ease-out),
             box-shadow var(--t-fast) var(--ease-out),
             background-color var(--t-fast) var(--ease-out),
             border-color var(--t-fast) var(--ease-out),
             filter var(--t-fast) var(--ease-out);
}
.btn:active, .cancel:active, .tabbtn:active{ transform:scale(.965); }
.slot:active:not(.slot--full):not(.slot--na){ transform:scale(.94); }
.fcard:active{ transform:scale(.985); }

/* The ripple that spreads from where a thumb landed. */
.rippling{ position:relative; overflow:hidden; }
.ripple{
  position:absolute; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle, rgba(255,255,255,.42) 0%, rgba(255,255,255,0) 70%);
  transform:translate(-50%,-50%) scale(0); opacity:.85;
  animation:ripple 620ms var(--ease-out) forwards;
}
@keyframes ripple{ to{ transform:translate(-50%,-50%) scale(1); opacity:0; } }

/* ───────────────────────────────────────────────────────── buttons ────── */
.btn--gold{
  background:var(--gold-grad);
  box-shadow:var(--glow-gold), inset 0 1px 0 rgba(255,255,255,.45);
  border:0;
}
.btn--gold:hover{ filter:brightness(1.05); box-shadow:0 8px 32px rgba(245,197,24,.44), inset 0 1px 0 rgba(255,255,255,.5); }
.btn--gold:disabled{ background:#3a3a3a; color:#8a8a8a; box-shadow:none; filter:none; }

/* A button that is waiting on the network says so. */
.btn.is-busy{ position:relative; color:transparent !important; pointer-events:none; }
.btn.is-busy::after{
  content:''; position:absolute; inset:0; margin:auto; width:18px; height:18px;
  border:2px solid rgba(0,0,0,.28); border-top-color:rgba(0,0,0,.8);
  border-radius:50%; animation:spin .62s linear infinite;
}
.btn--ghost.is-busy::after{ border-color:rgba(255,255,255,.25); border-top-color:#fff; }
@keyframes spin{ to{ transform:rotate(360deg) } }

/* ──────────────────────────────────────────────── loading placeholders ── */
/* A shape where the content will be beats a spinner: the page does not jump
   when the data lands. */
.sk{
  position:relative; overflow:hidden;
  background:linear-gradient(180deg,#171b22,#141820);
  border-radius:12px; border:1px solid rgba(255,255,255,.04);
}
.sk::after{
  content:''; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.055), transparent);
  animation:shimmer 1.35s infinite;
}
@keyframes shimmer{ to{ transform:translateX(100%) } }
.sk--card{ height:210px; }
.sk--slot{ height:70px; border-radius:14px; }
.sk--line{ height:13px; border-radius:7px; }
.sk--line + .sk--line{ margin-top:9px; }

/* ─────────────────────────────────────────────── facility cards ───────── */
.fcard{
  background:linear-gradient(168deg,#181d25 0%,#12161d 100%);
  box-shadow:var(--lift-1);
  border-color:rgba(255,255,255,.07);
  position:relative; isolation:isolate;
}
.fcard::before{                       /* a soft sheen across the top edge */
  content:''; position:absolute; inset:0; z-index:3; pointer-events:none;
  background:var(--sheen); opacity:.55; border-radius:inherit;
}
.fcard__img img{ transition:transform var(--t-slow) var(--ease-out); }
@media (hover:hover) and (pointer:fine){
  .fcard:hover{ box-shadow:var(--lift-2); transform:translateY(-4px); }
  .fcard:hover .fcard__img img{ transform:scale(1.07); }
}

/* The accent stripe tells the sports apart at a glance while scrolling. */
.fcard::after{
  content:''; position:absolute; left:0; right:0; top:0; height:3px; z-index:4;
  background:var(--accent, var(--gold)); opacity:.9; border-radius:16px 16px 0 0;
}

/* "3 slots left tonight" — the one thing that makes somebody book now. */
.fcard__live{
  display:inline-flex; align-items:center; gap:6px;
  font-size:11.5px; font-weight:700; letter-spacing:.4px;
  color:#8fe0a8; background:rgba(49,196,106,.13);
  border:1px solid rgba(49,196,106,.3); border-radius:999px; padding:3px 9px;
}
.fcard__live--low{ color:#ffcf8f; background:rgba(240,150,46,.13); border-color:rgba(240,150,46,.34) }
.fcard__live--none{ color:#ff9ba1; background:rgba(240,71,46,.12); border-color:rgba(240,71,46,.32) }
.fcard__live i{
  width:6px; height:6px; border-radius:50%; background:currentColor; font-style:normal;
  animation:livepulse 1.9s var(--ease-out) infinite;
}
@keyframes livepulse{
  0%,100%{ opacity:1; transform:scale(1) }
  50%    { opacity:.35; transform:scale(.72) }
}

/* ──────────────────────────────────────────────────── the slot board ──── */
.sgrid{ grid-template-columns:repeat(auto-fill,minmax(104px,1fr)); gap:10px; }

.slot{
  border-radius:14px; padding:12px 11px;
  background:linear-gradient(170deg,#1b2029,#151920);
  box-shadow:var(--lift-1);
  overflow:hidden; position:relative;
}
.slot__t{ font-size:15px; letter-spacing:.2px }
.slot__p{ font-size:12.5px }

.slot--free{ border-color:rgba(49,196,106,.34); }

/* ── hover is a mouse idea, and phones fake it badly ──
   A tapped element on Android keeps :hover until something else is tapped.
   `.slot--free:hover` is a class AND a pseudo-class, so it outranks
   `.slot--sel` — which meant the hour you had just chosen went back to
   looking free the moment you lifted your thumb. Hover effects are now
   confined to devices that actually have a pointer, and the chosen state
   is stated loudly enough to win in every case. */
@media (hover:none){
  .slot--free:hover{ background:linear-gradient(170deg,#1b2029,#151920) }
}
.slot--free::before{                 /* a quiet green wash, not a border    */
  content:''; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(120% 90% at 0% 0%, rgba(49,196,106,.14), transparent 62%);
}
@media (hover:hover) and (pointer:fine){
  .slot--free:hover{ border-color:var(--free,#31c46a); box-shadow:var(--lift-2); transform:translateY(-2px); }
}

/* Chosen: the gold surface, lifted off the board. */
.slot--sel,
.slot--sel:hover,
.slot--free.slot--sel:hover{
  background:var(--gold-grad); border-color:#ffd95e; color:#141414;
  box-shadow:var(--glow-gold), inset 0 1px 0 rgba(255,255,255,.5);
  transform:translateY(-2px);
  animation:slotpick 320ms var(--ease-spring);
}
.slot--sel::before{ display:none }
@keyframes slotpick{
  0%  { transform:scale(.9) translateY(0) }
  55% { transform:scale(1.05) translateY(-3px) }
  100%{ transform:scale(1) translateY(-2px) }
}
/* A tick, so a chosen hour is obvious at a glance and not only by colour. */
.slot--sel::after{
  content:'✓'; position:absolute; top:6px; right:8px;
  font-size:12px; font-weight:800; color:rgba(20,20,20,.55);
}

.slot--full{ background:linear-gradient(170deg,#211519,#191115); box-shadow:none }
.slot--na{ background:#141820; box-shadow:none }

/* ───────────────────────────────────────────── the sticky basket ──────── */
.cart{
  background:linear-gradient(180deg, rgba(16,19,25,.86), rgba(11,13,17,.98));
  backdrop-filter:blur(18px) saturate(1.3);
  -webkit-backdrop-filter:blur(18px) saturate(1.3);
  border-top:1px solid rgba(255,255,255,.09);
  padding-bottom:calc(14px + var(--safe-b));
  box-shadow:0 -14px 40px rgba(0,0,0,.5);
  animation:cartUp 340ms var(--ease-spring);
}
@keyframes cartUp{ from{ transform:translateY(110%) } to{ transform:none } }
.cart__total{
  font-size:30px; text-shadow:0 2px 18px rgba(245,197,24,.35);
  font-variant-numeric:tabular-nums;
}

/* ─────────────────────────────────────────── the bottom tab bar ───────── */
/* The single biggest thing that makes a site feel like an app on a phone:
   the main destinations always within thumb reach, never scrolled away. */
.navtabs{
  position:fixed; left:0; right:0; bottom:0; z-index:30;
  display:none; align-items:stretch;
  background:rgba(13,16,21,.92);
  backdrop-filter:blur(20px) saturate(1.4);
  -webkit-backdrop-filter:blur(20px) saturate(1.4);
  border-top:1px solid rgba(255,255,255,.08);
  padding-bottom:var(--safe-b);
  box-shadow:0 -8px 30px rgba(0,0,0,.4);
}
.navtab{
  flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:3px; padding:9px 4px 7px; background:none; border:0; cursor:pointer;
  color:#8b95a3; font:inherit; font-size:10.5px; font-weight:600; letter-spacing:.2px;
  text-decoration:none; position:relative; min-height:var(--tabbar-h);
}
.navtab__ico{ width:23px; height:23px; display:block;
  transition:transform var(--t-base) var(--ease-spring), stroke-width var(--t-base) var(--ease-out) }
.navtab.is-on .navtab__ico{ stroke-width:2.1 }
.navtab.is-on{ color:var(--gold) }
.navtab.is-on .navtab__ico{ transform:translateY(-2px) scale(1.12) }
.navtab.is-on::before{                       /* the little gold pip on top */
  content:''; position:absolute; top:0; left:50%; transform:translateX(-50%);
  width:26px; height:3px; border-radius:0 0 4px 4px; background:var(--gold-grad);
  box-shadow:0 2px 12px rgba(245,197,24,.6);
}
.navtab:active .navtab__ico{ transform:scale(.88) }
/* A dot for something waiting — an unread reply, an upcoming booking. */
.navtab__dot{
  position:absolute; top:7px; left:calc(50% + 9px);
  width:7px; height:7px; border-radius:50%; background:var(--red,#f0472e);
  box-shadow:0 0 0 2px rgba(13,16,21,.95);
}

@media (max-width:820px){
  .navtabs{ display:flex }
  /* Room at the foot of every page so the bar never covers the last control. */
  body.has-tabbar{ padding-bottom:calc(var(--tabbar-h) + var(--safe-b) + 8px); }
  /* The basket sits above the tab bar, not under it. */
  body.has-tabbar .cart{ bottom:calc(var(--tabbar-h) + var(--safe-b)); padding-bottom:14px }
}

/* ─────────────────────────────────────────────── header on a phone ────── */
@media (max-width:820px){
  .hdr{
    background:rgba(12,14,17,.86);
    backdrop-filter:blur(16px) saturate(1.3);
    -webkit-backdrop-filter:blur(16px) saturate(1.3);
    padding-top:calc(10px + var(--safe-t));
    transition:box-shadow var(--t-base) var(--ease-out), background var(--t-base) var(--ease-out);
  }
  .hdr.is-stuck{ box-shadow:0 6px 24px rgba(0,0,0,.5); background:rgba(12,14,17,.97) }
  /* The tabs move to the bottom bar on a phone, so the top row is just the
     brand and who you are — calmer, and less to mis-tap. */
  .hdr__nav .tabbtn:not(.tabbtn--home){ display:none }
  .hdr__nav .tabbtn--home{ display:none }
}

/* ─────────────────────────────────── the slot board, denser on a phone ── */
/* Three hours across instead of two: more of the evening visible without
   scrolling, which is the whole job of this screen. */
@media (max-width:560px){
  .sgrid{ grid-template-columns:repeat(3,1fr); gap:8px }
  .slot{ padding:10px 7px; border-radius:12px }
  .slot__t{ font-size:13.5px }
  .slot__p{ font-size:11.5px; margin-top:1px }
  .slot__x{ font-size:10px; margin-top:1px }
  .slot--sel::after{ top:4px; right:5px; font-size:10px }
}
@media (max-width:360px){
  .sgrid{ grid-template-columns:repeat(2,1fr) }
}

/* The legend earns its place on a wide screen. On a phone it does not: every
   chip already has the word Free, Filled or Past written on it, so the key was
   four wrapped lines of colour swatches explaining what the board already
   says. */
.legend{ gap:14px; row-gap:6px; font-size:11.5px; opacity:.85 }
.legend > *{ white-space:nowrap }
@media (max-width:560px){ .legend{ display:none } }

/* The date sits on the board rather than looking like a browser control. */
.datepick input{
  background:linear-gradient(150deg,#1c222b,#151a21);
  border:1px solid rgba(255,255,255,.09);
  box-shadow:var(--lift-1);
  padding:12px 14px; border-radius:12px; font-weight:600;
}
.datepick input:focus{ outline:none; border-color:var(--gold); box-shadow:0 0 0 3px rgba(245,197,24,.16) }

/* The board itself, lifted off the page. */
.board{
  background:linear-gradient(168deg,#171c24,#12161d);
  border-color:rgba(255,255,255,.07);
  box-shadow:var(--lift-2);
}

/* The big overlay word sits on the chosen facility's photo. At 37px with wide
   letter-spacing it pressed against both edges of a 390px screen; a shade
   smaller with room to breathe reads as deliberate rather than squeezed. */
.slotHero__court{ padding:0 18px }
.slotHero__court b{
  font-size:clamp(20px, 6.6vw, 34px);
  letter-spacing:clamp(.5px, .3vw, 2px);
  line-height:1.02;
}
.slotHero__court i{ font-size:clamp(8.5px, 2.2vw, 10.5px) }

/* The same word on the small cards in the grid. */
.court-tag{ padding:0 14px }
.court-tag b{
  font-size:clamp(19px, 6.4vw, 34px); line-height:1;
  letter-spacing:clamp(.5px, .35vw, 2px);
  max-width:100%; overflow-wrap:anywhere;
}
.court-tag i{ font-size:clamp(8.5px, 2.2vw, 10.5px); letter-spacing:1px }

/* ─────────────────────────────────────────────── the day strip ────────── */
/* A row of days you can thumb through beats a date field on a phone: no
   keyboard, no calendar popup, and no "is 07/08 July or August?" — the day
   and the date are both written on the chip. The real date input is still
   there underneath and is still what gets read; this only sets it. */
.daystrip{
  display:flex; gap:8px; overflow-x:auto; padding:2px 2px 10px;
  scroll-snap-type:x proximity; -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.daystrip::-webkit-scrollbar{ display:none }
.dayc{
  flex:0 0 auto; scroll-snap-align:start; min-width:62px;
  display:flex; flex-direction:column; align-items:center; gap:1px;
  padding:9px 10px 8px; border-radius:14px; cursor:pointer;
  background:linear-gradient(168deg,#1a1f27,#141920);
  border:1px solid rgba(255,255,255,.08); color:var(--muted,#9aa4b1);
  font:inherit; box-shadow:var(--lift-1);
  transition:transform var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out),
             background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.dayc small{ font-size:10px; text-transform:uppercase; letter-spacing:.7px; font-weight:700; opacity:.9 }
.dayc b{ font-family:'Barlow Condensed',sans-serif; font-size:21px; line-height:1.05; color:#eef1f5 }
.dayc i{ font-style:normal; font-size:9.5px; letter-spacing:.4px; opacity:.75 }
.dayc:active{ transform:scale(.94) }
.dayc.is-on{
  background:var(--gold-grad); border-color:#ffd95e; color:#3a2f00;
  box-shadow:var(--glow-gold), inset 0 1px 0 rgba(255,255,255,.5);
  transform:translateY(-2px);
}
.dayc.is-on b{ color:#141414 }
.dayc.is-on small, .dayc.is-on i{ color:#4a3c00; opacity:1 }
.dayc.is-today::after{
  content:''; width:4px; height:4px; border-radius:50%; background:var(--gold);
  margin-top:2px;
}
.dayc.is-on.is-today::after{ background:#3a2f00 }

/* With the strip doing the work, the raw field becomes a quiet "other date"
   escape hatch rather than the main control. */
.datepick.has-strip{ flex-direction:row; align-items:center; gap:8px; margin-top:2px }
.datepick.has-strip > span{ font-size:11px }
.datepick.has-strip input{ padding:7px 10px; font-size:12.5px; box-shadow:none; opacity:.8 }

/* ───────────────────────────────────────────────── numbers that count ─── */
.countup{ font-variant-numeric:tabular-nums }

/* ─────────────────────────────────────────────── page arrival ─────────── */
/* The whole view settles in when a tab is switched — small, quick, and it
   makes a single-page flow read as separate screens. */
.viewin{ animation:viewin 300ms var(--ease-out) }
@keyframes viewin{
  from{ opacity:0; transform:translate3d(0,10px,0) }
  to  { opacity:1; transform:none }
}

/* ───────────────────────────────────────────── modals and sheets ──────── */
.modal{ animation:fadein 200ms var(--ease-out) }
@keyframes fadein{ from{opacity:0} to{opacity:1} }
.modal__card{
  animation:sheetup 320ms var(--ease-spring);
  box-shadow:var(--lift-3);
  background:linear-gradient(168deg,#1a1f27,#12161d);
}
@keyframes sheetup{
  from{ transform:translate3d(0,26px,0) scale(.96); opacity:0 }
  to  { transform:none; opacity:1 }
}
/* On a phone a dialog reads better as a sheet rising from the bottom. */
@media (max-width:560px){
  .modal{ place-items:end center; padding:0 }
  .modal__card{
    max-width:none; width:100%;
    border-radius:22px 22px 0 0;
    padding-bottom:calc(18px + var(--safe-b));
    animation:sheetup 340ms var(--ease-spring);
  }
  .modal__card::before{               /* the grab handle people expect */
    content:''; display:block; width:38px; height:4px; border-radius:99px;
    background:rgba(255,255,255,.22); margin:0 auto 14px;
  }
}

/* ───────────────────────────────────────────── the booking chip ───────── */
.chip{
  background:linear-gradient(150deg,#1c222b,#151a21);
  border:1px solid rgba(255,255,255,.08);
  box-shadow:var(--lift-1);
}
.chip__pts{
  background:var(--gold-grad); color:#141414; font-weight:800;
  border-radius:999px; padding:1px 8px; margin-right:7px; font-size:12px;
  box-shadow:0 2px 10px rgba(245,197,24,.4);
}

/* ─────────────────────────────────────────── my bookings, as cards ────── */
.bk{
  background:linear-gradient(168deg,#181d25,#12161d);
  border-color:rgba(255,255,255,.07);
  box-shadow:var(--lift-1);
  transition:transform var(--t-base) var(--ease-out), box-shadow var(--t-base) var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .bk:hover{ transform:translateY(-2px); box-shadow:var(--lift-2) }
}
.pill--ok{ box-shadow:0 0 0 1px rgba(49,196,106,.25) inset }

/* ───────────────────────────────────────────── empty states ───────────── */
.emptyart{ text-align:center; padding:34px 18px }
.emptyart__ico{
  font-size:44px; line-height:1; display:block; margin-bottom:12px;
  animation:floaty 3.6s var(--ease-out) infinite;
}
@keyframes floaty{
  0%,100%{ transform:translateY(0) rotate(-3deg) }
  50%    { transform:translateY(-9px) rotate(3deg) }
}
.emptyart p{ color:var(--muted); font-size:14px; margin:0 auto; max-width:34ch }

/* ══════════════════════════════════════════════════ the home page ────── */
@media (max-width:820px){
  /* Two full-width gold buttons sat above the hero, so the first half-screen
     a customer saw was a login they mostly do not need — the gym and badminton
     members are a minority of the traffic. Both ways in are still here, on one
     quiet line, and the pitch gets the top of the screen back. */
  .memberbar__guest{
    display:flex; align-items:center; gap:8px; flex-wrap:nowrap;
    padding:7px 12px; min-width:0;
  }
  /* Without a label those two chips read as links to gym and badminton
     INFORMATION, which is a different thing entirely. Short, but present. */
  .memberbar__label{
    font-size:11px; opacity:.7; letter-spacing:.3px; flex:0 0 auto;
    white-space:nowrap; text-transform:uppercase; font-weight:600;
  }
  /* Side by side, never stacked, and never wider than the screen. */
  .memberbar__btns{ display:flex; flex-direction:row; gap:7px; flex:0 0 auto }
  .memberbar__guest .btn{
    background:transparent; color:var(--gold);
    border:1px solid rgba(245,197,24,.42); box-shadow:none;
    font-size:11.5px; padding:.42em .82em; white-space:nowrap;
  }
  /* The account chip, once they are signed in, gets the same treatment. */
  .acctchip{ padding:8px 12px; gap:8px }
  .acctchip__hi{ font-size:12.5px }
  .acctchip__pts{ font-size:11.5px }
  .acctchip .btn{ font-size:11.5px; padding:.45em .85em }

  /* Three lines of 48px headline pushed everything that sells the place below
     the fold. Tighter type puts the promise, the sentence and the button on
     one screen. */
  .hero{ min-height:92vh }
  .hero__content{ padding-top:34px; padding-bottom:38px }
  .hero__title{ font-size:clamp(2.5rem,12.5vw,3.6rem); line-height:.92; margin-bottom:14px }
  .hero__eyebrow{ letter-spacing:2px; font-size:.78rem; margin-bottom:9px }
  .hero__sub{ font-size:1rem; margin-bottom:22px; max-width:38ch }
  .hero__cta{ gap:10px }
  .hero__cta .btn{ flex:1 1 auto; justify-content:center }
  /* The four numbers read as a scoreboard rather than a wrapped list. */
  .hero__stats{
    gap:0; margin-top:30px; display:grid; grid-template-columns:repeat(4,1fr);
    background:rgba(10,12,16,.42); backdrop-filter:blur(8px);
    border:1px solid rgba(255,255,255,.09); border-radius:16px;
    padding:14px 6px; box-shadow:var(--lift-1);
  }
  .hero__stats > div{ text-align:center; position:relative }
  .hero__stats > div + div::before{
    content:''; position:absolute; left:0; top:12%; bottom:12%; width:1px;
    background:rgba(255,255,255,.1);
  }
  .hero__stats strong{ font-size:1.5rem }
  .hero__stats span{ font-size:.6rem; letter-spacing:.6px; line-height:1.25; display:block; padding:0 3px }
}

/* The hero video drifts, so the page has depth as you scroll off it. */
.hero__video{ will-change:transform }

/* ── the bar that follows you down the page ──
   Somebody who has scrolled past the hero is interested. On a phone the way
   to book should never be more than a thumb away from then on. */
.bookbar{
  position:fixed; left:0; right:0; bottom:0; z-index:34;
  display:none; align-items:center; gap:12px;
  padding:12px 16px calc(12px + var(--safe-b));
  background:linear-gradient(180deg, rgba(14,17,22,.86), rgba(9,11,15,.98));
  backdrop-filter:blur(18px) saturate(1.35);
  -webkit-backdrop-filter:blur(18px) saturate(1.35);
  border-top:1px solid rgba(255,255,255,.09);
  box-shadow:0 -12px 34px rgba(0,0,0,.5);
  transform:translateY(110%);
  transition:transform var(--t-base) var(--ease-out);
}
.bookbar.is-up{ transform:none }
.bookbar__txt{ flex:1; min-width:0 }
.bookbar__txt b{ display:block; font-family:'Barlow Condensed',sans-serif; font-size:16px;
  text-transform:uppercase; letter-spacing:.6px; line-height:1.15 }
.bookbar__txt span{ display:block; color:var(--muted,#9aa4b1); font-size:11.5px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.bookbar .btn{ flex:0 0 auto; padding:.68em 1.25em }
@media (max-width:820px){ .bookbar{ display:flex } }

/* The WhatsApp button has to get out of the way when the booking bar rises,
   or it sits on top of the very button the bar exists to offer. */
.whatsapp-fab{
  bottom:calc(22px + var(--safe-b));
  transition:transform var(--t-base) var(--ease-out), bottom var(--t-base) var(--ease-out);
}
@media (max-width:820px){
  .whatsapp-fab{ width:50px; height:50px; right:14px }
  body.bookbar-up .whatsapp-fab{ bottom:calc(84px + var(--safe-b)) }
  /* On the booking screens the bottom bar is always there. */
  body.has-tabbar .whatsapp-fab{ bottom:calc(var(--tabbar-h) + var(--safe-b) + 14px) }
}

/* ═══════════════════════════════════════════════════════════════════════
   Somebody who has asked their phone to stop animating things means it.
   Everything still WORKS — it just arrives instead of moving.
   ═══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; scroll-behavior:auto !important;
  }
  html.js-motion [data-reveal], html.js-motion [data-stagger] > *{ opacity:1 !important; transform:none !important }
  .sk::after{ display:none }
}
