@import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700&display=swap');
/* ============================================================
   fb-private-membership.css
   The shared F. BINSABBAR Private Membership client-pages design system.
   Arabic script: Futura PT (Latin) has no Arabic glyphs, so Arabic text
   falls through to Tajawal - the canonical F. BINSABBAR Arabic typeface -
   which is loaded via the @import above and added to the two Futura stacks
   below (the --pm-serif display token and the body stack).

   ONE cohesive luxury design system for the client-facing web
   (the account portal + the public self-registration page). Built
   ON TOP of the canonical fb-ui.css tokens - it never invents a
   parallel token scale, only consumes --canvas-bg / --text* /
   --accent* / --champagne / --glass-* / --radius-* / --control-* /
   --s-* and adds program-specific structure (membership card, tier
   ladder, progress, benefits, exclusive grid, request CTA).

   Edge-to-edge, mobile-first, luxury (Futura PT, cream, hairlines,
   generous whitespace, house graphics), RTL-correct.

   This account/ copy is the CANONICAL source of the shared system.
   The clients/ copy carries this exact same shared system verbatim
   (byte-identical down to the page-local REGISTRATION PAGE block it
   appends at the end, the way account.css appends portal-only bits).
   Reconcile by re-copying this file's shared body into clients/ and
   keeping its appended registration block. fb-ui.css is loaded FIRST
   (absolute URL on the account portal, root-relative on the register
   page); this file is loaded after it.

   HARD RULES honoured here:
   - No em-dashes / en-dashes anywhere (hyphens only).
   - "F. BINSABBAR" is always uppercase; F. BINSABBAR Private Membership is
     the program name, never lowercased or abbreviated to mean Facebook.
   ============================================================ */

/* ============================================================
   0. PROGRAM-LOCAL VARIABLES
   These are layered on fb-ui.css tokens - NOT a parallel scale.
   They centralise the program's hairline, ink and tier ramp so the
   account portal and the register page stay in lockstep.
   ============================================================ */
:root {
  /* ----------------------------------------------------------------
     KITH EDITORIAL THEME, in F. BINSABBAR's LIGHT brand (ivory/cream
     canvas, ink text, champagne/gold accent). The whole palette is
     expressed as tokens so the portal can be re-themed in ONE place
     (swap this block). We KEEP the fb-ui.css light token values
     (--canvas-bg / --text* / --champagne / --glass-* / --control-*) and
     add the KITH-specific structural tokens (elevated surfaces, hairline,
     navbar height, display headline stack). The KITH editorial STRUCTURE
     (sticky nav, top tabs, split stat, index cards, full-bleed exclusive,
     inset rows, member inbox/thread) is unchanged; only the palette is
     light. Every component below consumes these tokens.
     ---------------------------------------------------------------- */
  /* Canvas + elevated surfaces (cream canvas + lifted ivory cards/rows). */
  --canvas-bg:         #f4eedf;   /* warm ivory/cream page canvas         */
  --pm-surface:        #fbf8f1;   /* elevated surface (cards / rows)      */
  --pm-surface-2:      #f6f1e6;   /* a touch deeper (active rows / sheets)*/
  --pm-surface-3:      #efe9dc;   /* chips / inputs                       */
  /* Warm taupe/beige fill for PRODUCT image wells (gallery / card media /
     placeholders) - jewels sit on a tasteful light surface, not black. The well
     is a smooth, soft GRADIENT BEIGE (two warm beiges, no noise/grain texture)
     so the fill reads clean and editorial. --pm-surface-warm is the mid beige
     (fallback solid); --pm-well-bg is the gradient used on every product well. */
  --pm-surface-warm:   #ddd4c4;   /* mid beige product-image well (solid fallback) */
  /* Product tile well: an ANGLED warm-cream gradient (matches the main store
     catalogue's diagonal cream), two shades DEEPER than the old near-white wash
     so the piece reads on a richer cream surface (closer to the --canvas-bg
     page #f4eedf) instead of a flat off-white. */
  --pm-well-bg:        linear-gradient(140deg, #f9f4ea 0%, #ebe2cf 100%);

  /* Hairlines (ink-on-light: black-alpha). */
  --pm-hairline:       rgba(0,0,0,0.08);
  --pm-hairline-soft:  rgba(0,0,0,0.05);
  --pm-hairline-strong:rgba(0,0,0,0.12);

  /* Text ramp (ink -> muted -> faint). Match the fb-ui.css light tokens. */
  --text:              #0e0e0e;   /* primary ink                          */
  --text-muted:        #3a3a3a;   /* secondary muted                      */
  --text-faint:        #5a5a5a;   /* tertiary faint (WCAG AA on cream)    */
  --text-inverse:      #f6f4ef;

  /* Accent = the F. BINSABBAR champagne/gold (used for accents + active
     states). The signature red is reused sparingly (alerts / unread). */
  --champagne:         #b19b7d;   /* champagne/gold (accents, active tab) */
  --champagne-deep:    #8f7a5c;
  --accent:            #f74827;   /* signature red (sparingly)            */
  --accent-soft:       rgba(247,72,39,0.18);
  --accent-yellow:     #fee5a5;

  /* Inks for solid CTAs - the primary CTA fills champagne with dark ink. */
  --pm-ink:            #0e0e0e;   /* primary ink on light                 */
  --pm-cta-bg:         var(--champagne);
  --pm-cta-ink:        #1a140c;

  /* Glass (frosted on cream). */
  --glass-bg:          rgba(249,248,246,0.22);
  --glass-bg-strong:   rgba(249,248,246,0.42);
  --glass-blur:        blur(18px) saturate(140%);
  --glass-shadow:      0 2px 8px rgba(0,0,0,0.06), 0 0 0 1px rgba(255,255,255,0.30), inset 0 1px 0 rgba(255,255,255,0.55);

  /* Controls (inputs / chips) on light. */
  --control-bg:        rgba(255,255,255,0.55);
  --control-bg-hover:  rgba(255,255,255,0.85);
  --control-border:    rgba(0,0,0,0.10);

  --pm-max:            760px;   /* shared reading width            */
  --pm-card-max:       480px;   /* membership card - editorial centerpiece */
  --navbar-h:          52px;    /* native nav header content height (excl. safe-area) */

  /* Display headline stack. The owner does NOT want a serif: the big
     titles AND the big points numbers all render in Futura PT (the kit
     sans, from Typekit), same as labels + body. Kept as a token so every
     headline stays in lockstep. */
  --pm-serif: futura-pt, "Futura PT", "Tajawal", system-ui, sans-serif;

  /* Tier ramp, keyed to data-rank (0 public .. 3 top). The SAME ramp
     drives .tier-chip, .ladder, .excl-badge and the card tier so a tier
     reads identically everywhere. */
  --pm-rank0-bg:  rgba(0,0,0,0.08);
  --pm-rank0-ink: var(--text-muted);
  --pm-rank1-bg:  var(--champagne);
  --pm-rank1-ink: #1a140c;
  --pm-rank2-bg:  #6f5a3e;
  --pm-rank2-ink: var(--accent-yellow);
  --pm-rank3-bg:  #0e0e0e;
  --pm-rank3-ink: var(--accent-yellow);
}

/* ============================================================
   1. PAGE FRAME (shared shell)
   ============================================================ */
html, body { min-height: 100%; }
body {
  background: var(--canvas-bg);
  color: var(--text);
  display: flex;
  flex-direction: column;
  font-family: futura-pt, "Futura PT", "Tajawal", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* ----------------------------------------------------------------
   EDITORIAL TYPOGRAPHY (KITH structure, Futura PT everywhere): Futura PT
   (the kit sans) carries the big titles, the big points numbers, labels
   and body alike - the owner does NOT want a serif, so --pm-serif now
   resolves to the Futura stack. Eyebrows / section headers / tab labels
   are UPPERCASE, letter-spaced, small + muted (set per-component). The
   .pm-display utility (was .pm-serif) is applied where a display weight is
   wanted in markup; the big display headings below pick it up too.
   ---------------------------------------------------------------- */
.pm-serif { font-family: var(--pm-serif); font-weight: 500; }
.login-hero h1,
.acct-largetitle,
.split-num,
.idx-title,
.pd-name,
.thread-subject {
  font-family: var(--pm-serif);
  font-weight: 500;
}

/* The shared centred reading column. Pages use .pm-main; the account
   portal keeps .acct-main as an alias for backwards-compat. */
.pm-main, .acct-main {
  flex: 1 1 auto;
  width: 100%;
  max-width: var(--pm-max);
  margin: 0 auto;
  /* Bottom content clears the home indicator (safe-area-inset-bottom). */
  padding: 0 var(--s-5) calc(var(--s-9) + env(safe-area-inset-bottom, 0px));
}

/* ============================================================
   2. NATIVE STICKY NAV HEADER (iOS large-title nav bar)
   A compact, centered, translucent BLURRED bar. At rest it is fully
   transparent (only the wordmark + language affordance show, over the
   page wash); the large title lives in the scroll flow below. On scroll
   (.is-scrolled, set by app.js) it gains the frosted blur + a hairline
   bottom border and the collapsed centered title fades in. Respects
   env(safe-area-inset-top) for the notch / Dynamic Island.
   ============================================================ */
.navbar {
  position: sticky;
  top: 0;
  z-index: 70;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--s-3);
  box-sizing: border-box;
  /* Fixed content height so the sticky segmented control can offset under it. */
  /* Keep a minimum top inset so the logo never kisses the screen top when the
     bar is sticky (env() is 0 in a plain browser; >=10px guarantees breathing
     room, and the notch inset wins in the app). */
  height: calc(var(--navbar-h, 56px) + max(env(safe-area-inset-top, 0px), 10px));
  padding: max(env(safe-area-inset-top, 0px), 10px) var(--s-5) 0;
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom: 1px solid transparent;
  transition: background 260ms ease, border-color 260ms ease,
              -webkit-backdrop-filter 260ms ease, backdrop-filter 260ms ease;
}
/* Blur engages IMMEDIATELY on the first scroll px (.is-blurred), decoupled from
   the title collapse (.is-scrolled) so the bar frosts the moment you scroll. */
.navbar.is-blurred {
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  backdrop-filter: blur(20px) saturate(1.4);
  border-bottom-color: var(--pm-hairline);
}
.navbar-logo {
  display: inline-flex;
  align-items: center;
  margin: 0;
  color: var(--text);
  text-decoration: none;
  justify-self: start;
}
.wm-img {
  display: block;
  height: 14px;
  width: auto;
  /* The wordmark SVGs are authored ink-black; on the cream canvas they read
     directly as the F. BINSABBAR mark in ink (no filter). */
}
/* The collapsed centered title (the member name). Hidden until scrolled. */
.navbar-title {
  grid-column: 2;
  justify-self: center;
  text-align: center;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 220ms ease, transform 220ms ease;
  pointer-events: none;
}
.navbar.is-scrolled .navbar-title { opacity: 1; transform: none; }
.navbar-actions { display: flex; align-items: center; gap: var(--s-3); justify-self: end; }
/* The navbar language toggle is a quiet text affordance (not a pill) so the
   header reads clean and native. The full pill style is kept for the More row. */
.navbar-lang {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13px;
  letter-spacing: 0.02em;
  padding: 6px 4px;
  cursor: pointer;
  transition: color 160ms ease;
}
.navbar-lang:hover { color: var(--text); }
/* The legacy navbar sign-out button stays hidden (sign out moved into More);
   it is kept in the DOM only so existing JS that toggles #signOutBtn is inert. */
.navbar .signout { display: none; }

/* ============================================================
   3. SCREENS / TRANSITIONS
   ============================================================ */
.screen { display: none; }
.screen.is-active { display: block; animation: pm-fade-in 420ms cubic-bezier(.2,.7,.2,1) both; }
@keyframes pm-fade-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* Boot spinner - dead-centered in the full viewport at any screen size. Fixed +
   inset:0 so the loader sits at the true center regardless of content height; the
   navbar (z-index 70) still shows its wordmark above this (z-index 2). */
.screen-boot {
  position: fixed; inset: 0;
  display: none; place-items: center;
  z-index: 2;
}
.screen-boot.is-active { display: grid; }
.boot-mark {
  width: 46px; height: 46px;
  color: var(--text);
  background: center / contain no-repeat url('https://fbinsabbar.web.app/icons/aldebaran-motif.svg');
  animation: page-loader-pulse 1600ms ease-in-out infinite;
}
@keyframes pm-spin { to { transform: rotate(360deg); } }
@keyframes pm-breathe {
  0%, 100% { opacity: 0.32; transform: scale(0.9); }
  50%      { opacity: 1;    transform: scale(1); }
}

/* ============================================================
   4. LOGIN SCREEN (edge-to-edge hero + phone-OTP)
   ============================================================ */
.screen-login { position: relative; }
/* Large, quiet house monogram watermark behind the form. */
.login-watermark {
  position: absolute;
  top: 46%;
  inset-inline-start: 50%;
  transform: translate(-50%, -50%);
  width: min(82vw, 460px);
  height: auto;
  opacity: 0.07;
  filter: sepia(1) saturate(0.55) brightness(1.12) hue-rotate(-8deg);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
[dir="rtl"] .login-watermark { transform: translate(50%, -50%); }
.login-inner {
  position: relative;
  z-index: 1;
  max-width: 460px;
  margin: 0 auto;
  box-sizing: border-box;
  /* Side gutter so the banner + form are inset from the screen edges on phones,
     matching the register page (.page.reg uses the same var(--s-5)). */
  padding: var(--s-8) var(--s-5) 0;
}
/* Editorial membership banner - the LEAD visual on the login screen.
   Full-width / responsive, centred, NO divider line beneath it. */
.login-banner {
  display: flex;
  justify-content: center;
  margin: 0 0 var(--s-6);
}
.login-banner-img {
  display: block;
  width: 100%;
  height: auto;
  max-width: 460px;
  border-radius: clamp(12px, 3.5vw, 18px);
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
}
.login-hero { margin-bottom: var(--s-7); text-align: center; }
/* Center the hero block (eyebrow + h1 + lede) cleanly on all widths. */
.login-hero .eyebrow,
.login-hero h1 { text-align: center; }
/* The program eyebrow on login - letterspaced, quiet champagne. */
.login-hero .eyebrow { color: var(--champagne); }
.login-hero h1 { margin: var(--s-3) 0 var(--s-3); }
.login-hero p { max-width: 38ch; margin-inline: auto; }

.auth-card {
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
  border-radius: var(--radius-glass);
  padding: var(--s-7) var(--s-6) var(--s-6);
}
.field-label {
  display: block;
  font-size: var(--param-title-fs, 11px);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  color: var(--text-muted);
  margin-bottom: var(--s-3);
}
/* The kit's .text-input / .fb-select are authored for the LIGHT canvas
   (near-white fill). On the dark canvas relight them to a dark surface with a
   light hairline + near-white text + a champagne focus ring. Covers the phone /
   OTP inputs, the service notes textarea + date input. */
.text-input,
textarea.text-input,
input.text-input,
select.fb-select {
  background: var(--pm-surface-3);
  border-color: var(--control-border);
  color: var(--text);
}
.text-input::placeholder, textarea.text-input::placeholder { color: var(--text-faint); }
.text-input:focus, textarea.text-input:focus, input.text-input:focus {
  border-color: var(--champagne);
  background: var(--pm-surface-2);
}
/* Native date picker glyph is dark; on the light input it shows as-is. */
input[type="date"].text-input::-webkit-calendar-picker-indicator { opacity: 0.65; }
.dial { background: var(--pm-surface-3); border-color: var(--control-border); color: var(--text); }

.phone-row { display: flex; align-items: stretch; gap: var(--s-2); }
.dial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 64px;
  height: var(--control-h);
  padding: 0 var(--s-4);
  border-radius: var(--radius-pill);
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--text);
  direction: ltr;
  unicode-bidi: isolate;
}
.phone-input { flex: 1 1 auto; direction: ltr; text-align: start; letter-spacing: 0.08em; }
/* Apple-style one-time-code entry: six single-digit boxes. Always laid out
   left-to-right (even in Arabic - see the [dir="rtl"] override below). The row
   fills the card width but each box is capped so the group stays tidy and
   centered on wide (iPad) viewports; on narrow phones the boxes shrink to fit. */
.otp-boxes {
  display: flex;
  gap: var(--s-2);
  direction: ltr;
  justify-content: center;
}
/* Scoped under #otpBoxes (id) so these outrank the kit's dark-canvas relight of
   bare inputs - `:root input[type=text]` (specificity 0,2,1) otherwise forces the
   control height / radius / translucent fill, and its :focus rule paints a red
   `!important` ring. We beat the plain props by specificity and the two
   `!important` focus props by matching `!important` at higher specificity. */
#otpBoxes .otp-box {
  flex: 1 1 44px;
  min-width: 0;
  max-width: 54px;
  height: 52px;
  padding: 0;
  text-align: center;
  font-size: 24px;
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--pm-surface-3);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-md);
  caret-color: var(--champagne);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
#otpBoxes .otp-box.is-filled { border-color: var(--pm-hairline-strong); }
/* The box selects its digit on focus (so a keystroke overwrites); tint that
   highlight champagne instead of the browser's default blue. */
#otpBoxes .otp-box::selection { background: rgba(177, 155, 125, 0.32); }
#otpBoxes .otp-box:focus {
  outline: none;
  background: var(--pm-surface-2);
  border: 1px solid var(--champagne) !important;
  box-shadow: 0 0 0 3px rgba(177, 155, 125, 0.22) !important;
}
/* Wrong-code feedback: red ring + a brief shake before the boxes clear. The
   `!important` here wins over the focus ring above so the box the member just
   submitted from still reads as an error, not a normal focus. */
#otpBoxes.is-error .otp-box {
  border: 1px solid var(--accent) !important;
  box-shadow: 0 0 0 3px rgba(247, 72, 39, 0.18) !important;
  animation: otpShake 0.4s ease;
}
@keyframes otpShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}
/* Respect Reduce Motion: drop the shake but keep the static red ring, which
   still signals the wrong code without any movement. */
@media (prefers-reduced-motion: reduce) {
  #otpBoxes.is-error .otp-box { animation: none; }
}
.field-hint {
  min-height: 16px;
  margin: var(--s-2) 0 0;
  font-size: 12px;
  color: var(--text-faint);
}
.field-hint.is-error { color: var(--accent); }
/* The status line reserves min-height so an appearing error/hint does not shift
   the layout. When it is EMPTY (the default on the phone step) it must take ZERO
   space: otherwise its reserved height + top margin stack with the button's
   margin-top and open an obvious empty gap between the Mobile number input and
   the Send code button (conspicuous on wide / iPad viewports where the login
   card is centered). It expands again the moment a message is set. The invisible
   reCAPTCHA container is NOT the cause - it is position:fixed and out of flow. */
.field-hint:empty { min-height: 0; margin-top: 0; }
.field-note {
  margin: var(--s-4) 0 0;
  font-size: 11.5px;
  color: var(--text-faint);
  line-height: 1.5;
}
.auth-btn { width: 100%; justify-content: center; margin-top: var(--s-5); }
.auth-btn.is-busy { opacity: 0.6; pointer-events: none; }
/* Primary CTAs fill the champagne pill with dark ink (the house primary).
   Covers login, service submit + message retry. */
.auth-btn, .svc-submit, .message-inner .btn:not(.outline) {
  background: var(--pm-cta-bg);
  color: var(--pm-cta-ink);
}
/* The kit's .outline ring is an ink hairline; keep it readable on cream. */
.btn.outline {
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--pm-hairline-strong);
}
.back-link {
  appearance: none;
  background: none;
  border: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.04em;
  cursor: pointer;
  padding: 0;
  margin-bottom: var(--s-4);
}
.back-link:hover { color: var(--text); }
.back-link svg { width: 16px; height: 16px; }
[dir="rtl"] .back-link svg { transform: scaleX(-1); }
.otp-sent { margin: 0 0 var(--s-4); font-size: 13px; color: var(--text-muted); }
.resend {
  appearance: none; background: none; border: 0;
  display: block; margin: var(--s-4) auto 0;
  color: var(--text-muted); font: inherit; font-size: 12px;
  letter-spacing: 0.04em; cursor: pointer; text-decoration: underline;
  text-underline-offset: 3px;
}
.resend:hover { color: var(--accent); }
/* During the resend cooldown the button is disabled and shows a live countdown;
   it reads quiet (no underline, not interactive) until it re-enables at 0s. */
.resend:disabled, .resend.is-cooldown {
  color: var(--text-faint);
  cursor: default;
  text-decoration: none;
  opacity: 0.7;
}
.resend:disabled:hover, .resend.is-cooldown:hover { color: var(--text-faint); }
#recaptcha-container { position: fixed; bottom: 0; left: 0; }

/* Become-a-member affordance under the auth card: a quiet hairline
   divider then a "Not a member yet? Become a member" line that routes
   to the public registration page. */
.join-cta {
  margin-top: var(--s-7);
  padding-top: var(--s-6);
  border-top: 1px solid var(--pm-hairline);
  text-align: center;
}
.join-cta p {
  margin: 0 0 var(--s-4);
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.6;
}
.join-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  height: var(--control-h);
  padding: 0 var(--s-6);
  border-radius: var(--radius-pill);
  border: 1px solid var(--pm-ink);
  background: transparent;
  color: var(--pm-ink);
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background 160ms ease, color 160ms ease;
}
.join-link:hover { background: var(--champagne); color: #1a140c; border-color: var(--champagne); }
.join-link svg { width: 15px; height: 15px; }
[dir="rtl"] .join-link svg { transform: scaleX(-1); }

/* ============================================================
   5. ACCOUNT STAGE - the membership card is the HERO
   The logged-in page opens with the card, large and centred, on a
   generous field of whitespace. Nothing competes above it. A single
   quiet status line sits beneath it, then the Apple Wallet badge.
   ============================================================ */
.acct-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: clamp(var(--s-5), 5vw, 40px);
  margin-bottom: var(--s-8);
}
/* The minimal hero now carries ONLY the large-title block (the card + wallet +
   split stat moved into the Membership tab). Tighten the trailing space so the
   segmented control sits close beneath the title. */
.acct-stage-minimal { margin-bottom: var(--s-5); }
.acct-stage-minimal .acct-largetitle-wrap { margin-bottom: 0; }

/* The Membership tab now leads with the editorial Featured hero, then the
   membership card -> wallet -> split stat -> ladder. When the Featured block is
   present it carries its own trailing margin; otherwise the card needs a little
   breathing room from the segmented control above it. */
.sec-membership > .membership-card { margin-top: var(--s-5); }
.sec-membership > .featured-block + .membership-card { margin-top: 0; }

/* ---- iOS LARGE-TITLE BLOCK (in the scroll flow; collapses into the navbar) ----
   A small greeting eyebrow over the member's name as a bold, inline-start
   aligned large title - the way iOS large titles read. It scrolls away
   normally; app.js fades the collapsed navbar title in as the title passes. */
.acct-largetitle-wrap {
  align-self: stretch;
  margin: 0 0 var(--s-6);
  text-align: start;
}
.acct-largetitle-eyebrow {
  margin: 0 0 4px;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--champagne);
}
[dir="rtl"] .acct-largetitle-eyebrow { letter-spacing: 0.06em; }
.acct-largetitle {
  margin: 0;
  /* The single biggest heading, in the Futura display stack (the WELCOME
     eyebrow stays uppercase). */
  font-family: var(--pm-serif);
  font-size: clamp(28px, 8vw, 38px);
  line-height: 1.08;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text);
  word-break: break-word;
}

/* ---- Status line under the card (tier . points) ---- */
.acct-status {
  text-align: center;
  margin-top: var(--s-6);
}
.acct-status-greet {
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 0.5ch;
  flex-wrap: wrap;
  justify-content: center;
  font-size: 11px;
  letter-spacing: 0.24em;
  color: var(--champagne);
}
.acct-status-name {
  display: inline;
  font-size: clamp(20px, 5.4vw, 28px);
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--text);
  font-weight: 500;
}
.acct-status-meta {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
  flex-wrap: wrap;
  justify-content: center;
}
.status-dot {
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--champagne);
  opacity: 0.7;
}

/* ---- Tier chip (rank ramp) ---- */
.tier-chip {
  display: inline-flex;
  align-items: center;
  height: var(--s-7);
  padding: 0 var(--s-4);
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* Dark-safe default (no data-rank): the near-white var(--text) fill with pale
     ink was illegible on the dark canvas. Fall back to the rank-0 dark chip. */
  background: var(--pm-rank0-bg);
  color: var(--pm-rank0-ink);
}
.tier-chip[data-rank="0"] { background: var(--pm-rank0-bg); color: var(--pm-rank0-ink); }
.tier-chip[data-rank="1"] { background: var(--pm-rank1-bg); color: var(--pm-rank1-ink); }
.tier-chip[data-rank="2"] { background: var(--pm-rank2-bg); color: var(--pm-rank2-ink); }
.tier-chip[data-rank="3"] { background: var(--pm-rank3-bg); color: var(--pm-rank3-ink); }
.points-inline { font-size: 13px; color: var(--text-muted); letter-spacing: 0.02em; }
.points-inline strong { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }

/* ============================================================
   KITH SPLIT POINTS STAT - directly under the card.
   Two columns split by a thin vertical hairline divider:
   left  = big TOTAL POINTS (Futura display, ink)
   right = big UNTIL NEXT TIER (or HIGHEST TIER at the top).
   Letter-spaced uppercase captions beneath each number.
   ============================================================ */
.split-stat {
  align-self: stretch;
  display: grid;
  grid-template-columns: 1fr 1px 1fr;
  align-items: center;
  gap: 0;
  margin-top: var(--s-7);
  padding-top: var(--s-7);
  border-top: 1px solid var(--pm-hairline);
}
.split-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* A shared min-height so the top-tier "HIGHEST TIER" column (smaller text, no
     visible caption) centers against the big champagne TOTAL number in the other
     column, keeping both on one balanced baseline. */
  min-height: clamp(54px, 13vw, 70px);
  padding: var(--s-2) var(--s-4);
}
.split-divider {
  align-self: stretch;
  width: 1px;
  background: var(--pm-hairline);
}
.split-num {
  font-size: clamp(30px, 9vw, 44px);
  line-height: 1;
  /* Ink for strong contrast on cream; champagne stays the accent (eyebrow,
     active states), not the big number. */
  color: var(--text);
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
.split-num.is-text {
  font-size: clamp(17px, 5vw, 22px);
  color: var(--text);
}
.split-cap {
  margin-top: var(--s-3);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
}
[dir="rtl"] .split-cap { letter-spacing: 0.04em; }

/* ============================================================
   KITH INDEX CARDS - a stack of light rounded cards under the split
   stat on the Membership tab. Each = Futura title + uppercase muted
   subtitle + a circled chevron on the end. Taps jump to a segment /
   block. Generous + elegant.
   ============================================================ */
.index-cards {
  align-self: stretch;
  margin-top: var(--s-8);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.idx-card {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: 100%;
  margin: 0;
  padding: var(--s-5) var(--s-6);
  background: var(--pm-surface);
  border: 1px solid var(--pm-hairline);
  border-radius: var(--radius-card);
  text-align: start;
  cursor: pointer;
  appearance: none;
  font: inherit;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
  transition: background 160ms ease, border-color 160ms ease, transform 120ms ease;
}
.idx-card:hover { background: var(--pm-surface-2); border-color: var(--pm-hairline-strong); }
.idx-card:active { transform: scale(0.995); }
.idx-card:focus-visible {
  outline: none;
  border-color: var(--champagne);
  box-shadow: 0 0 0 1px var(--champagne);
}
.idx-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.idx-title {
  font-size: 19px;
  line-height: 1.15;
  letter-spacing: 0.01em;
  color: var(--text);
}
.idx-sub {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}
[dir="rtl"] .idx-sub { letter-spacing: 0.03em; }
/* unread/count chip on an index card (e.g. Requests) */
.idx-count {
  flex: 0 0 auto;
  min-width: 20px; height: 20px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.idx-chev {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--pm-hairline-strong);
  color: var(--text-muted);
}
.idx-chev::after {
  content: "";
  width: 7px; height: 7px;
  border-top: 1.5px solid currentColor;
  border-inline-end: 1.5px solid currentColor;
  transform: rotate(45deg);
  margin-inline-start: -2px;
}
[dir="rtl"] .idx-chev::after { transform: rotate(225deg); margin-inline-start: 2px; }
.idx-card:hover .idx-chev { color: var(--champagne); border-color: var(--champagne); }

/* ============================================================
   FEATURED CAROUSEL (Membership tab) - a horizontal, swipeable row of
   jewel cards (data.featured). Each card reuses the .excl-card visual and
   opens the normal piece-detail overlay. Snap + momentum + RTL-correct.
   The whole block is hidden (markup [hidden]) when data.featured is empty.
   ============================================================ */
/* ============================================================
   FEATURED - EDITORIAL BLOG CAROUSEL (KITH "Monday Program" hero)
   The lead "discover" hero at the very top of the Membership tab. Each entry
   is a FULL-BLEED editorial card: media (image or autoplay video) under a
   bottom scrim, with an eyebrow + big title + caption + optional button.
   Multiple entries = a swipeable scroll-snap carousel with a dot row. The
   rail bleeds to the screen edges (under the reading gutters).
   ============================================================ */
.featured-block {
  position: relative;
  align-self: stretch;
  margin: 0 calc(var(--s-5) * -1) var(--s-8);
}
.featured-rail {
  display: flex;
  /* gap MUST equal padding-inline: a centered full-width slide then leaves the
     next slide EXACTLY off-screen, with no sliver of the next card peeking at
     the right edge (gap < gutter was showing a few px of the next slide). */
  gap: var(--s-5);
  padding-inline: var(--s-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.featured-rail::-webkit-scrollbar { display: none; }
.feat-card {
  position: relative;
  flex: 0 0 100%;
  width: 100%;
  scroll-snap-align: center;
  aspect-ratio: 3 / 4;
  max-height: 78vh;
  border-radius: var(--radius-card);
  overflow: hidden;
  background-color: var(--pm-surface-warm);
  isolation: isolate;
}
.featured-block.is-single .featured-rail { scroll-snap-type: none; }
.feat-media { position: absolute; inset: 0; z-index: 0; }
.feat-media-el {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.feat-card::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to top, rgba(0,0,0,0.80) 0%, rgba(0,0,0,0.36) 34%, transparent 62%);
  pointer-events: none;
}
.feat-cap {
  position: absolute; z-index: 2;
  inset-inline: 0; bottom: 0;
  padding: var(--s-7) var(--s-6) var(--s-6);
  display: flex; flex-direction: column; gap: 6px;
  text-align: start;
}
.feat-eyebrow {
  margin: 0;
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.20em; text-transform: uppercase;
  /* Monochrome featured banner: white eyebrow over dark/busy imagery (no gold). */
  color: #f6f3ec;
}
[dir="rtl"] .feat-eyebrow { letter-spacing: 0.06em; }
.feat-title {
  margin: 0;
  font-family: var(--pm-serif);
  font-weight: 500;
  font-size: clamp(24px, 6.4vw, 34px);
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: #f6f3ec;
  text-shadow: 0 1px 18px rgba(0,0,0,0.45);
}
.feat-caption {
  margin: 2px 0 0;
  font-size: 14px; line-height: 1.45;
  color: rgba(246,243,236,0.86);
  max-width: 42ch;
}
.feat-btn {
  align-self: flex-start;
  margin-top: var(--s-4);
  appearance: none;
  display: inline-flex; align-items: center;
  height: 44px;
  padding: 0 22px;
  border: 0; border-radius: var(--radius-pill);
  /* Monochrome: white button with black ink (no champagne/gold) over dark imagery. */
  background: #f6f3ec;
  color: #0e0e0e;
  font: inherit; font-size: 13px; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background 200ms ease, transform 120ms ease;
}
.feat-btn:hover { background: #ffffff; }
.feat-btn:active { transform: scale(0.98); }
.feat-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--canvas-bg), 0 0 0 4px #f6f3ec; }

/* ---- DARK-TEXT THEME (.theme-dark) : ink text + a dark/champagne button, for
   PALE / light imagery. The default (light) theme keeps WHITE eyebrow/title/
   caption + a champagne button over dark/busy imagery (above). For the dark-text
   variant we LIGHTEN the bottom scrim (so it does not darken the pale image into
   a muddy band) and recolour the text to INK so it stays legible on the light
   photo. ---- */
.feat-card.theme-dark::after {
  /* Lighter, top-light wash so the pale image keeps its brightness while the
     ink text at the bottom gets just enough separation to read. */
  background: linear-gradient(to top, rgba(246,238,223,0.82) 0%, rgba(246,238,223,0.40) 30%, transparent 60%);
}
.feat-card.theme-dark .feat-eyebrow {
  /* Monochrome: black eyebrow over pale imagery (no gold). */
  color: #141414;
  text-shadow: none;
}
.feat-card.theme-dark .feat-title {
  color: var(--text);
  text-shadow: 0 1px 14px rgba(246,238,223,0.5);
}
.feat-card.theme-dark .feat-caption {
  color: var(--text-muted);
}
/* Monochrome: black button with white text over pale imagery (no gold/yellow). */
.feat-card.theme-dark .feat-btn {
  background: #0e0e0e;
  color: #f6f3ec;
}
.feat-card.theme-dark .feat-btn:hover { background: #2a2a2a; }
.feat-card.theme-dark .feat-btn:focus-visible {
  box-shadow: 0 0 0 2px var(--canvas-bg), 0 0 0 4px var(--pm-ink);
}

/* Carousel dot row (multi-entry only). The dots OVERLAY inside the gallery at
   the BOTTOM (the conventional, expected place on mobile). The old TOP pinning
   placed them under the sticky tab strip (the featured hero is pulled up flush
   beneath the nav) and an errant safe-area-inset pushed them around - both read
   as "misplaced" on a phone. Anchored at the bottom they sit over the dark
   scrim (legible) and match the bottom-sheet gallery dots. The .feat-cap below
   reserves extra bottom padding (see :not(.is-single)) so they never collide
   with the caption/button. The row is non-interactive (pointer-events: none) so
   swipes pass through to the rail; the dots themselves re-enable taps. A soft
   drop-shadow keeps them legible over bright imagery. */
.featured-dots {
  position: absolute;
  left: 0; right: 0;
  top: auto;
  bottom: var(--s-5);
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin-top: 0;
  z-index: 3;
  pointer-events: none;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.45));
}
/* Multi-slide cards reserve room at the bottom of the caption so the dot row
   (anchored at bottom: var(--s-5)) clears the eyebrow / title / button above. */
.featured-block:not(.is-single) .feat-cap { padding-bottom: var(--s-9); }
.feat-dot { pointer-events: auto; }
.featured-block.is-single .featured-dots { display: none; }
.feat-dot {
  appearance: none; border: 0; padding: 0;
  position: relative; overflow: hidden;
  flex: 0 0 auto;
  width: 6px; height: 6px; border-radius: 999px;
  background: var(--pm-hairline-strong);
  cursor: pointer;
  /* Active state grows the dot into an elongated pill (story-style). */
  transition: width 320ms cubic-bezier(.2,.7,.2,1), background 200ms ease;
}
.feat-dot.is-active { width: 26px; }
/* Play bar: the champagne fill sweeps across the active pill as the slide's
   auto-advance timer counts down (scaleX driven per-frame from JS). */
.feat-dot-fill {
  position: absolute; inset: 0;
  border-radius: inherit;
  /* Active pill / play-bar uses the primary text (ink) colour, not champagne. */
  background: var(--text);
  transform: scaleX(0); transform-origin: left center;
  pointer-events: none;
}
[dir="rtl"] .feat-dot-fill { transform-origin: right center; }
.feat-dot:not(.is-active) .feat-dot-fill { opacity: 0; }

/* ============================================================
   6. iOS SEGMENTED CONTROL + SECTION RHYTHM
   A native pill track. The active segment is a filled pill (.seg-indicator)
   that SLIDES under the chosen segment (positioned by app.js via translateX
   + width). The track is STICKY just under the navbar so segments stay
   reachable while scrolling a long section. RTL mirrors automatically (the
   flex track reverses; offsetLeft math stays correct). On a phone the track
   can scroll horizontally if the labels overflow, so 4-5 segments never cramp.
   ============================================================ */
/* KITH UNDERLINE TEXT TABS (not pills): sticky uppercase, letter-spaced text
   tabs across a hairline, with a warm-gold underline that SLIDES under the
   active tab (.seg-indicator positioned by JS). RTL mirrors automatically
   (the flex track reverses; offsetLeft math stays correct). The track can
   scroll horizontally on narrow phones so 4-5 tabs never cramp. */
.segmented {
  position: sticky;
  /* MUST match the navbar's actual height (which now uses max(env, 10px)) or the
     tab bar sticks 10px too high and content peeks through the seam = the header
     "slight scroll" jitter. */
  top: calc(var(--navbar-h, 52px) + max(env(safe-area-inset-top, 0px), 10px));
  z-index: 55;
  display: flex;
  align-items: stretch;
  /* Tighter gap so all SIX tabs (Membership / Exclusive / My Creations / Visits /
     Orders / More) pack into less width = more of them visible at once on a
     phone, so "My Creations" (3rd) is far less likely to be scrolled out of view. */
  gap: var(--s-5);
  padding: 0;
  margin: 0 calc(var(--s-5) * -1) var(--s-7);
  padding-inline: var(--s-5);
  /* Match the scrolled navbar's frosted-translucent look so the two stacked
     sticky layers (navbar + this tab track) read as one continuous frosted
     header instead of a flat-black seam under the translucent bar. */
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  backdrop-filter: blur(20px) saturate(1.4);
  border-bottom: 1px solid var(--pm-hairline);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* Only pan horizontally: a vertical swipe on the tab strip scrolls the PAGE
     instead of being captured by this sticky horizontal scroller. */
  touch-action: pan-x;
  isolation: isolate;
}
.segmented::-webkit-scrollbar { display: none; }
/* The sliding warm-gold underline. Positioned by JS (transform + width). */
.seg-indicator {
  position: absolute;
  z-index: 1;
  left: 0; bottom: -1px;
  height: 2px;
  width: 0;
  background: var(--champagne);
  border-radius: 2px;
  transition: transform 320ms cubic-bezier(.3,.7,.2,1), width 320ms cubic-bezier(.3,.7,.2,1);
  pointer-events: none;
}
.segment {
  position: relative;
  z-index: 0;
  flex: 0 0 auto;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-faint);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  height: 44px;
  padding: 0;
  cursor: pointer;
  transition: color 200ms ease;
}
[dir="rtl"] .segment { letter-spacing: 0.04em; }
.segment.is-active { color: var(--text); }
.segment:focus-visible {
  outline: none;
  color: var(--text);
  box-shadow: 0 2px 0 0 var(--champagne);
}
/* When motion is reduced the underline snaps instead of sliding. */
@media (prefers-reduced-motion: reduce) {
  .seg-indicator { transition: none; }
}

.acct-section {
  margin: 0 0 var(--s-9);
}
.section-head {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  margin-bottom: var(--s-6);
}
.section-title {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}
[dir="rtl"] .section-title { letter-spacing: 0.06em; }
/* The horizontal hairline that used to trail each section title is removed -
   the title now stands on its own (cleaner, less ruled). */
.section-rule {
  display: none;
}

/* ---- DETAILS ---- chrome-less list, hairline-separated rows ---- */
.detail-list { margin: 0; }
.detail-key, .detail-val { margin: 0; padding: var(--s-4) 0; }
.detail-key {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.10em;
  color: var(--text-faint);
  padding-bottom: 2px;
}
.detail-val {
  font-size: 16px;
  color: var(--text);
  padding-top: 0;
  border-bottom: 1px solid var(--pm-hairline);
}
.detail-list dd:last-of-type { border-bottom: 0; }

/* ---- ORDERS ---- each order is its OWN card, one by one ---- */
.orders-list { display: flex; flex-direction: column; gap: var(--s-4); }
.order-card {
  padding: var(--s-5);
  /* A standalone card per order (not a hairline-separated row). Neutralise the
     inherited .card frosted glass (fb-ui.css backdrop-filter reads as a
     beige-yellow fill over the warm canvas) and give it a clean surface. */
  background: var(--pm-surface);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid var(--pm-hairline);
  border-radius: var(--radius-card, 16px);
  box-shadow: 0 6px 18px -13px rgba(20,12,2,0.20);
}
.order-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-3); margin-bottom: var(--s-4);
}
.order-ref { font-size: 15px; font-weight: 500; letter-spacing: 0.02em; }
.order-source {
  font-size: 9.5px; letter-spacing: 0.10em; text-transform: uppercase;
  padding: 3px 9px; border-radius: var(--radius-pill);
  background: var(--pm-hairline); color: var(--text-muted);
}
.order-source.src-online { background: var(--accent-soft); color: var(--accent); }
.order-source.src-boutique { background: rgba(216,185,134,0.16); color: var(--champagne); }
.order-date { font-size: 12px; color: var(--text-faint); }
.order-meta {
  display: flex; gap: var(--s-6); flex-wrap: wrap;
  padding-bottom: var(--s-2);
}
.order-meta-cell { display: flex; flex-direction: column; gap: 2px; }
.meta-k { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.10em; color: var(--text-faint); }
.meta-v { font-size: 15px; color: var(--text); }
.order-items {
  margin: var(--s-4) 0 0; padding: var(--s-4) 0 0;
  list-style: none; border-top: 1px solid var(--pm-hairline);
}
.order-items li {
  font-size: 13px; color: var(--text-muted);
  padding: 3px 0; padding-inline-start: var(--s-4);
  position: relative;
}
.order-items li::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 11px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--champagne);
}
.order-fulfilment {
  margin: var(--s-3) 0 0;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
}
.order-timeline {
  list-style: none;
  margin: var(--s-5) 0 0;
  padding: var(--s-4) 0 0;
  border-top: 1px solid var(--pm-hairline);
}
.order-timeline li {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 5px 0 5px var(--s-4);
  position: relative;
}
.order-timeline li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--champagne);
}
.order-event-label { font-size: 12px; color: var(--text); }
.order-event-date { font-size: 11px; color: var(--text-faint); white-space: nowrap; }
.order-card.is-deep-linked {
  outline: 2px solid var(--champagne);
  outline-offset: 3px;
}
/* Order actions row: pill-shaped, branded buttons (charcoal fill). The same
   pill is reused for any sibling order action so the row stays consistent. */
.order-actions {
  display: flex; flex-wrap: wrap; gap: var(--s-3);
  margin-top: var(--s-5);
}
.order-pill {
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--s-9);
  padding: 0 var(--s-5);
  border-radius: var(--radius-pill);
  background: var(--pm-cta-bg);
  color: var(--pm-cta-ink);
  border: 1px solid var(--pm-cta-bg);
  font: inherit;
  font-size: 11px; letter-spacing: 0.10em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  transition: opacity 160ms ease, background 160ms ease, color 160ms ease;
}
.order-pill:hover { opacity: 0.88; }
/* Secondary variant (gold outline) for any non-primary sibling action. */
.order-pill.is-outline {
  background: transparent; color: var(--pm-ink);
  border-color: var(--champagne);
}
.order-pill.is-outline:hover { background: var(--champagne); color: #1a140c; opacity: 1; }

/* ============================================================
   7. MEMBERSHIP CARD - THE HERO (finished per-tier art, rendered clean)
   The cards are FINISHED art (wordmark + PRIVATE MEMBERSHIP + member
   number baked in). The portal renders the art CLEAN, with NO overlaid
   text and NO scrim. It is the prized possession: large, centred, lifted
   on a heavy luxe shadow, with a faint resting tilt that straightens on
   interaction. card-<tierCode>.jpg / membership-card.jpg are referenced
   RELATIVELY from app.js, so they must deploy alongside it in account/.
   ============================================================ */
.membership-card {
  position: relative;
  /* Inset from the screen edges by the page gutter (the card no longer bleeds to
     the edges on a phone - the card number was running off the right edge). On
     wide screens max-width caps it and margin auto centers it. */
  width: calc(100% - var(--s-5) * 2);
  max-width: var(--pm-card-max);
  margin: 0 auto;
  aspect-ratio: 1.586 / 1;
  border-radius: clamp(14px, 4vw, 22px);
  overflow: hidden;
  isolation: isolate;
  color: #fff;
  /* deep, soft luxe shadow + a faint resting tilt (straightens on hover) */
  transform: perspective(1400px) rotateX(5deg) rotateZ(-0.6deg);
  box-shadow:
    0 40px 80px -28px rgba(20,12,2,0.52),
    0 18px 36px -22px rgba(20,12,2,0.40),
    0 1px 0 0 rgba(255,255,255,0.30) inset;
  transition: transform 600ms cubic-bezier(.2,.7,.2,1), box-shadow 600ms cubic-bezier(.2,.7,.2,1);
  will-change: transform;
}
.membership-card:hover,
.membership-card:focus-within {
  transform: perspective(1400px) rotateX(0deg) rotateZ(0deg) translateY(-4px);
  box-shadow:
    0 52px 96px -30px rgba(20,12,2,0.55),
    0 22px 44px -24px rgba(20,12,2,0.42);
}
[dir="rtl"] .membership-card {
  transform: perspective(1400px) rotateX(5deg) rotateZ(0.6deg);
}
[dir="rtl"] .membership-card:hover,
[dir="rtl"] .membership-card:focus-within {
  transform: perspective(1400px) rotateX(0deg) rotateZ(0deg) translateY(-4px);
}
/* a hairline edge so the art reads as a physical card on cream */
.membership-card::after {
  content: "";
  position: absolute; inset: 0; z-index: 3;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.16);
  pointer-events: none;
}
.membership-card .mc-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block; z-index: 0;
}
/* ---- Live member info overlaid in the art's baked lower band ----
   Sits below the ::after hairline (z-index 3) and is non-interactive so
   it never blocks the Wallet control or the hover/focus tilt. A bottom-up
   scrim (::before) keeps the near-ivory text legible over the LIGHT
   (Signature), MID-DARK (Founder) and DARK (Black) tier arts alike. */
.membership-card .mc-info {
  position: absolute;
  z-index: 2;
  left: 0; right: 0; bottom: 0;
  height: 22%;
  padding: 0 8% 8%;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
  pointer-events: none;
  color: #fee5a5;
}
/* Per-tier overlay text color (chosen to read on each tier art, so no scrim):
   Signature (light) -> black, Black (dark) -> white, Founder -> cream gold. */
.membership-card[data-tier="signature"] .mc-info { color: #000; }
.membership-card[data-tier="black"] .mc-info { color: #fff; }
.membership-card[data-tier="founder"] .mc-info { color: #fee5a5; }
.membership-card .mc-info::before { content: none; }
.membership-card .mc-info-left {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.membership-card .mc-info-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: end;
  flex: 0 0 auto;
}
.membership-card .mc-info-label {
  font-size: 8px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(247,239,225,0.78);
  line-height: 1.2;
}
.membership-card .mc-info-id {
  font-size: 11px;
  letter-spacing: 0.06em;
  margin-bottom: 0.5em;
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}
.membership-card .mc-info-name {
  font-size: clamp(13px, 3.6vw, 17px);
  letter-spacing: 0.01em;
  font-weight: 500;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.membership-card .mc-info-since {
  font-size: 12px;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}
/* The scrim/overlay layers are intentionally UNUSED (the art is finished
   and rendered clean). The selectors are kept inert so any stray markup
   never paints over the card. */
.membership-card .mc-scrim,
.membership-card .mc-overlay { display: none; }

/* ============================================================
   8. MEMBERSHIP SECTION - progress + tier ladder + benefits + earn
   The live points sit in the status line under the card; this section
   is the program ladder (where you are, what is next, what it unlocks).
   ============================================================ */
.points-tier-note {
  margin: 0 0 var(--s-6);
  font-size: 14px; color: var(--text-muted); letter-spacing: 0.01em;
}

/* ---- Progress to next tier ---- */
.tier-progress {
  margin: 0 0 var(--s-7);
  max-width: 460px;
  text-align: start;
}
.tier-progress-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-3); margin-bottom: var(--s-3);
}
.tier-progress-label {
  font-size: 12px; color: var(--text-muted); letter-spacing: 0.02em;
}
.tier-progress-label strong { color: var(--text); font-weight: 500; }
.tier-progress-count {
  font-size: 11px; color: var(--text-faint);
  font-variant-numeric: tabular-nums; letter-spacing: 0.04em;
  white-space: nowrap;
}
.tier-progress-track {
  position: relative;
  height: 8px;
  border-radius: var(--radius-pill);
  background: rgba(0,0,0,0.08);
  overflow: hidden;
}
.tier-progress-fill {
  position: absolute; inset-block: 0; inset-inline-start: 0;
  width: 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--champagne), var(--accent));
  transition: width 700ms cubic-bezier(.2,.7,.2,1);
}
[dir="rtl"] .tier-progress-fill {
  background: linear-gradient(270deg, var(--champagne), var(--accent));
}
/* At the top tier there is no "next" - show a calm full champagne bar. */
.tier-progress.is-max .tier-progress-fill {
  width: 100% !important;
  background: var(--champagne);
}

/* ============================================================
   TIER WALLET - a swipeable, Apple-Wallet-style deck of the tier card arts
   (current centered) + a focused-tier panel (name + status + threshold +
   perks). Replaces the old tier-cards strip, tier ladder and Aspire deck.
   ============================================================ */
.tier-wallet { margin-top: var(--s-6); }
.tw-rail {
  display: flex; gap: var(--s-4);
  overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
  /* Full-bleed, with side padding so the first/last card can sit centered. */
  margin-inline: calc(-1 * var(--s-5));
  padding: var(--s-2) 13% var(--s-3);
}
.tw-rail::-webkit-scrollbar { display: none; }
.tw-card {
  flex: 0 0 74%;
  scroll-snap-align: center;
  cursor: pointer; opacity: 0.5;
  transition: opacity 320ms ease, transform 320ms cubic-bezier(.2,.7,.2,1);
}
.tw-card.is-focus { opacity: 1; }
.tw-card-art {
  position: relative;
  aspect-ratio: 1.586 / 1;
  border-radius: 16px; overflow: hidden;
  background: var(--pm-surface-warm);
  box-shadow: 0 12px 34px rgba(20,12,2,0.22);
}
.tw-card-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tw-card.is-locked .tw-card-art img { filter: saturate(0.72) brightness(0.98); }
.tw-card.is-focus.is-locked .tw-card-art img { filter: none; }
.tw-card.is-current.is-focus .tw-card-art {
  box-shadow: 0 14px 40px rgba(20,12,2,0.30), 0 0 0 2px var(--champagne);
}
.tw-card-art.is-placeholder::after {
  content: "F. BINSABBAR";
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 10px; letter-spacing: 0.20em; color: var(--text-faint);
}
.tw-dots { display: flex; align-items: center; justify-content: center; gap: 7px; margin-top: var(--s-4); }
/* .tw-dot reuses .feat-dot pill styling (no play-bar here, so colour it directly). */
.tw-dot.is-active { background: var(--champagne); }
.tw-panel { margin-top: var(--s-5); text-align: center; }
.tw-panel-head { display: flex; align-items: center; justify-content: center; gap: var(--s-3); flex-wrap: wrap; }
.tw-panel-name { font-size: 17px; font-weight: 500; letter-spacing: 0.04em; }
.tw-panel-tag {
  font-size: 9px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.12em;
  padding: 3px 9px; border-radius: 999px;
}
.tw-panel-tag.is-current { background: var(--champagne); color: #1a140c; }
.tw-panel-tag.is-earned { background: var(--pm-surface-3); color: var(--text-muted); box-shadow: inset 0 0 0 1px var(--pm-hairline); }
.tw-panel-threshold {
  display: block; margin-top: var(--s-2);
  font-size: 12px; letter-spacing: 0.04em; color: var(--text-muted);
}
.tw-perks {
  list-style: none; margin: var(--s-4) auto 0; padding: 0;
  max-width: 320px; display: grid; gap: var(--s-2); text-align: start;
}
.tw-perks li {
  position: relative; padding-inline-start: 18px;
  font-size: 13px; line-height: 1.45; color: var(--text);
}
.tw-perks li::before {
  content: ""; position: absolute; inset-inline-start: 3px; top: 7px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--champagne);
}
/* Small strip of every tier's card art under the bar (current tier highlighted).
   Decorative companion to the bar; scrolls horizontally if the ladder is long. */
.tier-progress-cards {
  display: flex;
  gap: var(--s-3);
  margin-top: var(--s-5);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.tier-progress-cards::-webkit-scrollbar { display: none; }
.tpc-card {
  flex: 0 0 auto;
  width: 72px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  opacity: 0.48;
  transition: opacity 300ms ease;
}
.tpc-card.is-current { opacity: 1; }
.tpc-card-art {
  width: 100%;
  aspect-ratio: 1.586 / 1;
  border-radius: 7px;
  overflow: hidden;
  background: var(--canvas-bg);
  box-shadow: 0 4px 12px -7px rgba(20,12,2,0.42);
}
.tpc-card.is-current .tpc-card-art {
  box-shadow: 0 0 0 1.5px var(--champagne), 0 6px 14px -7px rgba(20,12,2,0.5);
}
.tpc-card-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tpc-card-name {
  font-size: 9px; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--text-muted); text-align: center; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tpc-card.is-current .tpc-card-name { color: var(--text); }

/* ---- Tier ladder (vertical, with thresholds + benefits) ---- */
.tier-ladder {
  margin-top: var(--s-7);
  display: flex;
  flex-direction: column;
  gap: 0;
}
.ladder-step {
  position: relative;
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: var(--s-4);
  padding: var(--s-5) 0;
  opacity: 0.6;
  border-bottom: 1px solid var(--pm-hairline-soft);
}
.ladder-step:last-child { border-bottom: 0; }
.ladder-step.is-passed, .ladder-step.is-current { opacity: 1; }
/* connecting rail down the dot column */
.ladder-step::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  inset-inline-start: 13px;
  width: 1px;
  background: var(--pm-hairline);
}
.ladder-step:first-child::before { top: var(--s-5); }
.ladder-step:last-child::before { bottom: auto; height: var(--s-5); }
.ladder-marker {
  position: relative;
  z-index: 1;
  width: 28px;
  display: flex;
  justify-content: center;
  padding-top: 2px;
}
.ladder-dot {
  width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid rgba(0,0,0,0.18);
  background: var(--canvas-bg);
}
.ladder-step.is-passed .ladder-dot { background: var(--champagne); border-color: var(--champagne); }
.ladder-step.is-current .ladder-dot {
  background: var(--accent); border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.ladder-body { min-width: 0; }
.ladder-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-4);
}
.ladder-name-wrap { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); min-width: 0; }
.ladder-name {
  font-size: 14px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 500;
}
.ladder-step.is-current .ladder-name { color: var(--text); }
.ladder-current-tag {
  font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 2px 8px; border-radius: var(--radius-pill);
  background: var(--accent); color: #fff;
  vertical-align: middle;
}
.ladder-threshold {
  font-size: 11px; color: var(--text-faint);
  letter-spacing: 0.04em; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ladder-benefits {
  margin: var(--s-3) 0 0; padding: 0;
  list-style: none;
}
.ladder-benefits li {
  position: relative;
  font-size: 12.5px; color: var(--text-muted);
  line-height: 1.5;
  padding: 2px 0; padding-inline-start: var(--s-4);
}
.ladder-benefits li::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 9px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--champagne);
}

/* ---- "How you earn" explainer - quiet, hairline top rule, no box ---- */
.earn-card {
  margin-top: var(--s-7);
  padding: var(--s-6) 0 0;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--pm-hairline-soft);
  box-shadow: none;
}
.earn-title {
  margin: 0 0 var(--s-3);
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--champagne);
}
.earn-body {
  margin: 0;
  font-size: 13px; color: var(--text-muted); line-height: 1.65;
}

/* ---- ASPIRE - higher-tier marketing showcase (fanned card-art deck) ----
   A calm aspirational block: a small header, an overlapping deck of the higher
   tiers' card art (reusing the per-tier art the portal already loads), then a
   one-line brief per tier. Hidden by JS when the client is at the top tier. */
.aspire {
  margin-top: var(--s-8);
  padding-top: var(--s-7);
  border-top: 1px solid var(--pm-hairline-soft);
}
.aspire-head { margin-bottom: var(--s-6); }
.aspire-title {
  margin: 0 0 var(--s-2);
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--champagne);
}
.aspire-lede {
  margin: 0;
  font-size: 13px; color: var(--text-muted); line-height: 1.6;
  max-width: 46ch;
}
/* The fanned deck: overlapping cards (card aspect 1.586:1), highest tier on
   top. Each card carries --i (0-based) to step its offset + tilt. Centered. */
.aspire-deck {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin: var(--s-6) auto var(--s-7);
  height: 0;
  /* deck height = one card (card width / 1.586) + room for the wider fanned offset */
  padding-bottom: calc((300px - 80px) / 1.586 + 72px);
}
.aspire-card {
  position: absolute;
  /* Lowest tier (--i 0) sits at the FRONT of the deck; higher tiers fall behind.
     The horizontal step (40px) and card width (100% - 2*40px) are tied so the
     LAST of three cards still lands flush at the deck's trailing edge while each
     card reveals far more of its art than the old tight stack. */
  z-index: calc(100 - var(--i));
  inset-inline-start: calc(var(--i) * 40px);
  top: calc(var(--i) * 24px);
  width: calc(100% - 80px);
  aspect-ratio: 1.586 / 1;
  border-radius: clamp(10px, 3.4vw, 16px);
  overflow: hidden;
  background: var(--canvas-bg);
  box-shadow:
    0 24px 44px -22px rgba(20,12,2,0.46),
    0 8px 18px -14px rgba(20,12,2,0.34);
  transform: rotate(calc(var(--i) * -3deg));
  transform-origin: bottom center;
  transition: transform 500ms cubic-bezier(.2,.7,.2,1);
  isolation: isolate;
}
[dir="rtl"] .aspire-card { transform: rotate(calc(var(--i) * 3deg)); }
.aspire-card::after {
  content: ""; position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.14);
  pointer-events: none;
}
.aspire-card-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.aspire:hover .aspire-card,
.aspire:focus-within .aspire-card { transform: rotate(0deg); }
/* One brief line per aspirational tier. */
.aspire-list {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: var(--s-4);
}
.aspire-item {
  display: flex; flex-direction: column; gap: 3px;
  padding-inline-start: var(--s-4);
  position: relative;
}
.aspire-item::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 8px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--champagne);
}
.aspire-item-name {
  font-size: 12px; letter-spacing: 0.10em; text-transform: uppercase;
  color: var(--text); font-weight: 500;
}
.aspire-item-brief {
  font-size: 13px; color: var(--text-muted); line-height: 1.55;
}

/* ============================================================
   9. EXCLUSIVE - "Reserved for you" + Request a purchase
   ============================================================ */
/* Editorial lookbook: a big uppercase letterspaced header, then a disciplined
   square grid where the photography leads and chrome recedes (no boxes, no
   shadows around the media - the image IS the card). Tapping opens the rich
   detail view. */
.excl-lede {
  margin: 0 0 var(--s-7);
  font-size: 15px; color: var(--text-muted);
  max-width: 46ch; line-height: 1.6;
}
.excl-lede:empty { margin: 0; }
.excl-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* NO-BLEED: tiles touch edge-to-edge (no gaps/margins). Dividers are drawn as
     per-card right/bottom hairlines; the grid is pulled out of the .pm-main
     gutter so it runs to the screen edges, with a top hairline to cap it. */
  gap: 0;
  margin-inline: calc(-1 * var(--s-5));
  border-top: 1px solid var(--pm-hairline);
}
/* Clean, image-led product tile: the photography IS the card (no surface box or
   border), a softly-rounded gradient-beige well with a 1px inner hairline, and a
   quiet name / reference / price beneath. Shared by Exclusive AND My Creations. */
.excl-card {
  display: flex;
  flex-direction: column;
  /* ONE continuous cream product well across the whole tile: the same warm-beige
     gradient that the image well uses extends behind the image AND the
     name/price/tax below, so there is no seam between the media and the text. */
  background-color: var(--pm-surface-warm);
  background-image: var(--pm-well-bg);
  /* Hairline dividers between touching tiles (right + bottom). A trailing empty
     cell in an odd-count row stays borderless, so there are no stray lines. */
  border: 0;
  border-right: 1px solid var(--pm-hairline);
  border-bottom: 1px solid var(--pm-hairline);
  border-radius: 0;
  padding: 0;
  cursor: pointer;
  outline: none;
  -webkit-tap-highlight-color: transparent;
}
.excl-card .excl-name { margin-top: 0; }
#secMembershipHead { margin-top: var(--s-8); }
.excl-card:focus-visible .excl-media {
  box-shadow: 0 0 0 2px var(--canvas-bg), 0 0 0 4px var(--champagne);
}
.excl-media {
  position: relative;
  aspect-ratio: 1 / 1;
  /* Transparent: the media inherits the card's continuous well background, so the
     image area and the text area below read as ONE unbroken cream surface (no
     seam between them). */
  background: transparent;
  display: grid; place-items: center;
  overflow: hidden;
  /* Square, full-bleed well: the tile dividers do the separation now, so the
     rounded corners + inner ring are dropped. */
  border-radius: 0;
  box-shadow: none;
}
.excl-media img {
  /* Absolutely fill the well, anchored to the TOP, shown WHOLE (never cropped:
     object-fit contain). A square studio shot fills the square exactly; its own
     internal whitespace stays (trimming the source image is the real fix). */
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  object-position: center top;
  padding: 0;
  box-sizing: border-box;
  display: block;
  transition: transform 650ms cubic-bezier(.2,.7,.2,1);
}
.excl-card:hover .excl-media img { transform: scale(1.04); }
.excl-media.is-placeholder::after {
  content: "F. BINSABBAR";
  font-size: 10px; letter-spacing: 0.20em; color: var(--text-faint);
}
.excl-badge {
  position: absolute; top: var(--s-3); inset-inline-start: var(--s-3);
  font-size: 9px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 5px 11px; border-radius: var(--radius-pill);
  /* Frosted-glass PILL: translucent + blurred over the product well, with the
     kit's glass border/shadow. (No nested backdrop-filter ancestor, so Safari
     renders it cleanly.) */
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  color: var(--text-muted);
  box-shadow: var(--glass-shadow);
}
.excl-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  /* No background: the name/price/tax sit directly on the card's continuous well
     surface (no seam with the image above). Padding keeps the text inset from the
     now-touching tile edges (tiles bleed together). */
  background: transparent;
  padding: var(--s-4) var(--s-4) var(--s-5);
}
/* "Inclusive Tax" caption under the price (KSA prices are VAT-inclusive). */
.excl-tax {
  margin: 3px 0 0; font-size: 10px; letter-spacing: 0.02em;
  color: var(--text-faint);
}
/* Catalogue header: filter glyph (decorative) + product count, full-bleed and
   sitting directly above the grid (the grid's top hairline is the divider). */
.cat-bar {
  display: flex; align-items: center; justify-content: space-between;
  margin-inline: calc(-1 * var(--s-5));
  padding: var(--s-3) var(--s-5);
}
.cat-filter-ic { display: inline-flex; width: 17px; height: 17px; color: var(--text-muted); }
.cat-filter-ic svg { width: 100%; height: 100%; }
.cat-count {
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-muted);
}
[dir="rtl"] .cat-count { letter-spacing: normal; }

/* Working catalogue FILTER: the Filter button (replaces the old decorative glyph)
   + the toggled panel of category + sort chips. */
.cat-filter-btn {
  display: inline-flex; align-items: center; gap: var(--s-2);
  appearance: none; border: 0; background: transparent; cursor: pointer;
  padding: 0; font: inherit;
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-muted);
  -webkit-tap-highlight-color: transparent;
}
.cat-filter-btn:hover,
.cat-filter-btn.is-open { color: var(--text); }
.cat-filter-btn .cat-filter-ic { width: 16px; height: 16px; }
[dir="rtl"] .cat-filter-btn { letter-spacing: 0.04em; }

.filter-panel {
  padding: var(--s-4) var(--s-5) var(--s-5);
  background: var(--pm-surface-2);
  border-bottom: 1px solid var(--pm-hairline);
  display: flex; flex-direction: column; gap: var(--s-5);
  animation: pm-fade-in 200ms ease both;
}
.filter-panel[hidden] { display: none; }
.filter-row { display: flex; flex-direction: column; gap: var(--s-3); }
.filter-label {
  font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-faint);
}
[dir="rtl"] .filter-label { letter-spacing: 0.04em; }
.filter-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.filter-chip {
  appearance: none; cursor: pointer;
  border: 1px solid var(--pm-hairline-strong);
  border-radius: var(--radius-pill);
  background: transparent; color: var(--text-muted);
  font: inherit; font-size: 12px; letter-spacing: 0.02em;
  padding: 7px 14px; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.filter-chip:hover { border-color: var(--text-faint); color: var(--text); }
.filter-chip.is-active {
  background: var(--pm-ink); color: var(--canvas-bg); border-color: var(--pm-ink);
}
.excl-name {
  margin: 0; font-size: 14px; font-weight: 500; line-height: 1.3;
  letter-spacing: 0.02em;
}
.excl-ref {
  margin: 2px 0 0; font-size: 10.5px; letter-spacing: 0.10em;
  text-transform: uppercase; color: var(--text-faint);
}
.excl-price { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); letter-spacing: 0.02em; }

/* ============================================================
   FULL-BLEED EXCLUSIVE CARDS (KITH "Tier Exclusives" look)
   The reserved-for-you pieces rendered as full-width image cards with
   a bottom gradient scrim + the piece name / ref overlaid. Shown ABOVE
   the grid (the grid stays as the disciplined lookbook beneath).
   ============================================================ */
.excl-featured {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  margin: 0 0 var(--s-7);
}
.excl-feature {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 70vh;
  border-radius: var(--radius-card);
  overflow: hidden;
  /* Smooth gradient-beige well behind the piece image (no grain). */
  background-color: var(--pm-surface-warm);
  background-image: var(--pm-well-bg);
  border: 1px solid var(--pm-hairline);
  cursor: pointer;
  outline: none;
  -webkit-tap-highlight-color: transparent;
  isolation: isolate;
}
.excl-feature img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform 700ms cubic-bezier(.2,.7,.2,1);
}
.excl-feature:hover img { transform: scale(1.03); }
.excl-feature::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.78) 0%, rgba(0,0,0,0.32) 32%, transparent 58%);
  pointer-events: none;
}
.excl-feature:focus-visible { box-shadow: 0 0 0 2px var(--canvas-bg), 0 0 0 4px var(--champagne); }
.excl-feature-cap {
  position: absolute; z-index: 1;
  inset-inline: 0; bottom: 0;
  padding: var(--s-6);
  display: flex; flex-direction: column; gap: 4px;
  text-align: start;
}
.excl-feature-badge {
  align-self: flex-start;
  margin-bottom: var(--s-3);
  font-size: 9px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 4px 10px; border-radius: var(--radius-pill);
  background: var(--champagne); color: #1a140c;
}
.excl-feature-name {
  margin: 0; font-family: var(--pm-serif); font-weight: 500;
  font-size: clamp(20px, 5.6vw, 28px); line-height: 1.1; color: #f4f1ea;
  text-shadow: 0 1px 16px rgba(0,0,0,0.5);
}
.excl-feature-ref {
  margin: 2px 0 0; font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(244,241,234,0.78);
}
.excl-feature-price {
  margin: 4px 0 0; font-size: 13px; color: rgba(244,241,234,0.9); letter-spacing: 0.02em;
}
[dir="rtl"] .excl-feature-ref { letter-spacing: 0.03em; }

/* ============================================================
   9b. EXCLUSIVE - rich detail view (full-screen, swipeable gallery)
   Image-first: the gallery bleeds to the sheet edges; the piece copy
   sits in a calm, generous column beneath / beside it.
   ============================================================ */
body.pd-locked { overflow: hidden; }

/* ============================================================
   ACCOUNT-DELETION confirmation dialog (More > Account > Delete account).
   A centred, frosted card over a dimming scrim. The destructive button
   follows the house rule: red fill -> yellow text.
   ============================================================ */
.del-scrim {
  position: fixed; inset: 0; z-index: 9600;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(20, 16, 10, 0.46);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.del-sheet {
  width: 100%; max-width: 380px;
  background: var(--pm-surface);
  border: 1px solid var(--pm-hairline);
  border-radius: 18px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.28);
  padding: 24px 22px 18px;
  text-align: center;
}
.del-title {
  margin: 0 0 10px;
  font-size: 1.15rem; font-weight: 600;
  color: var(--text);
}
.del-body {
  margin: 0 0 16px;
  font-size: 0.92rem; line-height: 1.5;
  color: var(--text-muted);
}
.del-error {
  margin: 0 0 14px;
  font-size: 0.88rem; line-height: 1.45;
  color: var(--accent);
}
.del-actions { display: flex; flex-direction: column; gap: 10px; }
.del-btn {
  width: 100%; min-height: 48px;
  border-radius: 12px; border: 1px solid transparent;
  font-size: 0.98rem; font-weight: 600;
  cursor: pointer;
  transition: opacity 160ms ease, background 160ms ease;
}
.del-btn:disabled { opacity: 0.6; cursor: default; }
.del-btn-danger { background: var(--accent); color: var(--on-danger, #fee5a5); }
.del-btn-quiet {
  background: transparent;
  border-color: var(--pm-hairline-strong);
  color: var(--text);
}

.piece-detail {
  position: fixed; inset: 0; z-index: 9000;
  display: none;
}
.piece-detail.is-open { display: block; }
.pd-scrim {
  position: absolute; inset: 0;
  background: rgba(14,11,6,0.62);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: pm-fade-in 240ms ease both;
}
.pd-sheet {
  position: absolute;
  inset-inline: 0; bottom: 0; top: auto;
  max-height: 94vh;
  background: var(--canvas-bg);
  border-radius: 22px 22px 0 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 -18px 60px rgba(20,12,2,0.34);
  animation: sheet-up 360ms cubic-bezier(.2,.7,.2,1) both;
}
@keyframes pd-rise { from { transform: translateY(36px); opacity: 0; } to { transform: none; opacity: 1; } }
/* Native iOS bottom-sheet presentation: the whole sheet slides up from below the
   screen edge (translateY 100% -> 0), not a small nudge. Used by the bottom-
   anchored sheets (piece detail, booking, request thread). The scrim fades in
   separately. The centered service-request modal keeps the subtle pd-rise. */
@keyframes sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
/* Dismiss = the OPPOSITE slide: the sheet slides back DOWN off the bottom edge
   while the scrim fades. JS adds .is-closing to the overlay root for the
   duration, then drops .is-open once the slide finishes. */
@keyframes sheet-down { from { transform: translateY(0); } to { transform: translateY(100%); } }
@keyframes pm-fade-out { from { opacity: 1; } to { opacity: 0; } }
/* Dismiss is intentionally snappier than the 360ms open (iOS feel): the sheet
   slides out in 240ms and the scrim clears in 170ms - both faster than open. */
.is-closing .pd-sheet,
.is-closing .book-sheet,
.is-closing .thread-sheet,
.is-closing .requests-sheet {
  animation: sheet-down 240ms cubic-bezier(.4,0,1,1) both;
}
.is-closing .pd-scrim,
.is-closing .book-scrim,
.is-closing .thread-scrim,
.is-closing .requests-scrim {
  animation: pm-fade-out 170ms ease both;
}
.pd-close {
  position: absolute; z-index: 3;
  top: var(--s-4); inset-inline-end: var(--s-4);
  width: var(--s-9); height: var(--s-9);
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  color: var(--pm-ink); cursor: pointer;
  box-shadow: var(--glass-shadow);
}
.pd-close svg { width: 18px; height: 18px; }

/* ---- gallery ---- */
.pd-gallery {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  /* Smooth gradient-beige product well (no grain) so the jewel sits on a warm,
     light surface consistent with the theme. The piece photo is letterboxed
     (object-fit: contain) on this gradient so nothing is cropped. */
  background-color: var(--pm-surface-warm);
  background-image: var(--pm-well-bg);
  overflow: hidden;
}
.pd-gallery.is-empty::after {
  content: "F. BINSABBAR";
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 11px; letter-spacing: 0.22em; color: var(--text-faint);
}
.pd-track {
  display: flex;
  height: 100%;
  /* Force LTR so the slide order + translate math is identical in both
     directions; the arrow/swipe INTENT mapping handles RTL, not the layout. */
  direction: ltr;
  transition: transform 420ms cubic-bezier(.2,.7,.2,1);
  will-change: transform;
}
.pd-slide { flex: 0 0 100%; height: 100%; }
/* Gallery images are non-selectable / non-draggable, and pointer-events:none so
   a swipe never starts a native image drag or text selection (the swipe gesture
   is handled on the .pd-gallery container, not the IMG).
   The DETAIL image shows at its NATURAL aspect WITHOUT cropping: object-fit
   contain inside the 1:1 (square) gallery frame, letterboxed on the gradient
   beige so the WHOLE piece is visible (nothing cut off). */
.pd-gallery img,
.pd-slide img {
  width: 100%; height: 100%; object-fit: contain; object-position: top; display: block;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
/* Bottom-sheet gallery pagination: identical pill dots to the main Featured
   carousel (.feat-dot) - inactive = a small round dot, active = an elongated
   pill - but STATIC (no auto-rotation, so no play-bar sweep). Dark ink dots on
   the light cream product well (the inverse of the carousel's white-on-image). */
.pd-dots {
  position: absolute; z-index: 2;
  inset-inline: 0; bottom: var(--s-4);
  display: flex; justify-content: center; align-items: center; gap: 7px;
}
.pd-dot {
  appearance: none; border: 0; padding: 0;
  flex: 0 0 auto;
  width: 6px; height: 6px; border-radius: 999px;
  /* Inactive ink dot at 28% (matches the Featured carousel's inactive dot
     weight) so it reads clearly on the light cream gallery well; the active
     pill below fills to solid ink. */
  background: rgba(0,0,0,0.28);
  cursor: pointer;
  transition: width 320ms cubic-bezier(.2,.7,.2,1), background 200ms ease;
}
.pd-dot.is-active {
  width: 26px;
  background: var(--text);
}
.pd-badge {
  position: absolute; z-index: 2;
  top: var(--s-4); inset-inline-start: var(--s-4);
}

/* ---- 3D / AR launcher (gallery overlay) ---- */
/* Anchored to the gallery's bottom-end corner so it clears BOTH the sheet
   close button (top-end) and the centered dots row (bottom-center). */
.pd-3d-btn {
  position: absolute; z-index: 2;
  bottom: var(--s-4); inset-inline-end: var(--s-4);
  display: inline-flex; align-items: center; gap: 7px;
  height: var(--s-9); padding: 0 14px;
  border: 0; border-radius: var(--radius-pill);
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  color: var(--pm-ink); cursor: pointer;
  box-shadow: var(--glass-shadow);
  font: inherit; font-size: 10.5px;
  letter-spacing: 0.10em; text-transform: uppercase;
}
.pd-3d-btn svg { width: 16px; height: 16px; flex: 0 0 auto; }
.pd-3d-btn-label { white-space: nowrap; }

/* ---- detail body ---- */
.pd-body {
  padding: var(--s-7) var(--s-6) var(--s-8);
  max-width: 560px;
  margin: 0 auto;
  align-self: start;
}
.pd-name {
  margin: 0; font-size: 26px; font-weight: 500; line-height: 1.15;
  letter-spacing: 0.01em;
}
.pd-name-ar {
  margin: var(--s-3) 0 0;
  font-size: 15px; font-weight: 500; line-height: 1.4;
  color: var(--text-muted);
}
.pd-ref {
  margin: var(--s-3) 0 0;
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint);
}
.pd-price-wrap {
  margin: var(--s-5) 0 0;
  /* logical start so the price/VAT hug the inline-start edge in both LTR and RTL */
  display: flex; flex-direction: column; align-items: start;
  gap: 3px;
}
.pd-price {
  margin: 0;
  font-size: 22px; font-weight: 500; color: var(--text); letter-spacing: 0.01em;
}
.pd-vat {
  font-size: 10px; letter-spacing: 0.10em; text-transform: uppercase;
  color: var(--text-faint);
}
/* Highlight chips (jewel.tags) - lookbook pills under the price. */
.pd-tags {
  margin: var(--s-5) 0 0;
  display: flex; flex-wrap: wrap; gap: var(--s-3);
}
.pd-tag {
  display: inline-flex; align-items: center;
  height: 24px; padding: 0 11px;
  border-radius: var(--radius-pill);
  background: var(--pm-hairline);
  color: var(--text-muted);
  font-size: 9px; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
  white-space: nowrap;
}
/* NB: no stock/availability status pill in the client detail view - internal
   stock state is never shown to clients (and the CF never sends the data). */
/* "Make it yours!" personalization line. */
.pd-make-yours {
  margin: var(--s-4) 0 0;
  font-size: 14px; color: var(--text-muted);
  letter-spacing: 0.02em;
}
/* About-the-collection sub-labels (tagline / brief). */
.pd-coll-label {
  margin: var(--s-4) 0 var(--s-2);
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint);
}
.pd-coll-label:first-child { margin-top: 0; }
.pd-section { margin-top: var(--s-7); }
.pd-section-head {
  margin: 0 0 var(--s-3);
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--champagne);
}
.pd-desc { margin: 0; font-size: 15px; color: var(--text-muted); line-height: 1.7; }
.pd-specs { margin: 0; }
/* One row per spec: the key + value group as a single pair, with the divider
   and padding on the ROW (not the dd). So even a lone spec (e.g. a single
   "Category") reads as a label under its DETAILS header, not a second header. */
.pd-spec-row {
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--pm-hairline-soft);
}
.pd-spec-row:first-child { padding-top: 0; }
.pd-spec-row:last-child  { border-bottom: 0; padding-bottom: 0; }
.pd-specs dt {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.10em;
  color: var(--text-faint);
}
.pd-specs dd {
  margin: 2px 0 0; font-size: 15px; color: var(--text);
}
/* Arabic: drop the Latin letter-spacing that fragments connected glyphs in the
   detail-sheet captions / spec keys / order-card labels. */
[dir="rtl"] .pd-section-head,
[dir="rtl"] .pd-coll-label,
[dir="rtl"] .pd-specs dt,
[dir="rtl"] .pd-ref,
[dir="rtl"] .pd-vat,
[dir="rtl"] .meta-k { letter-spacing: normal; }
.pd-request {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-3);
  width: 100%;
  margin-top: var(--s-8);
  height: var(--s-9);
  padding: 0 var(--s-6);
  border-radius: var(--radius-pill);
  border: 0;
  background: var(--pm-cta-bg);
  color: var(--pm-cta-ink);
  font: inherit; font-size: 12px;
  letter-spacing: 0.12em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  transition: opacity 160ms ease;
}
.pd-request:hover { opacity: 0.88; }
.pd-request svg { width: 17px; height: 17px; }

/* ---- 3D / AR viewer modal (sits above the detail sheet) ---- */
.pd3d {
  position: fixed; inset: 0; z-index: 9100;
  display: none;
}
.pd3d.is-open { display: block; }
/* Full-screen: the embedded Studio Viewer fills the entire viewport, so the
   backdrop is a solid dark canvas (no blur - nothing shows through). */
.pd3d-scrim {
  position: absolute; inset: 0;
  background: #0b0906;
  animation: pm-fade-in 220ms ease both;
}
.pd3d-stage { position: absolute; inset: 0; }
.pd3d-close {
  position: absolute; z-index: 5;
  top: calc(var(--s-4) + env(safe-area-inset-top, 0px)); inset-inline-end: var(--s-5);
  width: var(--s-9); height: var(--s-9);
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  color: var(--pm-ink); cursor: pointer;
  box-shadow: var(--glass-shadow);
}
.pd3d-close svg { width: 18px; height: 18px; }
.pd3d-note {
  position: absolute; z-index: 4;
  top: 50%; inset-inline: 0; transform: translateY(-50%);
  margin: 0; text-align: center;
  font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
  color: rgba(255,255,255,0.7);
  pointer-events: none;
}
.pd3d-host {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
}
/* Now an <iframe> (Studio Viewer) filling the whole screen. */
.pd3d-viewer {
  width: 100%; height: 100%;
  border: 0; display: block;
  background: transparent;
}
.pd3d-fail {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--s-5); padding: var(--s-6);
  text-align: center;
}
.pd3d-fail-note {
  margin: 0; max-width: 32ch; text-align: center;
  font-size: 12px; letter-spacing: 0.04em; line-height: 1.6;
  color: rgba(255,255,255,0.78);
}
/* The raw-file link wraps long URLs; the Studio CTA is the solid pill. */
.pd3d-fail .pd3d-fallback:not(.pd3d-fallback-studio) {
  height: auto; padding: var(--s-3) var(--s-5);
  max-width: 90%; word-break: break-all;
  text-transform: none; letter-spacing: 0.02em; font-size: 11px;
  background: transparent; border: 1px solid rgba(255,255,255,0.22);
  color: rgba(255,255,255,0.82); box-shadow: none;
}
.pd3d-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--s-9); padding: 0 var(--s-6);
  border-radius: var(--radius-pill);
  background: var(--glass-bg-strong);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  color: var(--pm-ink);
  font-size: 12px; letter-spacing: 0.10em; text-transform: uppercase;
  text-decoration: none;
  box-shadow: var(--glass-shadow);
}

/* tablet / desktop: image-left, copy-right editorial split */
@media (min-width: 760px) {
  .piece-detail.is-open { display: grid; place-items: center; }
  .pd-sheet {
    position: relative; inset: auto;
    width: min(92vw, 980px);
    max-height: 90vh;
    border-radius: 18px;
    display: grid;
    grid-template-columns: 1.05fr 1fr;
  }
  .pd-gallery { aspect-ratio: auto; height: 100%; }
  .pd-body { align-self: center; max-width: none; padding: var(--s-8) var(--s-8); }
  .pd-close { background: var(--glass-bg-strong); }
  /* Desktop: the image column is fixed height (doesn't scroll), so pin the
     "View in 3D" button to the TOP of it (mobile keeps it bottom-anchored). */
  .pd-3d-btn { top: var(--s-4); bottom: auto; }
}

/* ============================================================
   10. EMPTY NOTES / MESSAGE SCREEN
   ============================================================ */
.empty-note {
  text-align: center; color: var(--text-muted); font-size: 14px;
  line-height: 1.6; max-width: 420px; margin: var(--s-9) auto; padding: 0 var(--s-4);
}
.screen-message { min-height: 60vh; display: none; }
.screen-message.is-active { display: grid; place-items: center; }
.message-inner { text-align: center; max-width: 420px; padding: var(--s-8) var(--s-5); }
.message-mark {
  width: 44px; height: 44px; margin: 0 auto var(--s-5);
  border-radius: 50%; border: 1px solid var(--pm-hairline-strong);
  display: grid; place-items: center;
}
.message-mark::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.message-inner h2 { margin: 0 0 var(--s-3); font-size: 22px; font-weight: 500; }
.message-inner p { margin: 0 0 var(--s-6); color: var(--text-muted); line-height: 1.6; font-size: 15px; }

/* ============================================================
   11. NATIVE INSET-GROUPED LISTS (iOS) + the "More" segment
   The native feel: rounded inset-grouped containers, hairline separators
   between rows, a leading icon, a title, and a trailing value or chevron.
   Used by Orders, Service requests, Details, and all the More content.
   ============================================================ */
/* Quiet uppercase group title above each inset group (iOS "list section"). */
.group-title {
  margin: var(--s-7) var(--s-2) var(--s-3);
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint);
}
[dir="rtl"] .group-title { letter-spacing: normal; }
.sec-more > .group-title:first-child,
.sec-more > .inset-group:first-child { margin-top: 0; }

/* The rounded grouped container. Rows inside it are hairline-separated. */
.inset-group {
  margin: 0 0 var(--s-2);
  border-radius: var(--radius-card, 16px);
  background: var(--pm-surface);
  border: 1px solid var(--pm-hairline);
  overflow: hidden;
}

/* One row: leading icon (optional) / label / trailing value or chevron.
   The hairline separator sits on every row except the last, and is inset to
   start after the leading icon (iOS style) when an icon is present. */
.row {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  width: 100%;
  margin: 0;
  padding: var(--s-4) var(--s-5);
  min-height: 50px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--pm-hairline-soft);
  font: inherit;
  color: var(--text);
  text-align: start;
  text-decoration: none;
  cursor: default;
}
.inset-group > .row:last-child,
.inset-group .orders-list .order-card:last-child,
.inset-group .svc-list > *:last-child { border-bottom: 0; }
a.row, button.row { cursor: pointer; -webkit-tap-highlight-color: transparent; }
a.row:active, button.row:active { background: rgba(0,0,0,0.04); }
.row-ic {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  color: var(--text-muted);
}
.row-ic svg { width: 20px; height: 20px; }
.row-label { flex: 1 1 auto; min-width: 0; font-size: 15px; color: var(--text); }
.row-value {
  flex: 0 0 auto;
  font-size: 15px; color: var(--text-muted);
  text-align: end; max-width: 56%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row-value[dir="ltr"] { unicode-bidi: isolate; }
/* Trailing chevron (links that navigate out). Mirrors in RTL. */
.row-chevron::after {
  content: "";
  flex: 0 0 auto;
  width: 8px; height: 8px;
  border-top: 1.6px solid var(--text-faint);
  border-inline-end: 1.6px solid var(--text-faint);
  transform: rotate(45deg);
  margin-inline-start: var(--s-3);
}
[dir="rtl"] .row-chevron::after { transform: rotate(225deg); }
.row-static { color: var(--text-muted); cursor: default; }
.row-address { font-size: 13.5px; color: var(--text-muted); line-height: 1.5; }
.row-danger .row-label, .row-danger .row-ic { color: var(--accent); }

/* Orders / Details / Service requests sit INSIDE an inset group: strip their
   own outer chrome and let the group own the rounding + separators. */
.inset-group .detail-list { margin: 0; }
.inset-group .detail-key {
  padding: var(--s-4) var(--s-5) 2px;
}
.inset-group .detail-val {
  padding: 0 var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--pm-hairline-soft);
}
.inset-group .detail-list dd:last-of-type { border-bottom: 0; }
.inset-group .orders-list { gap: 0; }
.inset-group .order-card {
  padding: var(--s-5) var(--s-5);
  border-bottom: 1px solid var(--pm-hairline-soft);
}
.inset-group .orders-list .order-card:last-child { border-bottom: 0; }
.inset-group .svc-list { gap: 0; }
.inset-group .svc-req-card {
  padding: var(--s-5) var(--s-5);
  background: transparent;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: 0; border-bottom: 1px solid var(--pm-hairline-soft);
  box-shadow: none; border-radius: 0;
}
.inset-group .svc-list .svc-req-card:last-child { border-bottom: 0; }

/* The quiet legal footnote at the very bottom of More (former footer base). */
.more-legal {
  margin: var(--s-8) auto var(--s-4);
  padding-top: var(--s-6);
  border-top: 1px solid var(--pm-hairline-soft);
  text-align: center;
}
.more-legal-brand { margin: 0 0 var(--s-2); font-size: 14px; letter-spacing: 0.18em; font-weight: 500; color: var(--text-muted); }
.more-legal-brand sup { font-size: 8px; }
.more-legal-line { margin: 0; font-size: 10.5px; color: var(--text-faint); letter-spacing: 0.03em; line-height: 1.6; }
[dir="rtl"] .more-legal-brand, [dir="rtl"] .more-legal-line { letter-spacing: normal; }

/* ============================================================
   12. RESPONSIVE + RTL + REDUCED MOTION
   ============================================================ */
@media (min-width: 600px) {
  .excl-grid { grid-template-columns: repeat(3, 1fr); }
}
/* From tablet up the card-as-hero can stand a touch larger and more imposing. */
@media (min-width: 760px) {
  .acct-stage { --pm-card-max: 520px; }
}
@media (max-width: 380px) {
  .wm-img { height: 13px; }
}

/* RTL: keep numbers/phone/card-number LTR but flip layout where needed */
[dir="rtl"] .order-head { direction: rtl; }
[dir="rtl"] .dial,
[dir="rtl"] .phone-input,
[dir="rtl"] .otp-boxes { direction: ltr; }

@media (prefers-reduced-motion: reduce) {
  .screen.is-active { animation: none; }
  .boot-mark { animation-duration: 1600ms; }
  .tier-progress-fill { transition: none; }
  /* Present the card flat (no resting tilt) when motion is reduced. */
  .membership-card,
  .membership-card:hover,
  .membership-card:focus-within,
  [dir="rtl"] .membership-card,
  [dir="rtl"] .membership-card:hover,
  [dir="rtl"] .membership-card:focus-within {
    transform: none;
    transition: none;
  }
}

/* ============================================================
   MEMBERSHIP APP - My Creations / Visits / Concierge / Service
   Added with the feature-complete build. Reuses the kit tokens
   and the existing card / pill / overlay patterns above.
   ============================================================ */

/* ---- Concierge CTA (sits under the membership card) ---- */
.acct-concierge { margin-top: var(--s-5); text-align: center; }
.concierge-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-3);
  height: var(--s-9);
  padding: 0 var(--s-6);
  border-radius: var(--radius-pill);
  background: var(--pm-cta-bg);
  color: var(--pm-cta-ink);
  border: 1px solid var(--pm-cta-bg);
  font: inherit; font-size: 12px;
  letter-spacing: 0.10em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  transition: opacity 160ms ease;
}
.concierge-btn:hover { opacity: 0.88; }
.concierge-ic { display: inline-flex; }
.concierge-ic svg { width: 16px; height: 16px; }

/* ---- My Creations: the "acquired" line on an owned-piece card ---- */
.excl-acquired {
  margin: 4px 0 0; font-size: 10.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
}
[dir="rtl"] .excl-acquired { letter-spacing: normal; }

/* ---- Owned-mode meta inside the piece detail (acquired / serial) ---- */
.pd-owned-meta {
  margin-top: var(--s-5);
  border: 1px solid var(--pm-hairline);
  border-radius: var(--radius-card);
  padding: var(--s-2) var(--s-5);
  background: var(--pm-surface);
}
.pd-owned-row {
  display: flex; align-items: baseline; gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--pm-hairline-soft);
}
.pd-owned-row:last-child { border-bottom: 0; }
.pd-owned-k {
  flex: 0 0 110px; font-size: 10.5px; letter-spacing: 0.10em;
  text-transform: uppercase; color: var(--text-faint);
}
[dir="rtl"] .pd-owned-k { letter-spacing: normal; }
.pd-owned-v { flex: 1 1 auto; min-width: 0; font-size: 15px; color: var(--text); }

/* ---- Status pill (shared by visits + service requests) ---- */
.visit-status {
  display: inline-flex; align-items: center;
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.10em; text-transform: uppercase;
  padding: 4px 10px; border-radius: var(--radius-pill);
  background: var(--pm-hairline); color: var(--text-muted); white-space: nowrap;
}
[dir="rtl"] .visit-status { letter-spacing: normal; }
.visit-status.ok { background: rgba(40,120,70,0.14); color: #2c7a4b; }
.visit-status.pending { background: var(--accent-soft, rgba(247,72,39,0.12)); color: var(--accent); }
.visit-status.off { background: var(--pm-hairline); color: var(--text-faint); }

/* ---- Visits list ---- (native rounded surfaces, hairline, no frosted glass) */
.visits-list { display: flex; flex-direction: column; gap: var(--s-4); }
.visit-card {
  padding: var(--s-5);
  background: var(--pm-surface);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border: 1px solid var(--pm-hairline);
  border-radius: var(--radius-card, 16px);
  box-shadow: none;
}
.visit-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.visit-when { font-size: 15px; font-weight: 500; color: var(--text); letter-spacing: 0.01em; }
.visit-meta { margin: var(--s-4) 0 0; }
.visit-meta dt {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.10em; color: var(--text-faint);
  margin-top: var(--s-3);
}
[dir="rtl"] .visit-meta dt { letter-spacing: normal; }
.visit-meta dd { margin: 2px 0 0; font-size: 14px; color: var(--text); }
.visit-notes { margin: var(--s-4) 0 0; font-size: 13.5px; color: var(--text-muted); line-height: 1.6; }
.visit-actions { margin-top: var(--s-4); }

/* ---- "Book a visit" CTA (opens the booking page in a modal) ----
   A single full-width champagne pill directly under the visits list. No
   inline iframe, so there is no empty gap between the last visit and this. */
.visit-book-cta {
  width: 100%;
  justify-content: center;
  margin-top: var(--s-6);
  background: var(--pm-cta-bg);
  color: var(--pm-cta-ink);
  border: 1px solid var(--pm-cta-bg);
}
.visit-book-cta:hover { opacity: 0.92; }

/* ---- Booking MODAL (full-screen rising sheet, mirrors .thread-modal) ----
   Opened on demand from .visit-book-cta; the public booking page (book.html)
   is lazy-loaded into the iframe the first time the modal opens. */
.book-modal { position: fixed; inset: 0; z-index: 9200; display: none; }
.book-modal.is-open { display: block; }
.book-scrim {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.42);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: pm-fade-in 220ms ease both;
}
.book-sheet {
  position: absolute; inset-inline: 0; bottom: 0; top: auto;
  height: 94vh; max-height: 94vh;
  display: flex; flex-direction: column;
  background: var(--canvas-bg);
  border-radius: 22px 22px 0 0;
  overflow: hidden;
  box-shadow: 0 -18px 60px rgba(0,0,0,0.22);
  animation: sheet-up 360ms cubic-bezier(.2,.7,.2,1) both;
}
.book-head {
  position: relative; flex: 0 0 auto;
  padding: var(--s-6) var(--s-6) var(--s-5);
  padding-inline-end: calc(var(--s-6) + 44px);
  border-bottom: 1px solid var(--pm-hairline);
}
.book-eyebrow {
  margin: 0 0 var(--s-2);
  font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--champagne);
}
[dir="rtl"] .book-eyebrow { letter-spacing: 0.04em; }
.book-title { margin: 0; font-size: 22px; line-height: 1.2; color: var(--text); letter-spacing: 0.01em; }
.book-close {
  position: absolute; top: var(--s-4); inset-inline-end: var(--s-4);
  width: var(--s-9); height: var(--s-9);
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--pm-surface-2);
  color: var(--text); cursor: pointer;
}
.book-close svg { width: 18px; height: 18px; }
.book-body {
  flex: 1 1 auto; position: relative;
  display: flex; min-height: 0;
  /* the booking page carries its own bottom safe-area padding */
}
.book-frame {
  flex: 1 1 auto;
  width: 100%; height: 100%;
  border: 0; display: block;
  background: var(--canvas-bg);
}

/* ---- Service requests list ---- */
.svc-list { display: flex; flex-direction: column; gap: var(--s-3); }
.svc-req-card { padding: var(--s-5); }
.svc-req-top { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }
.svc-req-piece { font-size: 14px; font-weight: 500; color: var(--text); }
.svc-req-type { margin: var(--s-3) 0 0; font-size: 13px; color: var(--text-muted); }
.svc-req-notes { margin: var(--s-2) 0 0; font-size: 13px; color: var(--text-faint); line-height: 1.6; }

/* ---- Service-request modal (mirrors the piece-detail overlay) ---- */
.svc-modal { position: fixed; inset: 0; z-index: 9200; display: none; }
.svc-modal.is-open {
  display: grid; place-items: center;
  /* Safe-area gutters so the centered sheet can never slide under the notch /
     Dynamic Island (top) or the home indicator (bottom). The native shell hands
     the full screen to the web (viewport-fit=cover, .ignoresSafeArea), so the
     web must self-inset - the sheet had no env() insets and was being clipped. */
  padding:
    calc(env(safe-area-inset-top, 0px) + var(--s-4))
    calc(env(safe-area-inset-right, 0px) + var(--s-4))
    calc(env(safe-area-inset-bottom, 0px) + var(--s-4))
    calc(env(safe-area-inset-left, 0px) + var(--s-4));
  box-sizing: border-box;
}
.svc-scrim {
  position: absolute; inset: 0;
  background: rgba(14,11,6,0.62);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.svc-sheet {
  position: relative;
  /* Width/height resolve against the safe-area-padded grid cell, so the sheet
     always fits fully on screen and scrolls internally if taller. */
  width: min(460px, 100%); max-height: 100%; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--canvas-bg);
  border-radius: 22px;
  box-shadow: 0 24px 70px rgba(20,12,2,0.40);
  padding: var(--s-7) var(--s-6) var(--s-6);
  animation: pd-rise 320ms cubic-bezier(.2,.7,.2,1) both;
}
.svc-title { margin: 0; font-size: 19px; font-weight: 500; letter-spacing: 0.01em; }
.svc-piece {
  margin: var(--s-2) 0 var(--s-5); font-size: 12px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-faint);
}
[dir="rtl"] .svc-piece { letter-spacing: normal; }
.svc-form .field-label { display: block; margin: var(--s-5) 0 var(--s-2); }
.svc-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.svc-chip {
  appearance: none; font: inherit;
  height: var(--s-9); padding: 0 var(--s-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--control-border, var(--pm-hairline));
  background: var(--pm-surface-3);
  color: var(--text); font-size: 12.5px; cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
.svc-chip:hover { border-color: var(--champagne); }
.svc-chip.sel { background: var(--champagne); color: #1a140c; border-color: var(--champagne); }
.svc-notes { width: 100%; min-height: 84px; resize: vertical; }
.svc-date { width: 100%; }
.svc-form-note { margin: var(--s-4) 0 0; min-height: 16px; font-size: 12.5px; color: var(--text-muted); }
.svc-form-note.is-error { color: var(--accent); }
.svc-form-note.is-ok { color: #2c7a4b; }
.svc-submit { width: 100%; margin-top: var(--s-4); justify-content: center; }
.svc-submit.is-busy { opacity: 0.6; pointer-events: none; }
/* Required-field gate: dimmed + inert until a service type is selected. */
.svc-submit:disabled { opacity: 0.4; pointer-events: none; }

/* ---- Notifications (push consent) - Details tab settings block ----
   A quiet settings block: a small section header, two label + switch rows
   (hairline-separated), then a helper line. The switch reuses the rank ramp
   ink (charcoal track when ON) and the kit control heights. Push is opt-in/
   opt-out only; it is never required. */
.notif-block { margin-top: 0; }
.notif-list { margin: 0; }
.notif-list.inset-group { border-top: 0; }
.notif-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  min-height: 50px;
  border-bottom: 1px solid var(--pm-hairline-soft);
}
.notif-list .notif-row:last-child { border-bottom: 0; }
.notif-label {
  font-size: 15px; color: var(--text);
  letter-spacing: 0.01em;
}
.notif-switch {
  appearance: none; -webkit-appearance: none;
  position: relative; flex: 0 0 auto;
  width: 46px; height: var(--s-9);
  padding: 0; margin: 0;
  border-radius: var(--radius-pill);
  border: 1px solid var(--control-border, var(--pm-hairline));
  background: rgba(0,0,0,0.10);
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease;
}
.notif-switch .notif-knob {
  position: absolute; top: 50%; inset-inline-start: 3px;
  transform: translateY(-50%);
  width: 20px; height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(20,12,2,0.30);
  transition: inset-inline-start 200ms cubic-bezier(.2,.7,.2,1);
}
.notif-switch.is-on {
  background: var(--champagne);
  border-color: var(--champagne);
}
.notif-switch.is-on .notif-knob {
  inset-inline-start: calc(100% - 23px);
}
.notif-switch:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--canvas-bg), 0 0 0 4px var(--champagne);
}
.notif-helper {
  margin: var(--s-3) var(--s-2) 0;
  font-size: 12px; color: var(--text-faint); line-height: 1.6;
}

/* ============================================================
   MEMBER INBOX - request rows + the request THREAD view (sub-sheet)
   The member's own requests render as inbox rows (subject + status pill +
   unread dot + last activity). Tapping opens a THREAD overlay (mirrors the
   service-modal pattern): details header + the message bubbles + a reply box.
   ============================================================ */

/* ---- Inbox rows (inside an inset group, under a group title) ---- */
.req-list { display: flex; flex-direction: column; gap: 0; }
.req-row {
  display: flex; align-items: center; gap: var(--s-4);
  width: 100%; margin: 0;
  padding: var(--s-5) var(--s-5);
  background: transparent; border: 0;
  border-bottom: 1px solid var(--pm-hairline-soft);
  font: inherit; color: var(--text); text-align: start;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
/* The last row KEEPS its hairline (closing divider) so the sheet ends with the
   same border seen between tiles, matching the request-detail sheet. */
.req-row:active { background: rgba(0,0,0,0.04); }
.req-unread {
  flex: 0 0 auto;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  visibility: hidden;
}
.req-row.is-unread .req-unread { visibility: visible; }
.req-row-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.req-row-subject {
  font-size: 15px; color: var(--text); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.req-row-meta {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  font-size: 11px; color: var(--text-faint);
}
.req-row-when { font-variant-numeric: tabular-nums; }
.req-row-ticket {
  font-variant-numeric: tabular-nums; letter-spacing: 0.03em;
  color: var(--text-muted); font-weight: 500;
}
.req-row-chev {
  flex: 0 0 auto; width: 8px; height: 8px;
  border-top: 1.6px solid var(--text-faint);
  border-inline-end: 1.6px solid var(--text-faint);
  transform: rotate(45deg);
  margin-inline-start: var(--s-2);
}
[dir="rtl"] .req-row-chev { transform: rotate(225deg); }

/* ---- Thread overlay (full-screen rising sheet) ---- */
.thread-modal { position: fixed; inset: 0; z-index: 9200; display: none; }
.thread-modal.is-open { display: block; }
.thread-scrim {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.66);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: pm-fade-in 220ms ease both;
}
.thread-sheet {
  position: absolute; inset-inline: 0; bottom: 0; top: auto;
  max-height: 94vh;
  display: flex; flex-direction: column;
  background: var(--canvas-bg);
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -18px 60px rgba(0,0,0,0.5);
  animation: sheet-up 360ms cubic-bezier(.2,.7,.2,1) both;
}
.thread-head {
  position: relative;
  padding: var(--s-7) var(--s-6) var(--s-5);
  /* clear the absolutely-positioned close button (top inline-end) */
  padding-inline-end: calc(var(--s-6) + 44px);
  border-bottom: 1px solid var(--pm-hairline);
  flex: 0 0 auto;
}
.thread-eyebrow {
  margin: 0 0 var(--s-2);
  font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--champagne);
}
[dir="rtl"] .thread-eyebrow { letter-spacing: 0.04em; }
.thread-subject {
  margin: 0; font-size: 22px; line-height: 1.2; color: var(--text); letter-spacing: 0.01em;
}
.thread-meta {
  margin: var(--s-3) 0 0;
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  font-size: 12px; color: var(--text-muted);
}
.thread-close {
  position: absolute; top: var(--s-4); inset-inline-end: var(--s-4);
  width: var(--s-9); height: var(--s-9);
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--pm-surface-2);
  color: var(--text); cursor: pointer;
}
.thread-close svg { width: 18px; height: 18px; }
/* ---- message stream ---- */
.thread-body {
  flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch;
  /* Full-bleed detail card: the inset detail-list runs edge to edge (its keys/
     values carry an s-5 inset). No side/top padding on the scroller. */
  padding: 0 0 calc(var(--s-6) + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; gap: var(--s-4);
}
.thread-empty {
  margin: var(--s-6) auto; text-align: center;
  font-size: 13px; color: var(--text-faint); max-width: 32ch; line-height: 1.6;
}
.msg {
  max-width: 82%;
  padding: var(--s-4) var(--s-5);
  border-radius: 16px;
  font-size: 14px; line-height: 1.5;
}
.msg-from-client {
  align-self: flex-end;
  background: var(--champagne); color: #1a140c;
  border-bottom-right-radius: 5px;
}
[dir="rtl"] .msg-from-client { border-bottom-right-radius: 16px; border-bottom-left-radius: 5px; }
.msg-from-staff {
  align-self: flex-start;
  background: var(--pm-surface-2); color: var(--text);
  border: 1px solid var(--pm-hairline);
  border-bottom-left-radius: 5px;
}
[dir="rtl"] .msg-from-staff { border-bottom-left-radius: 16px; border-bottom-right-radius: 5px; }
.msg-who {
  display: block; margin-bottom: 3px;
  font-size: 9.5px; letter-spacing: 0.10em; text-transform: uppercase;
  opacity: 0.7;
}
[dir="rtl"] .msg-who { letter-spacing: 0.02em; }
.msg-when {
  display: block; margin-top: var(--s-2);
  font-size: 10px; opacity: 0.6; font-variant-numeric: tabular-nums;
}
/* Staff (dark) bubble: opacity on the near-white text gives an unpredictable
   grey for the tiny 10px timestamp. Pin it to a fixed faint ink for legibility. */
.msg-from-staff .msg-when { opacity: 1; color: var(--text-faint); }
.msg-body { white-space: pre-wrap; word-break: break-word; }
/* ---- reply composer (pinned to the sheet bottom) ---- */
.thread-reply {
  flex: 0 0 auto;
  display: flex; align-items: flex-end; gap: var(--s-3);
  padding: var(--s-4) var(--s-5) calc(var(--s-4) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--pm-hairline);
  background: var(--canvas-bg);
}
.thread-input {
  flex: 1 1 auto;
  min-height: 44px; max-height: 120px; resize: none;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--radius-control);
}
.thread-send {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--pm-cta-bg); color: var(--pm-cta-ink);
  cursor: pointer;
  transition: opacity 160ms ease;
}
/* Disabled: a neutral surface (not dimmed gold, which reads muddy). */
.thread-send:disabled {
  background: var(--pm-surface-3);
  color: var(--text-faint);
  pointer-events: none;
}
.thread-send svg { width: 20px; height: 20px; }
[dir="rtl"] .thread-send svg { transform: scaleX(-1); }
.thread-note {
  margin: 0; padding: 0 var(--s-5) var(--s-2);
  font-size: 12px; min-height: 14px;
  background: var(--canvas-bg);
}
.thread-note.is-error { color: var(--accent); }
.thread-note.is-ok { color: #6bb585; }

/* ---- request-detail body (replaces the retired message stream) ----
   The thread overlay now shows a read-only detail card, not a conversation. */
.req-detail-group { margin: 0; border: 0; border-radius: 0; }
.req-detail-list { margin: 0; }
/* Closing divider on the last detail row (overrides the shared last-of-type
   border removal) so the detail sheet ends with the same hairline as its rows. */
.inset-group .req-detail-list dd:last-of-type { border-bottom: 1px solid var(--pm-hairline-soft); }

/* ============================================================
   REQUESTS SHEET - the member's requests list, presented as a bottom sheet
   opened from the single "Requests" row on the More tab. Mirrors the thread /
   booking sheet; sits BELOW the request-detail overlay (z 9200) so a tapped
   row stacks the detail on top of the list.
   ============================================================ */
.requests-modal { position: fixed; inset: 0; z-index: 9150; display: none; }
.requests-modal.is-open { display: block; }
.requests-scrim {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.66);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: pm-fade-in 220ms ease both;
}
.requests-sheet {
  position: absolute; inset-inline: 0; bottom: 0; top: auto;
  max-height: 88vh;
  display: flex; flex-direction: column;
  background: var(--canvas-bg);
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -18px 60px rgba(0,0,0,0.5);
  animation: sheet-up 360ms cubic-bezier(.2,.7,.2,1) both;
}
.requests-head {
  position: relative;
  padding: var(--s-7) var(--s-6) var(--s-5);
  padding-inline-end: calc(var(--s-6) + 44px);
  border-bottom: 1px solid var(--pm-hairline);
  flex: 0 0 auto;
}
.requests-title {
  margin: 0; font-size: 22px; line-height: 1.2; color: var(--text); letter-spacing: 0.01em;
}
.requests-close {
  position: absolute; top: var(--s-4); inset-inline-end: var(--s-4);
  width: var(--s-9); height: var(--s-9);
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--pm-surface-2);
  color: var(--text); cursor: pointer;
}
.requests-close svg { width: 18px; height: 18px; }
.requests-body {
  flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch;
  /* Full-bleed: rows run edge to edge (their own s-5 inset keeps content off the
     screen edge). No side/top padding on the scroller. */
  padding: 0 0 calc(var(--s-6) + env(safe-area-inset-bottom, 0px));
}
.requests-body .req-group { margin: 0; border: 0; border-radius: 0; }

/* ============================================================
   FULL-BLEED EDGE-TO-EDGE LAYOUT (global; placed last so it wins the cascade).
   The page canvas runs to the screen edges - every card / list / hero bleeds
   edge to edge with square corners; text keeps a readable inset via its own
   side padding. This replaces the old .pm-main side gutter site-wide.
   ============================================================ */
.pm-main, .acct-main { padding-inline: 0; max-width: none; }

/* Text-only blocks keep the old gutter as INTERNAL side padding so copy never
   touches the screen edge. */
.acct-largetitle-wrap,
.acct-status,
.section-head,
.segmented,
.excl-lede,
.points-tier-note,
.tier-progress,
.tw-panel,
.earn-card,
.aspire-head {
  padding-inline: var(--s-5);
}

/* Cards / grouped containers bleed to the edges with square corners; their own
   internal padding keeps the content inset. */
.idx-card,
.feat-card,
.order-card,
.visit-card,
.inset-group,
.svc-req-card {
  border-radius: 0;
}

/* Grids/rails/heroes that were pulled out of the old gutter with a negative side
   margin are already full-width now - neutralize the pull (this was the source
   of the page horizontal scroll once the gutter was removed). */
.excl-grid,
.cat-bar,
.tw-rail,
.featured-block,
.segmented { margin-inline: 0; }

/* Stacked card lists touch vertically (NO gap between containers); a single 1px
   hairline divides rows, with a top line capping the stack - a clean continuous
   grouped surface instead of floating cards with gaps. */
.index-cards,
.orders-list,
.visits-list { gap: 0; border-top: 1px solid var(--pm-hairline); }
.idx-card,
.order-card,
.visit-card {
  border: 0;
  border-bottom: 1px solid var(--pm-hairline);
  margin-bottom: 0;
}

/* Orders + Visits lists: a small vertical gap between items so each order / visit
   reads as its own separated, surfaced tile (not the touching hairline-divided
   stack the index cards use). Re-grants the all-round border + rounded corners
   that the flattening override above stripped. */
.orders-list,
.visits-list {
  gap: var(--s-3);
  border-top: 0;
}
.order-card,
.visit-card {
  border: 1px solid var(--pm-hairline);
  border-radius: 0;
  box-shadow: none;
}

/* ============================================================
   TAB BAR FIT - "My Creations" must never scroll out of view.
   Six top-level tabs (Membership / Exclusive / My Creations / Visits /
   Orders / More) overflow at the default 11px / 0.14em tracking until the
   viewport is ~500px+, so on any narrower width the strip scrolls and tapping
   a right-side tab (Orders / More) pushes "My Creations" (3rd) off the left
   edge - which reads as the tab "disappearing". We size the font / tracking /
   gap / gutter FLUIDLY with the viewport (clamp, NO breakpoint) so all six
   ALWAYS fit and the strip never needs to scroll - at every width, with no
   dead zone between breakpoints. The wide desktop tracking is preserved at the
   clamp upper bound. (RTL keeps its own tighter tracking from .segment[rtl].)
   ============================================================ */
.segmented {
  gap: clamp(8px, 2.3vw, var(--s-5));
  padding-inline: clamp(10px, 3vw, var(--s-5));
}
.segment {
  font-size: clamp(9.5px, 2.6vw, 11px);
  letter-spacing: clamp(0.03em, 0.2vw, 0.14em);
}

/* Tighten the sticky tab bar's bottom gutter, and pull the featured hero up so
   it sits flush under the nav (no gap above the carousel). */
.segmented { margin-bottom: var(--s-3); }
.featured-block { margin-top: calc(-1 * var(--s-3)); }

/* Full-width section-foot CTA (BOOK A VISIT): bleeds edge to edge with square
   corners, separated from the visits list above by a clear gap. */
.visit-book-cta { border-radius: 0; margin-top: var(--s-6); }

/* The membership CARD is a physical-card object: keep its rounded corners (the
   global square-corner rule does NOT apply to it) and add a slow, smooth,
   looping shimmer sweep across its face. */
.membership-card { border-radius: clamp(14px, 4vw, 22px); }
/* A diagonal gloss BAND that sweeps across the card via translateX (GPU-
   composited = smooth, unlike the old background-position version that stuttered)
   then rests off-screen and loops seamlessly (no visible jump). */
.membership-card::before {
  content: ""; position: absolute; top: -25%; bottom: -25%;
  left: 0; width: 45%; z-index: 2;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.34), transparent);
  transform: translateX(-160%) rotate(8deg);
  animation: mc-shimmer 7s ease-in-out infinite;
  will-change: transform;
}
@keyframes mc-shimmer {
  0%, 8%    { transform: translateX(-160%) rotate(8deg); }
  42%, 100% { transform: translateX(320%) rotate(8deg); }
}
@media (prefers-reduced-motion: reduce) {
  .membership-card::before { animation: none; }
}

/* Exclusive "Reserved for you" hero: edge to edge, no corner radius / border. */
.excl-feature { border-radius: 0; border: 0; }

/* Featured carousel slides are full-bleed (edge to edge): drop the rail's side
   padding + gap so each slide fills the viewport exactly. */
.featured-rail { gap: 0; padding-inline: 0; }

/* Featured pagination follows the FOCUSED slide's text theme (like the caption):
   light (near-white) over dark imagery by default, ink when the slide is
   .theme-dark. JS toggles .on-dark on the dots row to match the active slide. */
.featured-dots .feat-dot { background: rgba(246,243,236,0.45); }
.featured-dots .feat-dot-fill { background: #f6f3ec; }
.featured-dots.on-dark .feat-dot { background: rgba(0,0,0,0.28); }
.featured-dots.on-dark .feat-dot-fill { background: var(--text); }

/* ============================================================
   ARABIC LETTER-SPACING RESET
   Arabic script is cursive - letter-spacing shatters the joined glyphs. Zero all
   tracking in Arabic mode (lang=ar / dir=rtl). This overrides the earlier
   [dir="rtl"] .X { letter-spacing: 0.0Nem } softening rules (eyebrows, caps,
   segments) so Arabic renders with NO tracking anywhere. Latin/English untouched.
   ============================================================ */
:lang(ar), :lang(ar) *,
[dir="rtl"], [dir="rtl"] * {
  letter-spacing: normal !important;
}

/* ============================================================
   KIT SUPERSET ADDITIONS (propagated from fb-ui.css)
   This portal loads the canonical fb-ui.css first, then this bespoke
   override layer. These net-new primitives are mirrored here so the fork
   stays a SUPERSET of the kit even if the remote fb-ui.css lags a version.
   None of the portal's existing overrides (e.g. the .mc-shimmer card gloss,
   .auth-btn.is-busy) are touched - these are additive, net-new selectors.
   Tokens (--s-*, --radius-*, --premium-yellow) resolve from the loaded kit.
   ============================================================ */

/* --- SECTION NAV (.fb-nav) - segmented page-section nav --- */
.fb-nav {
  display: flex; gap: 4px;
  width: 100%;
  min-width: 0;
  height: var(--s-9);
  padding: 2px;
  background: rgba(0,0,0,0.05);
  border-radius: var(--radius-pill);
  overflow-x: auto;
  scrollbar-width: none;
}
.fb-nav::-webkit-scrollbar { display: none; }
.fb-nav label {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  white-space: nowrap;
  background: transparent;
  border-radius: var(--radius-pill);
  cursor: pointer;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  border: 0;
  transition: background 0.12s, color 0.12s;
}
.fb-nav label:hover { background: var(--accent); color: var(--on-danger, #fee5a5); }
.fb-nav input {
  display: block;
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  opacity: 0;
}
.fb-nav input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }
.fb-nav input:checked + label {
  background: #fff;
  color: var(--text);
  font-weight: 500;
  box-shadow: 0 1px 3px rgba(0,0,0,0.10), 0 0 0 0.5px rgba(0,0,0,0.04);
}

/* --- LOADING STATE - button in flight --- */
.btn.is-loading,
.btn[aria-busy="true"],
button[aria-busy="true"] {
  position: relative;
  pointer-events: none;
  opacity: 0.72;
  -webkit-text-fill-color: transparent;
}
.btn.is-loading > svg,
.btn[aria-busy="true"] > svg,
button[aria-busy="true"] > svg { visibility: hidden; }
.btn.is-loading::after,
.btn[aria-busy="true"]::after,
button[aria-busy="true"]::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M21 12a9 9 0 1 1-3.5-7.13'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M21 12a9 9 0 1 1-3.5-7.13'/%3E%3C/svg%3E") center / contain no-repeat;
  animation: fb-spin 1s linear infinite;
}
@keyframes fb-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn.is-loading::after,
  .btn[aria-busy="true"]::after,
  button[aria-busy="true"]::after { animation: none; }
}

/* --- BUSY OVERLAY (.fb-busy) - full-cover blocking scrim, hidden by [hidden] --- */
.fb-busy {
  position: fixed; inset: 0; z-index: 9600;
  display: none;
  flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-4);
  color: var(--text-muted);
  background: rgba(244, 238, 223, 0.72);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}
.fb-busy:not([hidden]) { display: flex; }
.fb-busy .fb-busy-ring {
  width: 40px; height: 40px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M21 12a9 9 0 1 1-3.5-7.13'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M21 12a9 9 0 1 1-3.5-7.13'/%3E%3C/svg%3E") center / contain no-repeat;
  animation: fb-spin 1s linear infinite;
}
.fb-busy .fb-busy-msg {
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}
@media (prefers-reduced-motion: reduce) {
  .fb-busy .fb-busy-ring { animation: none; }
}

/* --- SKELETON (.skel / .skel-*) - loading placeholders --- */
.skel-shimmer,
.skel,
.skel-text, .skel-line,
.skel-tile,
.skel-avatar,
.skel-pill,
.skel-btn {
  background: linear-gradient(100deg, rgba(0,0,0,0.045) 30%, rgba(0,0,0,0.085) 50%, rgba(0,0,0,0.045) 70%);
  background-size: 200% 100%;
  animation: shim 1.25s ease-in-out infinite;
  color: transparent;
}
.skel-shimmer { display: inline-block; border-radius: 4px; }
.skel        { display: block; border-radius: var(--radius-sm); }
.skel-text,
.skel-line   { display: block; height: 12px; border-radius: 6px; }
.skel-tile   { display: block; width: 100%; min-height: 120px; border-radius: var(--radius-card); }
.skel-avatar { display: block; width: 42px; height: 42px; border-radius: 50%; }
.skel-pill   { display: inline-block; height: 18px; border-radius: var(--radius-pill); }
.skel-btn    { display: inline-block; height: var(--s-9); border-radius: var(--radius-pill); }
.skel-row { display: grid; gap: var(--s-3); padding: var(--s-3) var(--s-4); }
@keyframes shim {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skel-shimmer, .skel, .skel-text, .skel-line,
  .skel-tile, .skel-avatar, .skel-pill, .skel-btn { animation: none; }
}

/* --- MARKDOWN EDITOR (.fb-md) - Write / Preview component --- */
.fb-md { display: block; }
.fb-md .fb-md-toolbar {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 10px;
}
.fb-md .fb-md-btn {
  min-width: 40px;
  height: var(--s-9);
  padding: 0 var(--s-3);
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--control-border);
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,0.55);
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, border-color 0.12s;
}
.fb-md .fb-md-btn:hover { background: rgba(0,0,0,0.05); }
.fb-md .fb-md-btn:active { transform: translateY(1px); }
.fb-md .fb-md-body {
  width: 100%;
  min-height: 320px;
  height: auto;
  padding: var(--s-3) var(--s-4);
  resize: vertical;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13.5px;
  line-height: 1.65;
}
[dir="rtl"] .fb-md .fb-md-body { direction: rtl; text-align: right; }
.fb-md .fb-md-preview {
  display: none;
  min-height: 320px;
  padding: var(--s-6);
  border-radius: var(--radius-card);
  background: rgba(255,255,255,0.55);
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.08);
}
.fb-md .fb-md-preview h1 { font-size: 26px; font-weight: 450; line-height: 1.2; margin: 0 0 6px; }
.fb-md .fb-md-preview h2 { font-size: 18px; font-weight: 550; margin: 22px 0 8px; }
.fb-md .fb-md-preview h3 { font-size: 15px; font-weight: 600; margin: 18px 0 6px; }
.fb-md .fb-md-preview p  { margin: 0 0 12px; line-height: 1.65; }
.fb-md .fb-md-preview ul { margin: 0 0 14px; padding-inline-start: 22px; }
.fb-md .fb-md-preview li { margin: 0 0 7px; }
.fb-md .fb-md-preview a  { color: var(--accent); }
[dir="rtl"] .fb-md .fb-md-preview { direction: rtl; text-align: right; }
.fb-md.is-preview .fb-md-body,
.fb-md.is-preview .fb-md-toolbar { display: none; }
.fb-md.is-preview .fb-md-preview { display: block; }
