/* ═══════════════════════════════════════════════════════════════════
   KWARTO'S GUEST HOUSE — Styles
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* === BRAND TOKENS (locked per §1 — do not modify) === */
  --olive: #4a5d23;
  --gold: #c8a951;
  --cream: #faf9f6;
  /* Golden Hour (Wave 1A) — live page-background var, written each frame by the
     kwGoldenHour engine in script.js. Defaults to cream so the page is visually
     identical until JS warms it on scroll. The Palette B journey + warm-travel
     strength live in JS (GH_STOPS / STRENGTH) because the colour math is JS-only;
     a CSS token nothing computes would be dead config. Not a brand token. */
  --page-light: var(--cream);
  --text-d: #1f2a1a; /* darkest text — brief §1 */
  --text-s: #3a463a; /* body text */
  --text-m: #5d6358; /* muted text, metadata — 5.38:1 on footer #eef3e5 and 6.0:1 on cream, both AA passing. Previous #6a7164 was 4.46:1 on the footer bg (just under 4.5), and 0.75 opacity on /privacy and /terms links (removed in the same change) composited it to ~#8b9284 at 2.84:1 (AA fail). */
  --brd: #e3e6de; /* default border */
  --brd-l: #f0f1ec; /* light divider */
  --olive-3: #eef3e5; /* pale olive — card backgrounds (brief §1) */
  --olive-10: rgba(74, 93, 35, 0.1);
  --olive-20: rgba(74, 93, 35, 0.2);

  /* === COMPATIBILITY ALIASES (legacy WIP keeps working) === */
  --text: var(--text-d);
  --olive-60: #6b8a3e;
  --olive-5: #f5f8f0;
  --warm: #f5f0e8;
  --gold-light: #fdf8ec;
  --wh: #fff;

  /* === LEGACY SHADOW ALIASES (preserved for WIP compatibility) === */
  --sh-s: 0 1px 3px rgba(27, 33, 18, 0.06);
  --sh: 0 4px 20px rgba(27, 33, 18, 0.07);
  --sh-m: 0 8px 32px rgba(27, 33, 18, 0.1);
  --sh-l: 0 20px 60px rgba(27, 33, 18, 0.12);

  /* === RADII (§1) === */
  --r: 16px;
  --rs: 10px;
  --rl: 24px;
  --rxl: 32px;

  /* === TYPOGRAPHY (§1) === */
  --serif: "Playfair Display", Georgia, serif;
  --sans: "Outfit", -apple-system, sans-serif;
  --script: var(--serif); /* Pacifico removed (casual-script "$200 tell"); legacy alias now resolves to the serif. Apply font-style:italic at the usage. */

  /* === LEGACY EASING ALIASES (preserved for WIP compatibility) === */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* === MOTION SYSTEM v2 (§2 — do not modify) === */
  --ease-out-expo: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out-quart: cubic-bezier(0.76, 0, 0.24, 1);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-in-quart: cubic-bezier(0.5, 0, 0.75, 0);
  --t-fast: 120ms;
  --t-med: 280ms;
  --t-slow: 520ms;
  --t-epic: 900ms;

  /* === SHADOW LANGUAGE (§1) === */
  --sh-rest: 0 1px 2px rgba(0, 0, 0, 0.03);
  --sh-card:
    0 12px 32px -8px rgba(74, 93, 35, 0.18), 0 2px 6px rgba(74, 93, 35, 0.06);
  --sh-modal: 0 24px 60px -12px rgba(31, 42, 26, 0.28);
}

/* === REDUCED MOTION SAFETY NET (§2, §14) ===
   Every section adds its own reduced-motion overrides on top.
   This is the global catch-all. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Golden Hour (Wave 1A): freeze the hero sun at its golden resting position.
     Mirrors kwGoldenHour's SUN_DX/DY/SCALE at e=1 (script.js) — keep both in
     sync if the dials are tuned. JS setStatic() also sets this inline; this
     rule is the no-JS / pre-hydration fallback so a reduced-motion visitor
     still sees the rested golden sun. */
  .art-sun-shift { transform: translate(-40px, 360px) scale(1.08); }
  /* Wave 1 (golden-hour deepening): rest every scroll-driven hero layer at
     the same e=1 golden rest. Mirrors writeSun's SKY_WARM_MAX / BLOOM_MIN-MAX /
     BLOOM_BREATHE / DUNE_*_DY dials (script.js kwGoldenHour) — keep in sync.
     JS setStatic() writes the same values inline; these rules are the no-JS /
     pre-hydration fallback (CSS class rules beat the q=0 presentation attrs). */
  .art-sky-warm { opacity: 0.55; }
  .art-sun-bloom { opacity: 0.75; transform: scale(1.18); }
  .art-dune-back { transform: translate3d(0px, -8px, 0px); }
  .art-dune { transform: translate3d(0px, -18px, 0px); }
  .art-ocean-shift { transform: translate3d(0px, -4px, 0px); } /* Phase B: rest sea at writeSun(1) */
}

/* === REVEAL UTILITY (§2 scroll-linked reveal pattern) ===
   IntersectionObserver toggles .is-in on .reveal elements.
   Variants for direction + 8 stagger steps. */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--t-slow) var(--ease-out-expo),
    transform var(--t-slow) var(--ease-out-expo);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}
.reveal-left {
  transform: translateX(-24px);
}
.reveal-left.is-in {
  transform: none;
}
.reveal-right {
  transform: translateX(24px);
}
.reveal-right.is-in {
  transform: none;
}
.reveal-scale {
  transform: scale(0.96);
}
.reveal-scale.is-in {
  transform: none;
}

/* Stagger helpers (§2: 40–70ms increments) */
.reveal[data-stagger="1"] {
  transition-delay: 40ms;
}
.reveal[data-stagger="2"] {
  transition-delay: 80ms;
}
.reveal[data-stagger="3"] {
  transition-delay: 120ms;
}
.reveal[data-stagger="4"] {
  transition-delay: 160ms;
}
.reveal[data-stagger="5"] {
  transition-delay: 200ms;
}
.reveal[data-stagger="6"] {
  transition-delay: 240ms;
}
.reveal[data-stagger="7"] {
  transition-delay: 280ms;
}
.reveal[data-stagger="8"] {
  transition-delay: 320ms;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    transform: none;
    transition: opacity 150ms ease;
  }
  .reveal[data-stagger] {
    transition-delay: 0ms;
  }
}
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  /* Kills the 300ms tap delay AND the double-tap-zoom gesture
     across the whole app. Pinch-to-zoom is preserved (manipulation
     allows pan + continuous zoom, blocks only discrete double-tap).
     Required for chat long-press / swipe-reply to feel native. */
  touch-action: manipulation;
}
body {
  font-family: var(--sans);
  /* Golden Hour (Wave 1A): page background reads the live --page-light var
     (falls back to cream). kwGoldenHour in script.js warms it on scroll. */
  background: var(--page-light, var(--cream));
  color: var(--text);
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-tap-highlight-color: transparent;
  /* Prevents iOS Safari bounce-overscroll snapping back into the
     chat composer while keyboard is open. */
  overscroll-behavior-y: contain;
}
/* iOS Safari auto-zooms any input whose computed font-size < 16px on
   focus. Force >= 16px on mobile to suppress the zoom-then-snap-back
   jitter without affecting desktop visual hierarchy. */
@media screen and (max-width: 768px) {
  input,
  select,
  textarea {
    font-size: 16px;
  }
}
img {
  display: block;
  max-width: 100%;
}
button {
  cursor: pointer;
  font-family: var(--sans);
  -webkit-tap-highlight-color: transparent;
}
input,
select,
textarea {
  font-family: var(--sans);
  -webkit-tap-highlight-color: transparent;
  -webkit-appearance: none;
}
::selection {
  background: var(--olive-10);
  color: var(--olive);
}
/* ─── Phase N — Manual QR Ph payment view ──────────────────────
   Static QR poster + numbered steps for guests who pay through
   their bank or e-wallet directly (admin verifies in chat).
   The poster file lives at /images/qrph-kwartos.jpg — drop the
   QR Ph PDF/PNG export from PayMongo's In-store QR dashboard
   there as a JPG. ──────────────────────────────────────────── */
.co-mic-qrph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: linear-gradient(135deg, #0070e0, #003a8a);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
}
.qrph-poster {
  margin: 18px 0 14px;
  padding: 16px;
  background: #fff;
  border: 1px solid #e7e3da;
  border-radius: 14px;
  box-shadow: 0 6px 18px rgba(27, 33, 18, 0.06);
  text-align: center;
}
.qrph-poster img {
  max-width: 320px;
  width: 100%;
  height: auto;
  display: block;
  margin: 0 auto;
}
.qrph-poster-fallback {
  display: none;
  padding: 24px 16px 12px;
  color: var(--text);
  text-align: center;
}
.qrph-poster.qrph-poster-missing .qrph-poster-fallback {
  display: block;
}
.qrph-poster-fallback-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: linear-gradient(135deg, #0070e0, #003a8a);
  color: #fff;
  font-size: 28px;
  font-weight: 700;
  margin: 0 auto 12px;
}
.qrph-poster-fallback-title {
  font-weight: 700;
  font-size: 15px;
  margin-bottom: 6px;
}
.qrph-poster-fallback-txt {
  font-size: 13px;
  color: var(--text-m);
  line-height: 1.55;
  max-width: 320px;
  margin: 0 auto;
}
.qrph-poster-caption {
  margin-top: 12px;
  font-size: 11.5px;
  color: var(--text-m);
  letter-spacing: 0.3px;
}

/* ─── Phase R/2 — QR poster sized down for the waiting view ──── */
.qrph-poster.co-waiting-qr {
  margin: 6px auto 18px;
  max-width: 280px;
  padding: 12px;
}
.qrph-poster.co-waiting-qr img {
  max-width: 240px;
}
.qrph-poster.co-waiting-qr .qrph-poster-caption {
  font-weight: 600;
  color: var(--text);
  margin-top: 8px;
  letter-spacing: 0;
}

/* ─── Phase R — Booking pending-payment waiting view ──────────── */
.co-waiting {
  text-align: center;
  padding: 28px 22px 32px;
}
.co-waiting-ic {
  position: relative;
  width: 80px;
  height: 80px;
  margin: 0 auto 16px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.co-waiting-spinner {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  animation: kwWaitingSpin 1.2s linear infinite;
}
@keyframes kwWaitingSpin {
  to {
    transform: rotate(360deg);
  }
}
.co-waiting-qr-mark {
  font-size: 32px;
  font-weight: 700;
  color: var(--olive);
  background: rgba(74, 93, 35, 0.06);
  width: 50px;
  height: 50px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.co-waiting-title {
  font-family: var(--serif);
  font-size: 24px;
  margin: 0 0 8px;
  color: var(--text);
  letter-spacing: -0.4px;
}
.co-waiting-sub {
  font-size: 14px;
  color: var(--text-m);
  line-height: 1.6;
  max-width: 460px;
  margin: 0 auto 22px;
}
.co-waiting-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
  align-items: stretch;
}
.co-cancel-link {
  background: transparent;
  border: none;
  color: var(--text-m);
  font-size: 13px;
  text-decoration: underline;
  text-decoration-color: rgba(15, 20, 12, 0.2);
  padding: 8px;
  cursor: pointer;
  font-family: var(--sans);
}
.co-cancel-link:hover {
  color: #c22020;
  text-decoration-color: #c22020;
}
@media (prefers-reduced-motion: reduce) {
  .co-waiting-spinner {
    animation: none;
  }
}
@media (max-width: 600px) {
  .co-waiting {
    padding: 22px 18px 28px;
  }
  .co-waiting-title {
    font-size: 21px;
  }
  .co-waiting-sub {
    font-size: 13px;
  }
}
.qrph-steps {
  list-style: none;
  padding: 0;
  margin: 18px 0 0;
  counter-reset: qrph;
}
.qrph-steps li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
  border-bottom: 1px solid #f3f1ea;
}
.qrph-steps li:last-child {
  border-bottom: none;
}
.qrph-step-num {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--olive);
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
@media (max-width: 600px) {
  .qrph-poster {
    padding: 12px;
  }
  .qrph-poster img {
    max-width: 100%;
  }
  .qrph-steps li {
    padding: 9px 0;
    font-size: 13px;
  }
}

/* ════════════════════════════════════════════════════════════════════
   PHASE W — 50% / Pay-in-full segmented toggle (v2 .md)
   ────────────────────────────────────────────────────────────────────
   Sits ABOVE the "Show my QR code" button. Two equal radio cards.
   Selected state uses the olive ring + olive-3 tint matching the
   existing checkout brand language. Stacks on small phones.
   ════════════════════════════════════════════════════════════════════ */
.kw-payplan {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 0 0 18px;
}
.kw-payplan-opt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 14px 16px;
  border-radius: var(--r, 12px);
  border: 1.5px solid var(--brd, #e6e3da);
  background: #fff;
  cursor: pointer;
  text-align: left;
  transition:
    border-color var(--t-med, 260ms) var(--ease-out-expo, ease-out),
    box-shadow var(--t-med, 260ms) var(--ease-out-expo, ease-out),
    background var(--t-med, 260ms) var(--ease-out-expo, ease-out);
  font-family: inherit;
}
.kw-payplan-opt:hover {
  border-color: rgba(74, 93, 35, 0.4);
}
.kw-payplan-opt.is-selected {
  border-color: var(--olive);
  background: var(--olive-3, rgba(74, 93, 35, 0.06));
  box-shadow: 0 0 0 4px rgba(74, 93, 35, 0.08);
}
.kw-payplan-label {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13px;
  color: var(--text-d, var(--text));
  letter-spacing: 0.1px;
}
.kw-payplan-amt {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 20px;
  color: var(--olive);
  letter-spacing: -0.3px;
  margin-top: 2px;
}
.kw-payplan-sub {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--text-m);
  margin-top: 2px;
}
.kw-payplan-opt:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .kw-payplan-opt {
    transition: none !important;
  }
}
@media (max-width: 480px) {
  .kw-payplan {
    grid-template-columns: 1fr;
  }
}

/* Balance-pay single-line message (when paymentStatus === "deposit_paid"). */
.kw-payplan-balance {
  margin: 0 0 18px;
  padding: 14px 16px;
  border-radius: var(--r, 12px);
  background: var(--olive-3, rgba(74, 93, 35, 0.06));
  border: 1px solid rgba(74, 93, 35, 0.18);
}
.kw-payplan-balance-msg {
  margin: 0;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text);
  line-height: 1.5;
}

/* ════════════════════════════════════════════════════════════════════
   PHASE U — Humanized QR Ph screen (renderQrphDynamic)
   ────────────────────────────────────────────────────────────────────
   Per CLAUDE_CODE_QRPH_ACTIVATION_PROMPT.md: single full-total QR,
   warm copy in Light's voice, brand tokens only. No new CDN libraries,
   no transform/translate animation on the QR card (respects
   prefers-reduced-motion).
   ════════════════════════════════════════════════════════════════════ */
.qrph-screen {
  /* Subtle vertical rhythm — header, QR area, trust block. */
}
.qrph-screen-header {
  margin-bottom: 14px;
  text-align: center;
}
.qrph-body-1 {
  font-family: var(--serif);
  font-size: 22px;
  color: var(--text);
  margin: 0 0 6px;
  letter-spacing: -0.4px;
  line-height: 1.25;
}
.qrph-body-2 {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-m);
  margin: 0 auto;
  max-width: 380px;
  line-height: 1.55;
}
.qrph-body-2 strong {
  color: var(--olive);
  font-weight: 600;
}

/* QR host container — wraps either the "Show my QR" button or the
   actual QR image. Imperative DOM swaps from renderQrphCode replace
   the inner content without re-rendering the entire screen. */
.qrph-code-host {
  margin: 18px 0 14px;
  display: flex;
  justify-content: center;
}
.qrph-generate-btn {
  /* .ncta is the existing primary-CTA class. We only need to tweak
     spacing for this specific placement. */
  width: 100%;
  max-width: 360px;
  font-size: 15px;
  padding: 14px 22px;
}

.qrph-code-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 20px;
}
.qrph-code-img {
  width: 240px;
  height: 240px;
  border-radius: var(--rs, 12px);
  background: #fff;
  padding: 12px;
  box-shadow:
    0 12px 32px -8px rgba(74, 93, 35, 0.18),
    0 2px 6px rgba(74, 93, 35, 0.06);
}
.qrph-code-img.qrph-code-img-failed {
  /* When the hosted QR PNG fails to load, hide it; the EMV-string
     fallback note (renderQrphCode adds it next to the img) carries
     the user. */
  display: none;
}
.qrph-fallback {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text-m);
  text-align: center;
  max-width: 280px;
  margin: 0;
  line-height: 1.55;
}
.qrph-hint {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text-s, var(--text-m));
  text-align: center;
  max-width: 280px;
  margin: 0;
  line-height: 1.5;
}
.qrph-timer {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--text-m);
  margin: 0;
  letter-spacing: 0.2px;
  font-variant-numeric: tabular-nums;
}
.qrph-timer.qrph-timer-warn {
  color: #c25a20;
  font-weight: 600;
}

/* Expired state — clean amber accent + regenerate button. */
.qrph-expired {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
  border: 1px dashed rgba(194, 90, 32, 0.35);
  background: linear-gradient(180deg, #fff8f1 0%, #fdf2e5 100%);
  border-radius: 14px;
}
.qrph-expired p {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-s, var(--text-m));
  margin: 0;
  max-width: 300px;
  line-height: 1.55;
}

/* Lock note — single sentence with key. Kept slightly tighter than
   the body copy so it reads as a footnote rather than a heading. */
.qrph-lock-note {
  font-family: var(--sans);
  font-size: 12.5px;
  color: var(--text-m);
  margin: 16px auto 14px;
  max-width: 380px;
  text-align: center;
  letter-spacing: 0.1px;
}

/* Trust rows — a 3-row label/value grid sitting under the lock note. */
.qrph-trust {
  display: grid;
  gap: 8px;
  border-top: 1px solid #ece9df;
  padding-top: 14px;
}
.qrph-trust-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-family: var(--sans);
  font-size: 13px;
}
.qrph-trust-lbl {
  color: var(--text-m);
  letter-spacing: 0.2px;
}
.qrph-trust-val {
  color: var(--text);
  font-weight: 600;
  text-align: right;
}

@media (max-width: 600px) {
  .qrph-body-1 {
    font-size: 19px;
  }
  .qrph-body-2 {
    font-size: 13.5px;
  }
  .qrph-code-img {
    width: 220px;
    height: 220px;
    padding: 10px;
  }
  .qrph-trust-row {
    font-size: 12.5px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .qrph-code-img {
    transition: none !important;
  }
}

/* ════════════════════════════════════════════════════════════════════
   PHASE T — Gateway-dormant banner (shown in checkout step 2 when
   settings/payments.paymongoEnabled === false). Visually de-emphasizes
   the online QR option and tells the user we'll verify via chat.
   ════════════════════════════════════════════════════════════════════ */
.co-gw-dormant {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  background: linear-gradient(180deg, #fff8e7 0%, #fdf2c9 100%);
  border: 1px solid #f1d68a;
  border-left: 4px solid #d4a04f;
  border-radius: 12px;
  padding: 14px 16px;
  margin: 4px 0 18px;
  box-shadow: 0 1px 3px rgba(180, 130, 40, 0.08);
}
.co-gw-dormant-ic {
  font-size: 22px;
  line-height: 1;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(212, 160, 79, 0.18);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.co-gw-dormant-body {
  flex: 1;
  min-width: 0;
}
.co-gw-dormant-title {
  font-weight: 700;
  font-size: 14px;
  color: #6b4a13;
  margin-bottom: 4px;
  letter-spacing: -0.1px;
}
.co-gw-dormant-sub {
  font-size: 12.5px;
  color: #7a5a25;
  line-height: 1.55;
}
@media (max-width: 600px) {
  .co-gw-dormant {
    padding: 12px 14px;
    gap: 10px;
  }
  .co-gw-dormant-title {
    font-size: 13.5px;
  }
  .co-gw-dormant-sub {
    font-size: 12px;
  }
}

/* ════════════════════════════════════════════════════════════════════
   PHASE S — Dynamic QR Ph payment view
   ────────────────────────────────────────────────────────────────────
   Styles for renderQrphDynamic() — the unified "Scan to Pay" experience
   with a 50%/100% toggle, on-demand QR generation, live countdown ring,
   and graceful expiry/regenerate state.
   ════════════════════════════════════════════════════════════════════ */

/* ─── 50% / 100% toggle ─────────────────────────────────────────── */
.co-qr-toggle {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 16px 0 18px;
}
.co-qr-toggle-opt {
  appearance: none;
  background: #fafaf6;
  border: 2px solid #e6e3da;
  border-radius: 14px;
  padding: 14px 12px 12px;
  cursor: pointer;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: center;
  transition: all 160ms ease;
  font-family: var(--sans);
  position: relative;
}
.co-qr-toggle-opt:hover {
  border-color: rgba(74, 93, 35, 0.35);
  transform: translateY(-1px);
}
.co-qr-toggle-opt.selected {
  border-color: var(--olive);
  background: rgba(74, 93, 35, 0.06);
  box-shadow: 0 2px 8px rgba(74, 93, 35, 0.12);
}
.co-qr-toggle-opt.selected::after {
  content: "✓";
  position: absolute;
  top: 8px;
  right: 10px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--olive);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.co-qr-toggle-pct {
  font-family: var(--serif);
  font-size: 24px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.5px;
  line-height: 1;
}
.co-qr-toggle-opt.selected .co-qr-toggle-pct {
  color: var(--olive);
}
.co-qr-toggle-lbl {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-m);
  letter-spacing: 0.4px;
  text-transform: uppercase;
  margin-top: 2px;
}
.co-qr-toggle-amt {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin-top: 6px;
}
.co-qr-toggle-hint {
  font-size: 11.5px;
  color: var(--text-m);
  margin-top: 2px;
}

/* ─── Pre-generate "tap to create" card ─────────────────────────── */
.co-qr-gen-card {
  border: 2px dashed rgba(74, 93, 35, 0.35);
  border-radius: 16px;
  background: linear-gradient(180deg, #fbfaf3 0%, #f6f4ea 100%);
  padding: 26px 22px 22px;
  text-align: center;
  margin-bottom: 8px;
}
.co-qr-gen-icon {
  font-size: 34px;
  color: var(--olive);
  background: rgba(74, 93, 35, 0.1);
  width: 60px;
  height: 60px;
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
  font-weight: 700;
}
.co-qr-gen-title {
  font-family: var(--serif);
  font-size: 19px;
  color: var(--text);
  margin: 0 0 6px;
  letter-spacing: -0.3px;
}
.co-qr-gen-sub {
  font-size: 13.5px;
  color: var(--text-m);
  line-height: 1.55;
  max-width: 380px;
  margin: 0 auto 18px;
}
.co-qr-gen-btn {
  appearance: none;
  border: none;
  background: var(--olive);
  color: #fff;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  padding: 14px 26px;
  border-radius: 12px;
  cursor: pointer;
  letter-spacing: 0.2px;
  box-shadow: 0 2px 10px rgba(74, 93, 35, 0.25);
  transition:
    transform 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
}
.co-qr-gen-btn:hover:not(:disabled) {
  background: #3e5021;
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(74, 93, 35, 0.3);
}
.co-qr-gen-btn:disabled {
  opacity: 0.7;
  cursor: progress;
}
.co-qr-gen-note {
  margin-top: 14px;
  font-size: 11.5px;
  color: var(--text-m);
  letter-spacing: 0.3px;
}

/* ─── Live QR display ────────────────────────────────────────────── */
.co-qr-live {
  border: 1px solid #e8e5dc;
  border-radius: 16px;
  background: #ffffff;
  padding: 18px 18px 14px;
  margin-bottom: 4px;
  box-shadow: 0 1px 3px rgba(15, 20, 12, 0.04);
}
.co-qr-live-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 14px;
}
.co-qr-live-amt-block {
  flex: 1;
  min-width: 0;
}
.co-qr-live-lbl {
  font-size: 11.5px;
  color: var(--text-m);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  font-weight: 600;
}
.co-qr-live-amt {
  font-family: var(--serif);
  font-size: 28px;
  font-weight: 700;
  color: var(--olive);
  letter-spacing: -0.6px;
  line-height: 1.1;
  margin-top: 2px;
}

/* Countdown ring + text */
.co-qr-countdown {
  position: relative;
  width: 56px;
  height: 56px;
  flex-shrink: 0;
}
.co-qr-countdown-ring {
  width: 100%;
  height: 100%;
}
.co-qr-countdown-text {
  position: absolute;
  inset: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12.5px;
  font-weight: 700;
  font-family: var(--sans);
  color: var(--olive);
  font-variant-numeric: tabular-nums;
}
.co-qr-countdown.warn .co-qr-countdown-text {
  color: #c25a20;
}
.co-qr-countdown.warn .co-qr-countdown-ring circle:last-of-type {
  stroke: #c25a20;
  animation: kwQrCountdownPulse 1s ease-in-out infinite;
}
@keyframes kwQrCountdownPulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.55;
  }
}

/* QR image wrapper */
.co-qr-img-wrap {
  position: relative;
  background: #fafaf6;
  border-radius: 12px;
  padding: 14px;
  text-align: center;
  margin: 4px 0 12px;
}
.co-qr-img {
  display: block;
  width: 100%;
  max-width: 280px;
  height: auto;
  margin: 0 auto;
  border-radius: 8px;
  background: #ffffff;
}
.co-qr-img-fail {
  display: none;
  font-size: 13px;
  color: var(--text-m);
  padding: 24px 12px;
  text-align: center;
}
.co-qr-img-fail-ic {
  font-size: 28px;
  margin-bottom: 8px;
  color: var(--olive);
}
.co-qr-img-wrap.co-qr-img-failed .co-qr-img {
  display: none;
}
.co-qr-img-wrap.co-qr-img-failed .co-qr-img-fail {
  display: block;
}

.co-qr-steps-tight {
  margin-top: 6px;
}
.co-qr-steps-tight li {
  padding: 8px 0;
  font-size: 13px;
}

.co-qr-actions {
  text-align: center;
  margin-top: 12px;
}
.co-qr-regen-link {
  background: transparent;
  border: none;
  color: var(--text-m);
  font-size: 12.5px;
  text-decoration: underline;
  text-decoration-color: rgba(15, 20, 12, 0.18);
  padding: 6px 8px;
  cursor: pointer;
  font-family: var(--sans);
}
.co-qr-regen-link:hover {
  color: var(--olive);
  text-decoration-color: var(--olive);
}

/* ─── Expired QR state ───────────────────────────────────────────── */
.co-qr-expired {
  border: 2px dashed rgba(194, 90, 32, 0.4);
  background: linear-gradient(180deg, #fff8f1 0%, #fdf2e5 100%);
  border-radius: 16px;
  padding: 26px 22px 22px;
  text-align: center;
  margin-bottom: 8px;
}
.co-qr-expired-ic {
  font-size: 38px;
  color: #c25a20;
  background: rgba(194, 90, 32, 0.12);
  width: 64px;
  height: 64px;
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
}
.co-qr-expired-title {
  font-family: var(--serif);
  font-size: 20px;
  color: var(--text);
  margin: 0 0 6px;
  letter-spacing: -0.3px;
}
.co-qr-expired-sub {
  font-size: 13.5px;
  color: var(--text-m);
  line-height: 1.55;
  max-width: 380px;
  margin: 0 auto 18px;
}

/* ─── Quiet footer (no big CTA, just secondary note) ────────────── */
.co-footer.co-footer-quiet {
  padding-top: 12px;
}
.co-footer.co-footer-quiet .co-footer-note {
  text-align: center;
  font-size: 12px;
  color: var(--text-m);
}

/* ─── Mobile tweaks ─────────────────────────────────────────────── */
@media (max-width: 600px) {
  .co-qr-toggle-opt {
    padding: 12px 10px 10px;
  }
  .co-qr-toggle-pct {
    font-size: 22px;
  }
  .co-qr-toggle-amt {
    font-size: 15px;
  }
  .co-qr-gen-card {
    padding: 22px 16px 18px;
  }
  .co-qr-gen-title {
    font-size: 17px;
  }
  .co-qr-gen-sub {
    font-size: 13px;
  }
  .co-qr-gen-btn {
    font-size: 14px;
    padding: 13px 22px;
  }
  .co-qr-live {
    padding: 14px 14px 12px;
  }
  .co-qr-live-amt {
    font-size: 24px;
  }
  .co-qr-img {
    max-width: 240px;
  }
  .co-qr-countdown {
    width: 50px;
    height: 50px;
  }
  .co-qr-countdown-text {
    font-size: 11.5px;
  }
  .co-qr-expired {
    padding: 22px 16px 18px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .co-qr-countdown.warn .co-qr-countdown-ring circle:last-of-type {
    animation: none;
  }
}

/* Firefox (the standard property) — must come BEFORE the webkit
   pseudo-selectors so Chromium can still override widths if needed. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--olive-20) transparent;
}
::-webkit-scrollbar {
  width: 6px;
}
::-webkit-scrollbar-thumb {
  background: var(--olive-20);
  border-radius: 3px;
}

@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-8px);
  }
}
@keyframes marquee {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}
@keyframes shrink {
  from {
    width: 100%;
  }
  to {
    width: 0;
  }
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.fu {
  animation: fadeUp 0.6s var(--ease) both;
}
.fi {
  animation: fadeIn 0.5s var(--ease) both;
}
.si {
  animation: scaleIn 0.4s var(--spring) both;
}
.s1 {
  animation-delay: 0.05s;
}
.s2 {
  animation-delay: 0.1s;
}
.s3 {
  animation-delay: 0.15s;
}
.s4 {
  animation-delay: 0.2s;
}
.s5 {
  animation-delay: 0.25s;
}
.s6 {
  animation-delay: 0.3s;
}
.s7 {
  animation-delay: 0.35s;
}
.s8 {
  animation-delay: 0.4s;
}

/* ── AUTH PAGES ──────────────────────────── */
.auth-page {
  min-height: 100vh;
  min-height: 100dvh; /* dynamic viewport: account for mobile browser chrome */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  position: relative;
  overflow: hidden;
}
.auth-page::before {
  content: "";
  position: absolute;
  top: -150px;
  right: -100px;
  width: 500px;
  height: 500px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--olive-5) 0%, transparent 70%);
  pointer-events: none;
}
.auth-page::after {
  content: "";
  position: absolute;
  bottom: -100px;
  left: -80px;
  width: 400px;
  height: 400px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--gold-light) 0%, transparent 70%);
  pointer-events: none;
}
.auth-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  animation: fadeUp 0.6s var(--ease) both;
}
.auth-brand {
  text-align: center;
  margin-bottom: 36px;
}
.auth-brand .auth-icon {
  width: 64px;
  height: 64px;
  border-radius: 20px;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 16px;
  font-size: 28px;
  color: #fff;
}
.auth-brand h1 {
  font-family: var(--serif);
  font-size: 28px;
  color: var(--text);
}
.auth-brand p {
  color: var(--text-m);
  font-size: 14px;
  margin-top: 6px;
}
.auth-form {
  background: var(--wh);
  padding: 36px;
  border-radius: var(--rl);
  box-shadow: var(--sh-m);
  border: 1px solid var(--brd-l);
}
.auth-form h2 {
  font-family: var(--serif);
  font-size: 24px;
  margin-bottom: 24px;
  text-align: center;
}
.auth-field {
  margin-bottom: 16px;
}
.auth-field label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-s);
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.auth-field input {
  width: 100%;
  padding: 14px 16px;
  border: 1.5px solid var(--brd);
  border-radius: var(--r);
  font-size: 14px;
  background: var(--cream);
  outline: none;
  transition: 0.2s var(--ease);
}
.auth-field input:focus {
  border-color: var(--olive);
  background: var(--wh);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.auth-field select {
  width: 100%;
  padding: 14px 16px;
  border: 1.5px solid var(--brd);
  border-radius: var(--r);
  font-size: 14px;
  background: var(--cream);
  outline: none;
  transition: 0.2s var(--ease);
  font-family: var(--sans);
  color: var(--text);
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}
.auth-field select:focus {
  border-color: var(--olive);
  background: var(--wh);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.pw-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.pw-wrap input {
  flex: 1;
  padding-right: 44px;
}
.pw-eye {
  position: absolute;
  right: 6px;
  background: none;
  border: none;
  font-size: 16px;
  padding: 8px;
  cursor: pointer;
  opacity: 0.5;
  transition: 0.2s;
}
.pw-eye:hover {
  opacity: 1;
}
.auth-submit {
  width: 100%;
  padding: 16px;
  border-radius: var(--r);
  background: var(--olive);
  color: #fff;
  border: none;
  font-weight: 700;
  font-size: 16px;
  transition: 0.3s var(--ease);
  margin-top: 8px;
}
.auth-submit:hover:not(:disabled) {
  background: var(--olive-60);
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(74, 93, 35, 0.3);
}
.auth-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.auth-error {
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #dc2626;
  padding: 12px 16px;
  border-radius: var(--rs);
  font-size: 13px;
  margin-bottom: 16px;
  animation: fadeUp 0.3s var(--ease);
}
/* Wave 3 — booking auth-wall banner. A calm olive note (NOT the red error)
   that tells a guest, after the "Confirm" redirect, why they're on the
   sign-in screen. Olive left-accent + warm wash so it reads as a friendly
   nudge, not a failure. Deep-olive text on the light wash clears WCAG AA. */
.auth-notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: linear-gradient(180deg, #f3f6ec, #eef2e3);
  border: 1px solid #dbe3c6;
  border-left: 3px solid var(--olive);
  color: #45502f;
  padding: 12px 14px;
  border-radius: var(--rs);
  font-size: 14px;
  line-height: 1.45;
  margin-bottom: 18px;
}
.auth-notice__icon {
  font-size: 16px;
  line-height: 1.4;
  flex-shrink: 0;
}
.auth-notice__text {
  font-weight: 500;
}
@media (prefers-reduced-motion: no-preference) {
  .auth-notice {
    animation: fadeUp 0.4s var(--ease);
  }
}
.auth-switch {
  text-align: center;
  margin-top: 24px;
  font-size: 14px;
  color: var(--text-m);
}
.auth-switch button {
  background: none;
  border: none;
  color: var(--olive);
  font-weight: 600;
  font-size: 14px;
  transition: 0.2s;
}
.auth-switch button:hover {
  text-decoration: underline;
}
.auth-divider {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 24px 0;
  color: var(--text-m);
  font-size: 12px;
}
.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--brd);
}
.auth-spinner {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 2.5px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

/* ── LAYOUT ──────────────────────────────── */
.app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(250, 249, 246, 0.88);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid rgba(74, 93, 35, 0.06);
  height: 72px;
  display: flex;
  align-items: center;
  padding: 0 clamp(16px, 4vw, 48px);
  /* Phase B/4 — env(safe-area-inset-top) protects the brand row from
     the iOS notch / Dynamic Island when installed as a PWA in
     standalone mode. Evaluates to 0 in normal browser mode so the
     header height is unchanged for non-installed users. */
  padding-top: env(safe-area-inset-top);
  transition: 0.3s var(--ease);
}
.nav.scr {
  height: 64px;
  box-shadow: var(--sh-s);
}
.nav-in {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.brand {
  /* Wordmark set in Playfair Display italic (our display face) instead of
     Pacifico. Pacifico is a casual Google script that reads "template/Canva";
     dropping it leaves a disciplined 2-family system (Playfair + Outfit) — the
     boutique-hospitality norm. Bumped 24->26px + 600 weight so the italic
     serif keeps the wordmark's presence. */
  font-family: var(--serif);
  font-style: italic;
  font-size: 26px;
  font-weight: 600;
  color: var(--olive);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: 0.2s;
  background: none;
  border: none;
}
.brand:hover {
  opacity: 0.8;
}
.brand .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--gold);
  display: inline-block;
}
.nlinks {
  display: flex;
  gap: 2px;
}
.nl {
  position: relative;
  padding: 10px 16px;
  border-radius: var(--rs);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-s);
  background: none;
  border: none;
  transition: 0.2s var(--ease);
}
.nl:hover {
  color: var(--olive);
  background: var(--olive-3);
}
.nl.act {
  color: var(--olive);
  font-weight: 600;
}
.nl.act::after {
  content: "";
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 20px;
  height: 3px;
  border-radius: 2px;
  background: var(--olive);
}
.nbadge {
  position: absolute;
  top: 4px;
  right: 6px;
  min-width: 18px;
  height: 18px;
  border-radius: 9px;
  background: var(--olive);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 5px;
}
.ncta {
  padding: 10px 24px;
  border-radius: var(--rs);
  background: var(--olive);
  color: #fff;
  border: none;
  font-weight: 600;
  font-size: 14px;
  transition: 0.25s var(--ease);
}
.ncta:hover {
  background: var(--olive-60);
  transform: translateY(-1px);
  box-shadow: 0 4px 16px rgba(74, 93, 35, 0.25);
}
.mtog {
  display: none;
  background: none;
  border: none;
  color: var(--text);
  padding: 8px;
  border-radius: var(--rs);
  font-size: 22px;
}
.mnav {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(250, 249, 246, 0.98);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  animation: fadeIn 0.25s var(--ease);
}
.mnav .xb {
  position: absolute;
  top: 20px;
  right: 20px;
  background: none;
  border: none;
  color: var(--text);
  padding: 8px;
  font-size: 24px;
}
.mnav button {
  font-size: 20px;
  padding: 16px 32px;
  border-radius: var(--r);
  background: none;
  border: none;
  color: var(--text-s);
  font-weight: 500;
  transition: 0.2s;
  width: 240px;
  text-align: center;
}
.mnav button:hover,
.mnav button.act {
  background: var(--olive-5);
  color: var(--olive);
}
.main {
  flex: 1;
}
.ctn {
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: 0 clamp(16px, 4vw, 48px);
}
.hero-full {
  position: relative;
  min-height: 520px;
  overflow: hidden;
}
.hero-bg-art {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-bg-art svg {
  width: 100%;
  height: 100%;
  display: block;
  /* Overscan: the JS parallax translates the SVG up to ~14px; scaling it
     slightly larger than the container guarantees no background shows
     through on any edge, no matter the mouse position. */
  transform: scale(1.08);
  transform-origin: center center;
  will-change: transform;
}
.hero-overlay {
  position: relative;
  z-index: 2;
  max-width: 1280px;
  margin: 0 auto;
  padding: 80px clamp(16px, 4vw, 48px) 60px;
  display: flex;
  align-items: center;
  min-height: 520px;
}
.hero-txt {
  max-width: 560px;
}
.hero-eye {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 18px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--olive-10);
  border-radius: 100px;
  font-size: 12px;
  font-weight: 600;
  color: var(--olive);
  margin-bottom: 24px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.hero-eye .pdot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--olive);
  animation: pulse 2s infinite;
  display: inline-block;
}
.hero-full h1 {
  font-family: var(--serif);
  font-size: clamp(32px, 5vw, 58px);
  font-weight: 700;
  line-height: 1.1;
  margin-bottom: 20px;
  letter-spacing: -0.02em;
  color: var(--text);
}
.hero-full h1 em {
  font-style: italic;
  color: var(--olive);
}
.hero-sub {
  font-size: 16px;
  color: var(--text-s);
  line-height: 1.7;
  margin-bottom: 16px;
  max-width: 480px;
}
.hero-loc {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--text-m);
  margin-bottom: 28px;
}
.hero-acts {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}
.hero-rating {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: var(--r);
  box-shadow: var(--sh-s);
}
.hero-rate-num {
  font-weight: 700;
  color: var(--olive);
  font-size: 16px;
}
.hero-rate-sub {
  color: var(--text-m);
  font-size: 11px;
}
.marq {
  /* Wave 2 (golden thread): sun-kissed top edge — the hero's descended sun
     grazes the strip below it. Static gold wash over the olive base; white
     13px text stays >=5.7:1 at the warmest point of the tint. */
  background:
    linear-gradient(180deg, rgba(200, 169, 81, 0.18), rgba(200, 169, 81, 0) 60%),
    var(--olive);
  border-bottom: 1px solid rgba(200, 169, 81, 0.25);
  color: #fff;
  padding: 14px 0;
  overflow: hidden;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.marq-trk {
  display: flex;
  gap: 40px;
  animation: marquee 35s linear infinite;
  white-space: nowrap;
  width: max-content;
}
.marq-item {
  display: flex;
  align-items: center;
  gap: 10px;
}
.marq-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold);
  display: inline-block;
}

/* ── STATS STRIP ───────────────────── */
.stats-strip {
  padding: 48px 0;
  background: var(--wh);
  border-bottom: 1px solid var(--brd-l);
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  text-align: center;
}
.stat-item {
  position: relative;
  padding: 20px 10px;
}
.stat-item:not(:last-child)::after {
  content: "";
  position: absolute;
  right: 0;
  top: 20%;
  height: 60%;
  width: 1px;
  background: var(--brd);
}
.stat-num {
  font-family: var(--serif);
  font-size: clamp(36px, 5vw, 52px);
  font-weight: 700;
  color: var(--olive);
  line-height: 1;
  display: inline;
}
.stat-plus,
.stat-slash {
  font-family: var(--serif);
  font-size: clamp(18px, 2.5vw, 24px);
  color: var(--olive-60);
  font-weight: 600;
  display: inline;
  margin-left: 2px;
}
.stat-label {
  font-size: 13px;
  color: var(--text-m);
  margin-top: 6px;
  font-weight: 500;
  letter-spacing: 0.3px;
}

/* ── REVIEWS CAROUSEL ──────────────── */
.rev-carousel-wrap {
  position: relative;
}
.rev-carousel {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 4px 0 20px;
  -ms-overflow-style: none;
  scrollbar-width: none;
}
.rev-carousel::-webkit-scrollbar {
  display: none;
}
.rev-carousel .rev-card {
  flex: 0 0 340px;
  scroll-snap-align: start;
}
.rev-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-60%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--wh);
  border: 1px solid var(--brd);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  color: var(--text-s);
  cursor: pointer;
  box-shadow: var(--sh);
  transition: 0.25s var(--ease);
  z-index: 5;
}
.rev-nav:hover {
  background: var(--olive);
  color: #fff;
  border-color: var(--olive);
  box-shadow: var(--sh-m);
}
.rev-nav.rev-prev {
  left: -22px;
}
.rev-nav.rev-next {
  right: -22px;
}
.rev-dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 16px;
}
.rev-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--olive-20);
  border: none;
  cursor: pointer;
  transition: 0.3s var(--ease);
  padding: 0;
}
.rev-dot.active {
  background: var(--olive);
  width: 24px;
  border-radius: 4px;
}

/* ── BACK TO TOP BUTTON ────────────── */
.btt {
  position: fixed;
  bottom: 28px;
  right: 28px;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--olive);
  color: #fff;
  border: none;
  font-size: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--sh-m);
  z-index: 90;
  opacity: 0;
  transform: translateY(20px);
  pointer-events: none;
  transition: 0.35s var(--ease);
}
.btt.show {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.btt:hover {
  background: var(--olive-60);
  transform: translateY(-3px) scale(1.05);
  box-shadow: var(--sh-l);
}

/* ── SMOOTH FAQ ACCORDION ──────────── */

/* ── SCROLL REVEAL ─────────────────── */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity 0.7s var(--ease),
    transform 0.7s var(--ease);
}
.reveal.vis {
  opacity: 1;
  transform: translateY(0);
}
.reveal.vis .reveal-d1 {
  transition-delay: 0.08s;
}
.reveal.vis .reveal-d2 {
  transition-delay: 0.16s;
}
.reveal.vis .reveal-d3 {
  transition-delay: 0.24s;
}
.reveal.vis .reveal-d4 {
  transition-delay: 0.32s;
}
.reveal.vis .reveal-d5 {
  transition-delay: 0.4s;
}
.reveal-child {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.5s var(--ease),
    transform 0.5s var(--ease);
}
.reveal.vis .reveal-child {
  opacity: 1;
  transform: translateY(0);
}
.sec {
  padding: 80px 0;
}
.sec-hd {
  margin-bottom: 44px;
}
.sec-ov {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.sec-ov::after {
  content: "";
  flex: 0 0 32px;
  height: 2px;
  background: linear-gradient(90deg, var(--olive), transparent);
  border-radius: 1px;
}
.sec-hd h2 {
  font-family: var(--serif);
  font-size: clamp(26px, 3.5vw, 40px);
  font-weight: 600;
}
.sec-hd p {
  color: var(--text-s);
  font-size: 15px;
  margin-top: 8px;
  max-width: 500px;
}
.rgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
  gap: 28px;
}
.rc {
  background: var(--wh);
  border-radius: var(--rl);
  overflow: hidden;
  box-shadow: var(--sh);
  cursor: pointer;
  border: 1px solid var(--brd-l);
  transition: 0.4s var(--ease);
}
.rc:hover {
  transform: translateY(-6px);
  box-shadow: var(--sh-l);
  /* Wave 3 (golden thread): hover rim warms to gold (was olive-20),
     matching the svc-card hover language. */
  border-color: rgba(200, 169, 81, 0.5);
}
/* Wave 3 (golden thread): the hero/auth film-grain language at card scale —
   2% multiply, static, pointer-events:none. NOTE: .rc::after is taken (the
   composite-cheap shadow intensifier, z-index:-1), so grain lives on ::before.
   .rc is position:relative + overflow:hidden + isolation:isolate (see the
   motion block ~10214), so the layer clips to the card radius and stays
   contained. At 0.02 alpha it has no legibility or photo impact. */
.rc::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.02;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
}
.rc-img {
  position: relative;
  overflow: hidden;
  height: 240px;
}
.rc-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease);
}
.rc:hover .rc-img img {
  transform: scale(1.06);
}
.rc-type {
  position: absolute;
  top: 14px;
  left: 14px;
  padding: 6px 14px;
  /* Wave 3 (golden thread): chip warms from plain white to the gold-light
     family + gold hairline. Olive text on #fdf8ec stays well above AA. */
  background: rgba(253, 248, 236, 0.92);
  border: 1px solid rgba(200, 169, 81, 0.35);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: 100px;
  font-size: 11px;
  font-weight: 700;
  color: var(--olive);
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.rc-fav {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  transition: 0.25s var(--spring);
}
.rc-fav:hover {
  transform: scale(1.15);
}
.rc-bod {
  padding: 22px;
}
.rc-top {
  display: flex;
  justify-content: space-between;
  align-items: start;
  margin-bottom: 6px;
}
.rc-nm {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 600;
}
.rc-rat {
  display: flex;
  align-items: center;
  gap: 4px;
  /* Phase L (a11y) — gold #C8A951 on cream #FAF9F6 ≈ 1.6:1 fails WCAG 4.5:1
     for 14px body text. Olive #4A5D23 on cream ≈ 7.5:1 (passes AA + AAA),
     preserves brand. Gold survives elsewhere on accents/large display. */
  color: var(--olive);
  font-size: 14px;
  font-weight: 600;
}
.rc-rat span {
  color: var(--text-m);
  font-weight: 400;
  font-size: 12px;
}
.rc-loc {
  color: var(--text-m);
  font-size: 13px;
  margin-bottom: 14px;
}
.rc-bot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 14px;
  border-top: 1px solid var(--brd-l);
}
.rc-pr {
  font-weight: 700;
  font-size: 20px;
  color: var(--olive);
}
.rc-pr span {
  font-weight: 400;
  font-size: 13px;
  color: var(--text-m);
}
.rc-btn {
  padding: 10px 20px;
  border-radius: var(--rs);
  background: var(--olive-5);
  color: var(--olive);
  border: none;
  font-weight: 600;
  font-size: 13px;
  transition: 0.25s var(--ease);
}
.rc-btn:hover {
  background: var(--olive);
  color: #fff;
}
.attr-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
}
.attr-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  background: var(--wh);
  padding: 22px;
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  transition: 0.35s var(--ease);
  overflow: hidden;
  cursor: pointer; /* card is now an <a> to Google Maps */
  text-decoration: none;
  color: inherit; /* keep title/desc colors, not link-blue */
}
/* Keyboard focus ring (a11y) for the now-tappable cards */
.attr-card:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 3px;
}
/* Subtle persistent "opens in Maps" cue — visible on touch (no hover).
   Wave 4 (golden thread): cue warms to the hero's bronze-gold (#8a6a1c,
   ~4.4:1 on white — the deep-gold family that passes where --gold can't)
   and strengthens to full opacity on hover. */
.attr-card::after {
  content: "↗";
  position: absolute;
  top: 10px;
  right: 12px;
  font-size: 12px;
  line-height: 1;
  color: #8a6a1c;
  opacity: 0.45;
  transition:
    opacity 0.3s var(--ease),
    transform 0.3s var(--ease);
}
.attr-card:hover::after {
  opacity: 1;
  transform: translate(1px, -1px);
}
.attr-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 0;
  background: linear-gradient(180deg, var(--olive), var(--gold));
  border-radius: 0 2px 2px 0;
  transition: height 0.35s var(--ease);
}
.attr-card:hover {
  /* Wave 4 (golden thread): hover rim warms to gold, matching svc/rc cards. */
  border-color: rgba(200, 169, 81, 0.5);
  box-shadow: var(--sh-m);
  transform: translateY(-4px);
}
.attr-card:hover::before {
  height: 100%;
}
.attr-icon {
  font-size: 26px;
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--olive-5), var(--olive-10));
  display: flex;
  align-items: center;
  justify-content: center;
  transition: 0.35s var(--ease);
  box-shadow: 0 2px 8px rgba(74, 93, 35, 0.06);
}
.attr-card:hover .attr-icon {
  transform: scale(1.08) rotate(-3deg);
  /* Wave 4 (golden thread): icon hover warms from gold-light into olive,
     matching the svc-icon hover treatment. */
  background: linear-gradient(135deg, var(--gold-light), var(--olive-20));
  box-shadow: 0 4px 14px rgba(74, 93, 35, 0.12);
}
.attr-txt h3 {
  font-family: var(--serif);
  font-size: 15px;
  margin-bottom: 3px;
  transition: color 0.25s;
}
.attr-card:hover .attr-txt h3 {
  color: var(--olive);
}
.attr-txt p {
  color: var(--text-m);
  font-size: 12px;
  line-height: 1.5;
}
.attr-meta {
  margin-left: auto;
  text-align: right;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.attr-dist {
  color: var(--wh);
  font-size: 11px;
  font-weight: 600;
  background: var(--olive);
  padding: 3px 10px;
  border-radius: 20px;
  white-space: nowrap;
}
.attr-fee {
  color: var(--text-m);
  font-size: 11px;
  text-align: center;
}
/* "Nearby" proximity tag (landing cards) — olive pill, always visible.
   Kept separate from .attr-dist, which the Siquijor Guide page reveals
   via .is-in/.fu; the landing cards use the reveal-child system and
   never get those classes, so a shared .attr-dist would stay invisible. */
.attr-near {
  display: inline-flex;
  align-items: center;
  color: var(--wh);
  font-size: 11px;
  font-weight: 600;
  background: var(--olive);
  /* Wave 4 (golden thread): gold hairline ring on the olive pill. The pill
     stays olive/white (7.5:1) — a full-gold pill or gold TEXT at 11px would
     fail the 4.5:1 floor (Phase L lesson). */
  border: 1px solid rgba(200, 169, 81, 0.45);
  padding: 3px 10px;
  border-radius: 20px;
  white-space: nowrap;
}
.svc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 18px;
}
.svc-card {
  position: relative;
  background: var(--wh);
  padding: 26px;
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  display: flex;
  gap: 18px;
  align-items: center;
  transition: 0.35s var(--ease);
  overflow: hidden;
}
.svc-card:hover {
  /* Wave 2 (golden thread): hover rim warms to gold (was olive-20). */
  border-color: rgba(200, 169, 81, 0.5);
  box-shadow: var(--sh-m);
  transform: translateY(-4px);
}
/* Wave 2 (golden thread): the hero/auth film-grain language at card scale —
   2% multiply, static, pointer-events:none. Sits over the whole card face
   (that is what film grain is); at 0.02 alpha it has no legibility impact. */
.svc-card::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.02;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
}
.svc-icon {
  font-size: 24px;
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--olive-5), var(--olive-10));
  display: flex;
  align-items: center;
  justify-content: center;
  transition: 0.35s var(--ease);
  box-shadow: 0 2px 8px rgba(74, 93, 35, 0.06);
}
.svc-card:hover .svc-icon {
  /* Wave 2 (golden thread): icon hover warms from gold-light into olive. */
  background: linear-gradient(135deg, var(--gold-light), var(--olive-20));
  transform: scale(1.1);
  box-shadow: 0 4px 14px rgba(74, 93, 35, 0.12);
}
.svc-nm {
  font-weight: 600;
  font-size: 15px;
  margin-bottom: 4px;
  transition: color 0.25s;
}
.svc-card:hover .svc-nm {
  color: var(--olive);
}
.svc-desc {
  color: var(--text-m);
  font-size: 13px;
  line-height: 1.5;
}
.svc-arrow {
  position: absolute;
  right: 20px;
  top: 50%;
  transform: translateY(-50%) translateX(-4px);
  opacity: 0;
  color: var(--olive);
  font-size: 16px;
  transition: 0.3s var(--ease);
}
.svc-card:hover .svc-arrow {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}
.rev-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}
.rev-card {
  position: relative;
  background: var(--wh);
  padding: 32px 28px 28px;
  border-radius: var(--rl);
  border: 1px solid var(--brd-l);
  transition: 0.35s var(--ease);
  overflow: hidden;
}
.rev-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(
    90deg,
    var(--olive),
    var(--gold),
    var(--olive-20)
  );
  opacity: 0;
  transition: opacity 0.35s;
}
.rev-card:hover {
  box-shadow: var(--sh-m);
  border-color: var(--olive-20);
  transform: translateY(-4px);
}
.rev-card:hover::before {
  opacity: 1;
}
.rev-quote {
  font-family: var(--serif);
  font-size: 40px;
  line-height: 1;
  /* Wave 2 (golden thread): the quote glyph warms to gold (was olive-20) —
     decorative only, echoes the hero's gold accents. */
  color: rgba(200, 169, 81, 0.45);
  margin-bottom: 8px;
  user-select: none;
}
.rev-stars {
  color: var(--gold);
  display: flex;
  gap: 2px;
  margin-bottom: 14px;
  font-size: 16px;
  letter-spacing: 1px;
}
.rev-text {
  font-size: 14px;
  color: var(--text-s);
  line-height: 1.8;
  margin-bottom: 20px;
  font-style: italic;
}
.rev-author {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 16px;
  border-top: 1px solid var(--brd-l);
}
.rev-name {
  font-weight: 600;
  font-size: 14px;
}
.rev-src {
  font-size: 11px;
  color: var(--olive);
  background: var(--olive-5);
  padding: 5px 12px;
  border-radius: 100px;
  font-weight: 500;
  border: 1px solid var(--olive-10);
}
/* Guest avatar in carousel cards */
.rev-avatar,
.rev-avatar-ring {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 18px;
  color: #fff;
  font-weight: 700;
  margin-bottom: 12px;
  flex-shrink: 0;
}
.rev-avatar-ring {
  border: 2px solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.rev-src-app {
  /* Wave 7: off-brand blue -> warm gold-tinted olive pill. Keeps the "app"
     source visually distinct from the plain-olive .rev-src (it gains a gold
     tint + hairline) while joining the golden thread. Olive TEXT, not gold —
     gold at 11px on a pale pill fails 4.5:1 (Phase L). */
  background: linear-gradient(135deg, var(--olive-5), rgba(200, 169, 81, 0.14));
  color: var(--olive);
  border-color: rgba(200, 169, 81, 0.35);
}
/* Unfilled stars */
.rev-stars {
  color: var(--gold);
}

/* ── WRITE REVIEW ──────────────────── */
.write-rev-wrap {
  margin-top: 36px;
}
.write-rev-card {
  background: var(--wh);
  border-radius: var(--rxl);
  padding: 32px;
  border: 1px solid var(--brd-l);
  box-shadow: var(--sh);
  transition: 0.35s var(--ease);
  position: relative;
  overflow: hidden;
}
.write-rev-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(
    90deg,
    var(--olive),
    var(--gold),
    var(--olive-60)
  );
  background-size: 200% 100%;
  animation: ftGradient 3s linear infinite;
}
.write-rev-card.star-picked {
  animation: revBounce 0.4s var(--spring);
}
@keyframes revBounce {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.015);
  }
  100% {
    transform: scale(1);
  }
}
.write-rev-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}
.write-rev-icon {
  font-size: 32px;
  width: 56px;
  height: 56px;
  background: linear-gradient(135deg, var(--olive-5), var(--olive-10));
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.write-rev-title {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 3px;
}
.write-rev-sub {
  font-size: 13px;
  color: var(--text-m);
}
.write-rev-stars {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
}
.wr-star {
  background: none;
  border: none;
  font-size: 36px;
  cursor: pointer;
  color: var(--brd);
  transition: 0.2s var(--spring);
  padding: 0 2px;
  line-height: 1;
}
.wr-star.hov {
  color: var(--gold);
  transform: scale(1.2);
}
.wr-star.sel {
  color: var(--gold);
  transform: scale(1.1);
}
.write-rev-hint {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 16px;
  min-height: 20px;
  transition: 0.2s;
}
.write-rev-textarea {
  width: 100%;
  border: 1.5px solid var(--brd);
  border-radius: var(--r);
  padding: 14px 16px;
  font-size: 14px;
  font-family: var(--sans);
  resize: none;
  min-height: 100px;
  outline: none;
  transition: 0.2s var(--ease);
  background: var(--cream);
  line-height: 1.6;
  color: var(--text);
}
.write-rev-textarea:focus {
  border-color: var(--olive);
  background: var(--wh);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.write-rev-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 12px;
}
.write-rev-chars {
  font-size: 12px;
  color: var(--text-m);
}
.write-rev-btn {
  padding: 12px 28px;
  border-radius: var(--rs);
  background: var(--olive);
  color: #fff;
  border: none;
  font-weight: 700;
  font-size: 14px;
  transition: 0.3s var(--ease);
  cursor: pointer;
}
.write-rev-btn:hover:not(:disabled) {
  background: var(--olive-60);
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(74, 93, 35, 0.3);
}
.write-rev-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.write-rev-success {
  text-align: center;
  padding: 24px 0;
  animation: scaleIn 0.5s var(--spring);
}
.write-rev-success-icon {
  font-size: 52px;
  margin-bottom: 12px;
}
.write-rev-success h3 {
  font-family: var(--serif);
  font-size: 22px;
  margin-bottom: 8px;
  color: var(--olive);
}
.write-rev-success p {
  color: var(--text-m);
  font-size: 14px;
}
.write-rev-login {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 20px 24px;
  background: var(--wh);
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  margin-top: 28px;
  flex-wrap: wrap;
}
.write-rev-login span {
  font-size: 24px;
}
.write-rev-login p {
  color: var(--text-s);
  font-size: 14px;
  flex: 1;
}

/* ── COCONUT TREES ─────────────────── */
@keyframes sway {
  0%,
  100% {
    transform: rotate(-2deg) translateX(0);
  }
  50% {
    transform: rotate(2deg) translateX(4px);
  }
}
@keyframes swayR {
  0%,
  100% {
    transform: rotate(2deg) translateX(0);
  }
  50% {
    transform: rotate(-2deg) translateX(-4px);
  }
}
.coco-tree {
  position: absolute;
  bottom: 0;
  width: 160px;
  pointer-events: none;
  z-index: 1;
}
.coco-tree svg {
  display: block;
  width: 100%;
  height: auto;
}
.coco-left {
  left: 0;
  transform-origin: bottom center;
  animation: sway 6s ease-in-out infinite;
}
.coco-right {
  right: 0;
  transform-origin: bottom center;
  animation: swayR 7s ease-in-out infinite;
}
.coco-frond {
  transform-origin: 65px 60px;
}
.coco-left .coco-frond {
  animation: sway 4s ease-in-out infinite;
}
.coco-right .coco-frond {
  animation: swayR 5s ease-in-out infinite;
}
.island-cta {
  overflow: visible;
}

.cta {
  background: var(--olive);
  border-radius: var(--rxl);
  padding: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
  color: #fff;
  position: relative;
  overflow: hidden;
}
.cta::before {
  content: "";
  position: absolute;
  top: -50%;
  right: -10%;
  width: 400px;
  height: 400px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.04);
}
.cta h2 {
  font-family: var(--serif);
  font-size: 32px;
  margin-bottom: 10px;
}
.cta p {
  opacity: 0.8;
  font-size: 15px;
  max-width: 420px;
}
.cta-btn {
  padding: 16px 32px;
  border-radius: var(--r);
  background: #fff;
  color: var(--olive);
  border: none;
  font-weight: 700;
  font-size: 15px;
  transition: 0.25s var(--ease);
  white-space: nowrap;
  flex-shrink: 0;
}
.cta-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}

/* ── STATS STRIP ─────────────────────── */
.stats-strip {
  padding: 48px 0;
  border-bottom: 1px solid var(--brd-l);
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  text-align: center;
}
.stat-item {
  padding: 20px;
  border-right: 1px solid var(--brd-l);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.stat-item:last-child {
  border-right: none;
}
.stat-num {
  font-family: var(--serif);
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 700;
  color: var(--olive);
  line-height: 1;
  display: inline-block;
}
.stat-plus {
  font-family: var(--serif);
  font-size: clamp(20px, 3vw, 32px);
  font-weight: 700;
  /* Phase L (a11y) — even at large-text size (≥18.66px bold qualifies for
     3:1), gold #C8A951 on cream is ~1.6:1 → fails. Olive passes 7.5:1. */
  color: var(--olive);
  line-height: 1;
  display: inline-block;
}
.stat-slash {
  font-family: var(--serif);
  font-size: clamp(16px, 2.5vw, 24px);
  color: var(--text-m);
  line-height: 1;
  display: inline-block;
}
.stat-label {
  font-size: 13px;
  color: var(--text-s);
  font-weight: 500;
  margin-top: 6px;
}
.stat-item > div:first-child {
  display: flex;
  align-items: baseline;
  gap: 2px;
}
@media (max-width: 768px) {
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .stat-item {
    border-bottom: 1px solid var(--brd-l);
    padding: 24px 16px;
  }
  .stat-item:nth-child(even) {
    border-right: none;
  }
  .stat-item:nth-child(3),
  .stat-item:nth-child(4) {
    border-bottom: none;
  }
  .stats-strip {
    padding: 32px 0;
  }
}

/* ── ISLAND CTA ─────────────────────── */
@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
@keyframes glow {
  0%,
  100% {
    opacity: 0.04;
  }
  50% {
    opacity: 0.08;
  }
}
.island-cta {
  position: relative;
  border-radius: var(--rxl);
  overflow: hidden;
  /* Wave 2 (golden thread): a static gold sun-rim grazes the top of the card
     (the descended hero sun's light), layered over the olive base. The bottom
     waves are deliberately NOT warmed — .sec-prefooter .island-wave must stay
     olive-3 to blend into the footer it dives into (brief §5.8). White h2
     stays >=6.6:1 at the warmest point of the rim. */
  background:
    linear-gradient(180deg, rgba(200, 169, 81, 0.22), rgba(200, 169, 81, 0) 38%),
    linear-gradient(
    160deg,
    #3a4d1a 0%,
    var(--olive) 40%,
    #5a7a2e 100%
  );
  padding: 0;
  text-align: center;
}
.island-cta-bg {
  position: absolute;
  inset: 0;
  opacity: 0.06;
  background-image:
    radial-gradient(
      ellipse 300px 200px at 10% 80%,
      rgba(255, 255, 255, 0.3),
      transparent
    ),
    radial-gradient(
      ellipse 200px 300px at 90% 20%,
      rgba(255, 255, 255, 0.2),
      transparent
    ),
    radial-gradient(
      circle 100px at 50% 100%,
      rgba(200, 169, 81, 0.3),
      transparent
    );
  animation: glow 4s ease-in-out infinite;
}
.island-cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    110deg,
    transparent 30%,
    rgba(255, 255, 255, 0.04) 50%,
    transparent 70%
  );
  background-size: 200% 100%;
  animation: shimmer 8s linear infinite;
  z-index: 1;
  pointer-events: none;
}
.island-cta-content {
  position: relative;
  z-index: 2;
  padding: 52px 36px 40px;
}
.island-cta-icon {
  font-size: 44px;
  margin-bottom: 16px;
  animation: float 4s ease-in-out infinite;
}
.island-cta h2 {
  font-family: var(--serif);
  font-size: clamp(26px, 4vw, 36px);
  color: #fff;
  margin-bottom: 12px;
  line-height: 1.2;
}
.island-cta p {
  color: rgba(255, 255, 255, 0.8);
  font-size: 15px;
  max-width: 480px;
  margin: 0 auto 28px;
  line-height: 1.7;
}
.island-cta-features {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 32px;
}
.island-feat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  color: rgba(255, 255, 255, 0.9);
  font-size: 13px;
  font-weight: 500;
  border: 1px solid rgba(255, 255, 255, 0.08);
  transition: 0.25s var(--ease);
}
.island-feat:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-1px);
}
.island-feat span {
  font-size: 16px;
}
.island-cta-btn {
  padding: 16px 40px;
  border-radius: var(--r);
  background: #fff;
  color: var(--olive);
  border: none;
  font-weight: 700;
  font-size: 16px;
  transition: 0.3s var(--ease);
  cursor: pointer;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  position: relative;
  z-index: 2;
}
.island-cta-btn:hover {
  transform: translateY(-3px) scale(1.02);
  box-shadow: 0 10px 36px rgba(0, 0, 0, 0.3);
  background: var(--gold-light);
  color: #3a4d1a;
}
.island-cta-note {
  margin-top: 16px;
  /* Wave 7 (a11y): was rgba(255,255,255,0.45) on the olive CTA gradient ≈ 2.3:1
     (AA fail at 12px). Solid #fff over the lightest olive stop (#5a7a2e) is
     ≥4.95:1, and more over the darker olive above it — so AA holds across the
     gradient. margin-bottom lifts the note clear of the olive-3 wave crest (it
     previously dipped ~28px into .island-cta-deco; the crest grazed its last
     ~3px), so no glyph sits over the pale wave where no colour would pass. */
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.5px;
  margin-bottom: 14px;
}
.island-cta-deco {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 60px;
  overflow: hidden;
  z-index: 1;
}
.island-wave {
  position: absolute;
  bottom: -5px;
  left: -5%;
  width: 110%;
  height: 40px;
  background: var(--cream);
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: 1;
}
.island-wave.w2 {
  bottom: -15px;
  height: 30px;
  opacity: 0.3;
  animation: float 6s ease-in-out infinite;
}
/* Phase 3 (a11y) — reduced-motion was enumerated per-element and never covered
   these decorative home loops (coconut-palm sway, island-CTA glow/float/shimmer)
   or the page-transition fade, so they kept animating under `reduce`, violating
   the reduced-motion mandate. Neutralise them. Each element rests in its visible
   base state (sways stop rotating, glow/float stop pulsing, .page-fade shows
   fully opaque because pageFade is a 0→1 fade-in), so nothing disappears. */
@media (prefers-reduced-motion: reduce) {
  .coco-left,
  .coco-right,
  .coco-left .coco-frond,
  .coco-right .coco-frond,
  .island-cta::before,
  .island-cta::after,
  .island-cta-icon,
  .island-wave.w2,
  .page-fade {
    animation: none !important;
  }
}
.sec-prefooter {
  padding-bottom: 0;
  /* Brief §5.8 — footer is olive-3; prefooter gradient blends into it. */
  background: linear-gradient(180deg, var(--cream) 0%, var(--olive-3) 100%);
}
.sec-prefooter .island-wave {
  /* Wave colour must match the footer it dives into (olive-3 per §5.8). */
  background: var(--olive-3);
}
.ft {
  /* §5.8 — Multi-column layout with soft olive-3 background.
     Wave 6: the base stays OPAQUE var(--olive-3) on purpose. The footer is
     the destination of the §5.8 prefooter-wave blend (.sec-prefooter
     .island-wave is olive-3), so dropping it to the golden-thread
     translucent wash (olive-3 @ 55%) would let the live body-warming bleed
     through and open a tonal seam exactly at the wave dive. The thread is
     carried here by grain + gold accents instead of transparency. */
  background: var(--olive-3);
  color: var(--text-s);
  padding: 0 0 24px;
  margin-top: 0;
  position: relative;
  overflow: hidden; /* bounds the ::after grain layer (kit host requirement) */
}
/* Wave 6 (golden thread): the hero/auth/card film-grain language at footer
   scale — 2% multiply, static, pointer-events:none, behind the links.
   .ft::after is free (the accent bar is a real child <div>; the h3::after and
   newsletter::after pseudos live on descendants, not on .ft). inset:0
   self-bounds to the padding box; overflow:hidden above is belt-and-braces.
   At 0.02 alpha it is texture only — zero legibility impact on the footer
   links, and the global reduced-motion reset (styles.css ~74) leaves it
   untouched because it is a static image, not an animation. */
.ft::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.02;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
}
.ft-top-accent {
  height: 3px;
  background: linear-gradient(
    90deg,
    var(--olive),
    var(--gold),
    var(--olive-60),
    var(--olive)
  );
  background-size: 300% 100%;
  animation: ftGradient 8s linear infinite;
}
@keyframes ftGradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}
.ft-main {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 48px;
  padding: 60px 0 48px;
}
.ft-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
}
.ft-logo-icon {
  font-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  /* Olive tint on the pale footer reads as a soft brand chip. */
  background: var(--olive-10);
  border-radius: 12px;
  /* Wave 6 (golden thread): gold hairline rim ties the brand mark to the
     thread. rgba(200,169,81,0.35) = --gold #c8a951 at 35% — a DECORATIVE
     border only (never gold text/fill at this size; Phase L a11y). */
  border: 1px solid rgba(200, 169, 81, 0.35);
}
.ft-brand {
  font-family: var(--serif);
  font-size: 28px;
  color: var(--text-d);
  font-weight: 700;
}
.ft-desc {
  font-size: 14px;
  line-height: 1.8;
  max-width: 320px;
  margin-bottom: 24px;
}
.ft-socials {
  display: flex;
  gap: 10px;
}
.ft-social {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--olive-10);
  border: 1px solid var(--olive-20);
  display: grid;
  place-items: center;
  color: var(--text-d);
  transition: 0.3s var(--ease);
  text-decoration: none;
  line-height: 0;
  padding: 0;
  box-sizing: border-box;
}
.ft-social:hover {
  background: var(--olive);
  color: #fff;
  border-color: var(--olive);
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(74, 93, 35, 0.4);
}
.ft-social svg {
  display: block;
  flex-shrink: 0;
}
.ft-links-col h3 {
  color: var(--text-d);
  font-size: 11px;
  font-weight: 700;
  margin-bottom: 20px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  position: relative;
  padding-bottom: 12px;
}
.ft-links-col h3::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 24px;
  height: 2px;
  /* Wave 6 (golden thread): column-header tick olive -> gold. A decorative
     2px accent (not text) -> AA-exempt; carries the thread through the
     footer columns. */
  background: var(--gold);
  border-radius: 1px;
}
.ft a {
  color: var(--text-s);
  text-decoration: none;
  font-size: 14px;
  display: block;
  padding: 6px 0;
  transition: 0.25s var(--ease);
  position: relative;
}
.ft a:hover {
  color: var(--olive);
  padding-left: 6px;
}
/* Wave 6 (golden thread + a11y): gold keyboard focus ring on every footer
   control. The footer had NO :focus-visible rule before this, so keyboard
   users got only the UA default outline on booking-adjacent links (Our
   Rooms, Payment Methods, Chat with Us). Every footer control is an <a>
   inside .ft — the social chips and the WhatsApp link included — so this one
   selector covers them all. outline (not box-shadow) can't be clipped by the
   new overflow:hidden and needs no extra layer. */
.ft a:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.ft-location {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin-top: 12px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-m);
}
.ft-divider {
  height: 1px;
  /* Wave 6 (golden thread): mid-stop olive-20 -> faint gold hairline
     (rgba(200,169,81,0.35) = --gold at 35%). Decorative 1px rule -> AA-exempt;
     a soft gold seam between the columns and the bottom bar. */
  background: linear-gradient(90deg, transparent, rgba(200, 169, 81, 0.35), transparent);
  margin-bottom: 20px;
}
.ft-bot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  color: var(--text-m);
}
.ft-made {
  color: var(--text-m);
}
.det {
  padding: 32px 0 80px;
}
.det-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  border-radius: var(--rs);
  background: none;
  border: 1px solid var(--brd);
  color: var(--text-s);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 24px;
  transition: 0.2s;
}
.det-back:hover {
  background: var(--olive-3);
  border-color: var(--olive-20);
  color: var(--olive);
}
.det-gal {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 6px;
  border-radius: var(--rxl);
  overflow: hidden;
  height: 400px;
  margin-bottom: 36px;
}
.dg-main {
  height: 100%;
}
.dg-main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.dg-side {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 6px;
}
.dg-side img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: 0.3s;
}
.dg-side img:hover {
  opacity: 0.85;
}
.det-lay {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 44px;
}
.det-info h1 {
  font-family: var(--serif);
  font-size: 32px;
  margin-bottom: 10px;
}
.det-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 24px;
}
.det-mi {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-s);
}
.det-desc {
  font-size: 15px;
  line-height: 1.8;
  color: var(--text-s);
  margin-bottom: 28px;
}
.det-stit {
  font-family: var(--serif);
  font-size: 20px;
  margin-bottom: 16px;
}
.am-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 32px;
}
.am-tag {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: var(--olive-3);
  border: 1px solid var(--olive-10);
  border-radius: 100px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-s);
}
.bk {
  position: sticky;
  top: 96px;
  background: var(--wh);
  border-radius: var(--rl);
  padding: 28px;
  box-shadow: var(--sh-m);
  border: 1px solid var(--brd-l);
  height: fit-content;
}
.bk-pr {
  font-family: var(--serif);
  font-size: 28px;
  color: var(--olive);
  margin-bottom: 4px;
}
.bk-pr span {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 400;
  color: var(--text-m);
}
.bk-sub {
  font-size: 12px;
  color: var(--text-m);
  margin-bottom: 20px;
}
.bk-dates {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1.5px solid var(--brd);
  border-radius: var(--r);
  overflow: hidden;
  margin-bottom: 10px;
}
.bk-df {
  position: relative;
  cursor: pointer;
  min-height: 62px;
  display: block;
  -webkit-tap-highlight-color: rgba(74, 93, 35, 0.08);
  transition: background 0.15s ease;
}
.bk-df:active {
  background: rgba(74, 93, 35, 0.05);
}
.bk-df:first-child {
  border-right: 1.5px solid var(--brd);
}
.bk-df-lbl {
  position: absolute;
  top: 10px;
  left: 14px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-m);
  pointer-events: none;
  z-index: 1;
}
.bk-df input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 28px 14px 8px;
  border: none;
  background: transparent;
  font-size: 16px;
  font-weight: 500;
  color: var(--text);
  outline: none;
  font-family: var(--sans);
  box-sizing: border-box;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  z-index: 2;
}
.bk-df input::-webkit-date-and-time-value {
  text-align: left;
  line-height: 1.2;
}
.bk-df input::-webkit-calendar-picker-indicator {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}
@media (max-width: 768px) {
  .bk-df {
    min-height: 68px;
  }
  .bk-df input {
    font-size: 16px;
    padding: 30px 14px 10px;
  }
}
.bk-guests {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border: 1.5px solid var(--brd);
  border-radius: var(--r);
  margin-bottom: 16px;
}
/* Extra-guests pill — visually paired with the Guests pill above it */
.bk-xguests {
  margin-bottom: 16px;
  border: 1.5px dashed rgba(74, 93, 35, 0.22);
  background: var(--olive-3);
  transition:
    border-color 200ms ease,
    background 200ms ease;
}
.bk-xguests:hover {
  border-color: rgba(74, 93, 35, 0.4);
}
.bk-guests label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-m);
}
.bk-ctr {
  display: flex;
  align-items: center;
  gap: 14px;
}
.bk-ctr button {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1.5px solid var(--brd);
  background: none;
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: 0.2s;
  color: var(--text-s);
}
.bk-ctr button:hover {
  border-color: var(--olive);
  color: var(--olive);
  background: var(--olive-3);
}
.bk-ctr span {
  font-weight: 600;
  min-width: 18px;
  text-align: center;
}
.bk-go {
  width: 100%;
  padding: 14px;
  border-radius: var(--r);
  background: var(--olive);
  color: #fff;
  border: none;
  font-weight: 700;
  font-size: 15px;
  transition: 0.3s var(--ease);
}
.bk-go:hover:not(:disabled) {
  background: var(--olive-60);
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(74, 93, 35, 0.3);
}
.bk-go:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.bk-brk {
  padding-top: 16px;
  margin-top: 16px;
  border-top: 1px solid var(--brd-l);
}
.bk-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: 13px;
  color: var(--text-s);
}
.bk-total {
  display: flex;
  justify-content: space-between;
  padding-top: 12px;
  margin-top: 6px;
  border-top: 1px solid var(--brd);
  font-weight: 700;
  font-size: 16px;
}
.bk-note {
  font-size: 11px;
  color: var(--text-m);
  margin-top: 14px;
  padding: 10px;
  background: var(--olive-3);
  border-radius: var(--rs);
  line-height: 1.5;
}
.tov {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(27, 33, 18, 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  animation: fadeIn 0.2s;
}
.tkt {
  background: #fff;
  border-radius: var(--rxl);
  overflow: hidden;
  max-width: 400px;
  width: 100%;
  box-shadow: var(--sh-l);
  animation: scaleIn 0.35s var(--spring);
}
.tkt-img {
  height: 160px;
  overflow: hidden;
}
.tkt-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tkt-bod {
  padding: 28px;
}
.tkt-st {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}
.tkt-conf {
  color: #16a34a;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 1px;
}
.tkt-bod h3 {
  font-family: var(--serif);
  font-size: 24px;
  margin-bottom: 16px;
}
.tkt-div {
  height: 1px;
  background: var(--brd-l);
  margin: 14px 0;
  position: relative;
}
.tkt-div::before,
.tkt-div::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--cream);
  transform: translateY(-50%);
}
.tkt-div::before {
  left: -28px;
}
.tkt-div::after {
  right: -28px;
}
.tkt-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 12px;
}
.tkt-row .tl {
  color: var(--text-m);
  font-size: 13px;
}
.tkt-row .tv {
  font-weight: 600;
  font-size: 14px;
}
.tkt-ft {
  background: var(--olive);
  padding: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: #fff;
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.5px;
}
.tkt-cls {
  margin-top: 16px;
  width: 100%;
  padding: 12px;
  border-radius: var(--r);
  background: var(--olive-3);
  border: none;
  font-weight: 600;
  color: var(--olive);
  font-size: 13px;
  transition: 0.2s;
}
.tkt-cls:hover {
  background: var(--olive-10);
}
.chat-list {
  max-width: 700px;
}
.chat-item {
  background: var(--wh);
  padding: 18px 22px;
  border-radius: var(--r);
  display: flex;
  gap: 14px;
  align-items: center;
  margin-bottom: 8px;
  border: 1px solid var(--brd-l);
  cursor: pointer;
  transition: 0.25s;
}
.chat-item:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
  transform: translateX(3px);
}
.chat-item.unr {
  border-left: 3px solid var(--olive);
}
.chat-av {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.chat-av-icon {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}
.chat-av-initial {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 20px;
  color: #fff;
  flex-shrink: 0;
  overflow: hidden;
}
.chat-c {
  flex: 1;
  min-width: 0;
}
.chat-nm {
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 1px;
}
.chat-preview {
  color: var(--text-m);
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-tm {
  color: var(--text-m);
  font-size: 11px;
  white-space: nowrap;
  flex-shrink: 0;
}
.chat-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--olive);
  flex-shrink: 0;
}
.chat-room {
  display: flex;
  flex-direction: column;
  /* Phase B/4 — use 100dvh on mobile so the chat occupies the
     dynamic-viewport area below the browser chrome (which collapses
     after scroll). 100vh fallback preserved for older browsers.
     Header offset reduced 140 -> 72 so the chat fills more of the
     screen above the keyboard. */
  height: calc(100vh - 72px);
  height: calc(100dvh - 72px);
  max-width: 800px;
  background: var(--wh);
  border-radius: var(--rl);
  border: 1px solid var(--brd-l);
  overflow: hidden;
  box-shadow: var(--sh);
}
.chat-header {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 24px;
  border-bottom: 1px solid var(--brd-l);
  flex-shrink: 0;
}
.chat-header img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
}
.chat-header-info h3 {
  font-family: var(--serif);
  font-size: 17px;
}
.chat-header-info p {
  font-size: 11px;
  color: var(--text-m);
}
.chat-header .ch-back {
  background: none;
  border: none;
  font-size: 20px;
  padding: 6px 10px;
  border-radius: 8px;
  color: var(--text-s);
  transition: 0.2s;
  margin-right: 4px;
}
.chat-header .ch-back:hover {
  background: var(--olive-3);
  color: var(--olive);
}
.chat-online {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22c55e;
  display: inline-block;
  margin-left: 6px;
}
.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* Phase B/4 — overscroll-behavior:contain stops scroll-chaining
     to the page body (otherwise dragging at the top of the chat
     list pulls the whole page). -webkit-overflow-scrolling:touch
     keeps momentum scrolling on iOS Safari < 16. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.chat-msg {
  max-width: 75%;
  padding: 12px 18px;
  border-radius: 18px;
  font-size: 14px;
  line-height: 1.5;
  position: relative;
  animation: fadeUp 0.25s var(--ease) both;
  /* Phase B/4 — long URLs / unbroken tokens should wrap rather than
     stretch the bubble past its 75% max-width and overflow the
     viewport on narrow screens. */
  overflow-wrap: anywhere;
  word-break: break-word;
}
.chat-msg.me {
  align-self: flex-end;
  /* Phase 11 A1: olive-10 alpha 0.10 was nearly invisible on cream parent
     after Phase 1 token change. Solid pale-olive gradient gives the brief's
     warm olive bubble vibe and passes WCAG AA for --text-d (#1F2A1A). */
  background: linear-gradient(135deg, #dceab9 0%, #c8d9a1 100%);
  color: var(--text-d);
  border-bottom-right-radius: 4px;
}
.chat-msg.them {
  align-self: flex-start;
  background: #fff;
  border: 1px solid var(--brd-l);
  color: var(--text);
  border-bottom-left-radius: 4px;
}
.chat-msg .msg-time {
  font-size: 10px;
  color: var(--text-m);
  margin-top: 6px;
  display: block;
}
.chat-msg .msg-sender {
  font-size: 10px;
  font-weight: 600;
  color: var(--olive);
  margin-bottom: 4px;
  display: block;
}
.chat-msg.me .msg-sender {
  color: var(--text-m);
}
.chat-input-bar {
  display: flex;
  gap: 10px;
  padding: 16px 24px;
  border-top: 1px solid var(--brd-l);
  background: var(--cream);
  flex-shrink: 0;
}
.chat-input-bar input {
  flex: 1;
  /* Phase E — without min-width:0, flex items use their content's
     intrinsic width as the floor. On narrow phones (iPhone SE/mini at
     375px), the 16px-mobile input + "Reply as Kwarto's…" placeholder
     pushed the input's min-content to ~190px which combined with the
     3 × 44px buttons + gaps overflowed the viewport, hiding the send
     button off the right edge. min-width:0 lets the input shrink. */
  min-width: 0;
  padding: 12px 18px;
  border: 1.5px solid var(--brd);
  border-radius: 100px;
  font-size: 14px;
  outline: none;
  background: var(--wh);
  transition: 0.2s;
}
.chat-input-bar input:focus {
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.chat-input-bar button {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--olive);
  color: #fff;
  border: none;
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: 0.25s var(--ease);
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(74, 93, 35, 0.2);
}
.chat-input-bar button:hover {
  background: var(--olive-60);
  transform: scale(1.08);
  box-shadow: 0 4px 14px rgba(74, 93, 35, 0.3);
}
.chat-input-bar button:active {
  transform: scale(0.95);
}
.chat-date-sep {
  text-align: center;
  font-size: 11px;
  color: var(--text-m);
  padding: 8px 0;
  position: relative;
}
.chat-date-sep::before,
.chat-date-sep::after {
  content: "";
  position: absolute;
  top: 50%;
  width: calc(50% - 50px);
  height: 1px;
  background: var(--brd-l);
}
.chat-date-sep::before {
  left: 0;
}
.chat-date-sep::after {
  right: 0;
}
/* ════════════════════════════════════════════════════════════════════
   PHASE AB — Payment system messages + Trips card states + receipt
   (CLAUDE_CODE_PAYMENT_TRIPS_RECEIPT_COPY_COMBINED.md Tasks 2–5)
   Brand tokens only; reuses existing pill base.
   ════════════════════════════════════════════════════════════════════ */

/* ── Centered system pills inside the chat thread (Task 2) ── */
.chat-system {
  align-self: center;
  max-width: 80%;
  margin: 10px auto;
  padding: 8px 14px;
  border-radius: 100px;
  background: var(--olive-3, rgba(74, 93, 35, 0.06));
  border: 1px solid rgba(74, 93, 35, 0.18);
  color: var(--text-s, var(--text-m));
  font-family: var(--sans);
  font-size: 12px;
  text-align: center;
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 1.45;
}
.chat-system-payment {
  background: linear-gradient(
    135deg,
    rgba(74, 93, 35, 0.1),
    rgba(200, 169, 81, 0.12)
  );
  border-color: rgba(200, 169, 81, 0.35);
  color: var(--text-d, var(--text));
  font-weight: 500;
}
.chat-system-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
  flex-shrink: 0;
}
.chat-system-txt {
  flex: 1;
  min-width: 0;
}

/* ════════════════════════════════════════════════════════════════════
   PHASE 2 — Chat upgrade client features
   (CLAUDE_CODE_CHAT_UPGRADE_PHASED_1.md follow-on tasks)
   - Auto-message pills (cron fan-out: prearrival / welcome / review)
   - Image attachments in bubbles
   - Starred messages indicator
   - Presence + typing affordances
   Brand tokens only — olive, gold, cream.
   ════════════════════════════════════════════════════════════════════ */

/* Auto messages: same pill shape as system, with a soft gold ring so the
   guest can tell "the host's automation is speaking" apart from "the host
   typed this manually." Border is the only differentiator — colour gradient
   reads the same so it doesn't feel out of brand. */
.chat-system-auto {
  background: linear-gradient(
    135deg,
    rgba(200, 169, 81, 0.1),
    rgba(74, 93, 35, 0.06)
  );
  border-color: rgba(200, 169, 81, 0.45);
  color: var(--text-d, var(--text));
}
.chat-system-auto .chat-system-dot {
  background: var(--olive, #4a5d23);
  box-shadow: 0 0 0 2px rgba(200, 169, 81, 0.35);
}

/* ── Image attachments inside chat bubbles ─────────────────────────── */
.msg-attachment {
  display: block;
  margin: 6px 0 4px;
  max-width: 260px;
  border-radius: 12px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.04);
  cursor: zoom-in;
  position: relative;
}
.msg-attachment img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 360px;
  object-fit: cover;
  border-radius: 12px;
  /* Soft fade-in once the network image loads. */
  animation: kwAttachFade 220ms ease-out;
}
.msg-attachment.is-uploading {
  cursor: wait;
}
.msg-attachment.is-uploading::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.45);
  backdrop-filter: blur(2px);
}
.msg-attachment-spinner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.msg-attachment-spinner span {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2.5px solid rgba(74, 93, 35, 0.18);
  border-top-color: var(--gold, #c8a951);
  animation: kwSpin 0.7s linear infinite;
}
@keyframes kwAttachFade {
  from {
    opacity: 0;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes kwSpin {
  to {
    transform: rotate(360deg);
  }
}

/* Lightbox — full-screen modal that shows the image at its natural size.
   Tap the backdrop, the close button, or press Escape to dismiss. */
.kw-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(15, 17, 12, 0.86);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: kwFadeIn 160ms ease-out;
}
.kw-lightbox img {
  max-width: min(96vw, 1400px);
  max-height: 92vh;
  border-radius: 8px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
  cursor: zoom-out;
}
.kw-lightbox-close {
  position: absolute;
  top: 18px;
  right: 22px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 22px;
  cursor: pointer;
  transition: background 120ms;
}
.kw-lightbox-close:hover {
  background: rgba(255, 255, 255, 0.22);
}
@keyframes kwFadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* ── Attachment compose button ("+") ───────────────────────────────── */
.chat-attach-btn {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--olive, #4a5d23);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 120ms;
}
.chat-attach-btn:hover {
  background: rgba(74, 93, 35, 0.08);
}
.chat-attach-btn:focus-visible {
  outline: 2px solid var(--gold, #c8a951);
  outline-offset: 2px;
}

/* ── Starred badge on a bubble ─────────────────────────────────────── */
.msg-star-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 100px;
  background: rgba(200, 169, 81, 0.15);
  /* Phase L (a11y) — 10px gold text on pale gold tint (~1.4:1) fails
     hard. Olive on the same pale gold tint passes ~6:1. Badge stays
     visually warm via the gold background. */
  color: var(--olive);
  font-size: 10px;
  font-weight: 700;
}
.msg-star-badge svg {
  width: 10px;
  height: 10px;
}

/* Starred filter overlay — shows when the user opens the starred list. */
.chat-starred-panel {
  position: absolute;
  top: 60px;
  left: 12px;
  right: 12px;
  max-height: 70vh;
  overflow-y: auto;
  background: var(--cream, #faf7f2);
  border: 1px solid rgba(74, 93, 35, 0.18);
  border-radius: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
  z-index: 60;
  padding: 12px;
}
.chat-starred-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  font-family: var(--serif);
  font-size: 16px;
  color: var(--text-d, var(--text));
}
.chat-starred-panel-close {
  border: 0;
  background: transparent;
  font-size: 20px;
  cursor: pointer;
  color: var(--text-m);
}
.chat-starred-item {
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  border: 1px solid transparent;
}
.chat-starred-item:hover {
  background: rgba(74, 93, 35, 0.06);
  border-color: rgba(74, 93, 35, 0.12);
}
.chat-starred-item .csi-name {
  font-weight: 600;
  color: var(--olive);
  margin-right: 6px;
}
.chat-starred-empty {
  padding: 18px;
  text-align: center;
  color: var(--text-m);
  font-size: 13px;
}

/* ── Presence dot in chat header ───────────────────────────────────── */
.chat-presence-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #c0bfbc;
  margin-right: 5px;
  box-shadow: 0 0 0 0 rgba(74, 167, 91, 0);
}
.chat-presence-dot.is-online {
  background: #4aa75b;
  animation: kwPresencePulse 2.2s ease-out infinite;
}
@keyframes kwPresencePulse {
  0% {
    box-shadow: 0 0 0 0 rgba(74, 167, 91, 0.55);
  }
  70% {
    box-shadow: 0 0 0 7px rgba(74, 167, 91, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(74, 167, 91, 0);
  }
}

/* ════════════════════════════════════════════════════════════════════
   PUBLIC ROOM AVAILABILITY CALENDAR
   (CLAUDE_CODE_ROOM_AVAILABILITY_CALENDAR.md Task 2/3/4)
   Brand-token only. Reads the dates-only public projection. AA: don't
   rely on color alone — "Booked" is also surfaced via aria-label, a
   visible text pill, AND a diagonal stripe pattern, so colorblind users
   and screen readers both get a non-color signal.
   ════════════════════════════════════════════════════════════════════ */
.kw-avail-cal {
  background: var(--cream, #faf7f2);
  border: 1px solid rgba(74, 93, 35, 0.18);
  border-radius: 16px;
  padding: 16px 14px 12px;
  margin: 12px 0 18px;
  font-family: var(--sans);
}
.kw-avail-hdr {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  gap: 8px;
}
.kw-avail-title {
  font-family: var(--serif, Georgia, serif);
  font-size: 18px;
  color: var(--text-d, var(--text));
  font-weight: 500;
  letter-spacing: 0.3px;
  flex: 1;
  text-align: center;
}
.kw-avail-nav {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border: 1px solid rgba(74, 93, 35, 0.22);
  border-radius: 50%;
  background: transparent;
  color: var(--olive, #4a5d23);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition:
    background 120ms,
    color 120ms;
}
.kw-avail-nav:hover:not(:disabled) {
  background: rgba(74, 93, 35, 0.1);
}
.kw-avail-nav:disabled {
  opacity: 0.32;
  cursor: not-allowed;
}
.kw-avail-nav:focus-visible {
  outline: 2px solid var(--gold, #c8a951);
  outline-offset: 2px;
}
.kw-avail-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  margin-bottom: 4px;
}
.kw-avail-weekday {
  text-align: center;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  color: var(--text-m, #8a9182);
  text-transform: uppercase;
  padding: 4px 0;
}
.kw-avail-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.kw-avail-blank {
  visibility: hidden;
}
.kw-avail-day {
  position: relative;
  aspect-ratio: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #fff;
  border: 1px solid rgba(74, 93, 35, 0.1);
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-d, var(--text));
  font-weight: 500;
  user-select: none;
}
.kw-avail-num {
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.kw-avail-day.is-past {
  background: transparent;
  color: rgba(138, 145, 130, 0.55);
  border-color: transparent;
}
.kw-avail-day.is-today {
  border: 2px solid var(--gold, #c8a951);
  font-weight: 700;
}
.kw-avail-day.is-blocked {
  /* AA — color + pattern + label. Background is muted olive; a diagonal
     stripe pattern overlays as a non-color cue; the visible "Booked"
     label and the aria-label complete the trio. */
  background-color: rgba(74, 93, 35, 0.16);
  background-image: repeating-linear-gradient(
    -45deg,
    rgba(74, 93, 35, 0.18) 0px,
    rgba(74, 93, 35, 0.18) 4px,
    transparent 4px,
    transparent 8px
  );
  color: var(--olive, #4a5d23);
  border-color: rgba(74, 93, 35, 0.3);
  cursor: not-allowed;
}
.kw-avail-day.is-blocked .kw-avail-num {
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  opacity: 0.7;
}
.kw-avail-label {
  position: absolute;
  bottom: 3px;
  left: 4px;
  right: 4px;
  text-align: center;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--olive, #4a5d23);
  line-height: 1;
}
.kw-avail-day.is-selected {
  background: rgba(74, 93, 35, 0.85);
  color: #fff;
  border-color: var(--olive, #4a5d23);
}
.kw-avail-day.is-sel-start {
  background: var(--olive, #4a5d23);
}
.kw-avail-day[role="button"] {
  cursor: pointer;
  transition:
    background 120ms,
    transform 120ms;
}
.kw-avail-day[role="button"]:hover {
  background: rgba(200, 169, 81, 0.12);
}
.kw-avail-day[role="button"]:focus-visible {
  outline: 2px solid var(--gold, #c8a951);
  outline-offset: 2px;
}

/* Legend */
.kw-avail-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin-top: 14px;
  padding-top: 10px;
  border-top: 1px solid rgba(74, 93, 35, 0.1);
  font-size: 11px;
  color: var(--text-m, #8a9182);
}
.kw-avail-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.kw-avail-legend-sw {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  border: 1px solid rgba(74, 93, 35, 0.18);
}
.kw-avail-legend-sw.is-available {
  background: #fff;
}
.kw-avail-legend-sw.is-blocked {
  background-color: rgba(74, 93, 35, 0.16);
  background-image: repeating-linear-gradient(
    -45deg,
    rgba(74, 93, 35, 0.3) 0px,
    rgba(74, 93, 35, 0.3) 2px,
    transparent 2px,
    transparent 4px
  );
}
.kw-avail-legend-sw.is-today {
  background: #fff;
  border: 2px solid var(--gold, #c8a951);
}

.kw-avail-hint {
  margin-top: 12px;
  padding: 8px 12px;
  background: rgba(200, 169, 81, 0.1);
  border: 1px solid rgba(200, 169, 81, 0.3);
  border-radius: 10px;
  font-size: 12px;
  text-align: center;
  color: var(--text-d, var(--text));
  font-weight: 500;
}

/* Reduced motion — strip transitions; the calendar still works without them. */
@media (prefers-reduced-motion: reduce) {
  .kw-avail-nav,
  .kw-avail-day[role="button"] {
    transition: none;
  }
}

/* Mobile sizing — the calendar lives in the room-detail sidebar which
   collapses to full width below ~860px. Keep cells comfortable for thumbs. */
@media (max-width: 600px) {
  .kw-avail-cal {
    padding: 14px 10px 10px;
  }
  .kw-avail-day {
    font-size: 12px;
    border-radius: 6px;
  }
  .kw-avail-label {
    font-size: 7px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   WAVE 2 — Custom date-range picker (selectMode). Olive carries
   selection; gold stays accent-only (today ring, status). Everything
   here is scoped to .kw-avail-pick / .kw-sheet so the read-only
   calendar is untouched. Spec: 2026-06-01-wave2-date-range-calendar.
   ═══════════════════════════════════════════════════════════════════ */
.kw-avail-cal {
  --range: rgba(74, 93, 35, 0.16); /* committed in-range band */
  --range-soft: rgba(74, 93, 35, 0.09); /* desktop hover preview */
}

/* Scoped status live-region — the ONLY live region in selectMode. */
.kw-avail-status {
  font-size: 12px;
  line-height: 1.35;
  font-weight: 600;
  color: var(--olive, #4a5d23);
  text-align: center;
  min-height: 17px;
  margin: -2px 0 10px;
}
.kw-avail-status:empty {
  display: none;
}

/* Multi-month container — two side-by-side on a wide column, auto-stacking
   to vertical when it can't hold them (spec §7). */
.kw-avail-months {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 22px;
  justify-content: center;
}
.kw-avail-months .kw-avail-month {
  flex: 1 1 280px;
}
.kw-avail-monthlabel {
  font-family: var(--serif, Georgia, serif);
  font-size: 15px;
  font-weight: 500;
  color: var(--text-d, var(--text));
  text-align: center;
  margin-bottom: 8px;
}

/* Hard min cell width on real desktops so two months never crush a cell
   below the comfortable floor. Mobile keeps repeat(7,1fr) to fit 320px with
   zero horizontal overflow (the sheet is the touch surface there). */
@media (min-width: 769px) {
  .kw-avail-pick .kw-avail-grid {
    grid-template-columns: repeat(7, minmax(40px, 1fr));
  }
}
/* Seven columns can't be 44px WIDE at 320px (no date grid can), so on touch we
   meet the 44px tap target on the vertical axis instead: taller cells, ~40px
   wide. This is the hit-area padding the spec calls for on coarse pointers. */
@media (pointer: coarse) {
  .kw-avail-pick .kw-avail-day {
    min-height: 44px;
  }
}

/* Phase 3 (a11y) — 44px touch-target floor for secondary controls that render
   below it on fine pointers. COARSE (touch) pointers only, so desktop sizing is
   untouched. Buttons centre their own label, so growing them is invisible apart
   from a taller tap zone. The review dots can't each get a 44px-WIDE target in
   one row of 11 on a 320px screen (would overflow), so — like the date-picker
   cells above — they meet 44px on the VERTICAL axis via transparent padding,
   with background-clip keeping the painted dot its original 8px size; horizontal
   padding is kept small (4px) so 11 dots stay well under 320px wide. */
@media (pointer: coarse) {
  .rc-btn {
    padding-block: 14px; /* ~36px tall -> 44px; label stays centred */
  }
  .map-btn {
    min-height: 44px; /* already inline-flex + align-items:center */
  }
  .ft-social {
    min-width: 44px;
    min-height: 44px; /* grid place-items:center keeps the icon centred */
  }
  .rev-dot,
  .rev-dot.active {
    box-sizing: content-box; /* make the padding math width-independent */
    padding: 18px 4px; /* 8px dot -> ~16x44px tap zone */
    background-clip: content-box; /* paint only the dot, not the padding */
  }
}

/* Selectable cells: pointer, olive hover (NOT the legacy gold), press feedback. */
.kw-avail-pick .kw-avail-day[role="gridcell"]:not([aria-disabled="true"]) {
  cursor: pointer;
  transition:
    background 120ms,
    transform 90ms;
}
.kw-avail-pick
  .kw-avail-day[role="gridcell"]:not([aria-disabled="true"]):hover {
  background: rgba(74, 93, 35, 0.08);
}
.kw-avail-pick
  .kw-avail-day[role="gridcell"]:not([aria-disabled="true"]):active {
  background: rgba(74, 93, 35, 0.14);
  transform: scale(0.95);
}

/* In-range band — soft olive, DARK text, continuous ribbon. REDEFINES the
   dormant .is-selected (was opaque .85). Interior cells drop their border +
   radius and bridge the 4px grid gap with a same-color side shadow. */
.kw-avail-day.is-selected {
  background: var(--range);
  color: var(--text-d, var(--text));
  border-color: transparent;
  border-radius: 0;
  box-shadow:
    -4px 0 0 0 var(--range),
    4px 0 0 0 var(--range);
}
/* Anchors (check-in + check-out) — solid olive, white bold, 7.29:1 AAA.
   Round only the outer corner so the run reads as one ribbon. */
.kw-avail-day.is-sel-start,
.kw-avail-day.is-sel-end {
  background: var(--olive, #4a5d23);
  color: #fff;
  font-weight: 700;
  border-color: var(--olive, #4a5d23);
  box-shadow: none;
}
.kw-avail-day.is-sel-start {
  border-radius: 8px 0 0 8px;
}
.kw-avail-day.is-sel-end {
  border-radius: 0 8px 8px 0;
}

/* Desktop hover preview — clearly lighter than the committed band. */
.kw-avail-day.is-preview {
  background: var(--range-soft);
  border-color: transparent;
  border-radius: 0;
  box-shadow:
    -4px 0 0 0 var(--range-soft),
    4px 0 0 0 var(--range-soft);
}
.kw-avail-day.is-preview-end {
  box-shadow: inset 0 0 0 2px rgba(74, 93, 35, 0.5);
  border-radius: 8px;
}

/* Today — gold ring (existing) PLUS a small olive dot. The gold ring alone is
   2.27:1, below the 3:1 non-text floor, so the dot is the real cue (§5). */
.kw-avail-dot {
  position: absolute;
  bottom: 5px;
  left: 50%;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
  background: var(--olive, #4a5d23);
}
.kw-avail-day.is-sel-start .kw-avail-dot,
.kw-avail-day.is-sel-end .kw-avail-dot {
  background: #fff;
}

/* Dual focus ring — white halo + olive ring reads on white cells AND on the
   olive anchors (gold-on-olive fails). Not gold. */
.kw-avail-pick .kw-avail-day[role="gridcell"]:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px #fff,
    0 0 0 4px var(--olive, #4a5d23);
  position: relative;
  z-index: 2;
}

/* Beyond the booking horizon — muted + inert (mirrors past). */
.kw-avail-day.is-beyond {
  background: transparent;
  color: rgba(138, 145, 130, 0.5);
  border-color: transparent;
}

/* availability-load-failed hint reuses the gold hint chrome. */
.kw-avail-availerr {
  color: var(--text-d, var(--text));
}

/* ── Wave 2 mobile bottom-sheet ─────────────────────────────────── */
.kw-sheet-back {
  position: fixed;
  inset: 0;
  z-index: 500; /* above Book bar (300), below lightbox (600) */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(28, 25, 20, 0);
  transition: background 280ms cubic-bezier(0.32, 0.72, 0, 1);
}
.kw-sheet-back.is-open {
  background: rgba(28, 25, 20, 0.5);
}
.kw-sheet {
  width: 100%;
  max-width: 520px;
  max-height: 92vh;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  background: var(--cream, #faf7f2);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.22);
  /* Exit: ease-in, accelerate away (~200ms). */
  transform: translateY(100%);
  transition: transform 200ms cubic-bezier(0.4, 0, 1, 1);
  overflow: hidden;
}
.kw-sheet-back.is-open .kw-sheet {
  transform: translateY(0);
  /* Enter: ease-out (~280ms). */
  transition: transform 280ms cubic-bezier(0.32, 0.72, 0, 1);
}
.kw-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px 4px;
  flex-shrink: 0;
}
.kw-sheet-title {
  font-family: var(--serif, Georgia, serif);
  font-size: 19px;
  font-weight: 500;
  color: var(--text-d, var(--text));
}
.kw-sheet-x {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border: none;
  border-radius: 50%;
  background: rgba(74, 93, 35, 0.08);
  color: var(--olive, #4a5d23);
  font-size: 15px;
  cursor: pointer;
  transition: transform 90ms ease;
}
.kw-sheet-x:active {
  transform: scale(0.95);
}
.kw-sheet-x:focus-visible {
  outline: 2px solid var(--olive, #4a5d23);
  outline-offset: 2px;
}
#kwPickerSheetCal {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#kwPickerSheetCal.kw-avail-cal {
  border: none;
  background: transparent;
  margin: 0;
  padding: 4px 14px 10px;
}
.kw-sheet-foot {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
  padding: 12px 16px;
  /* Safe-area aware so the sticky Confirm clears the home indicator (§8). */
  padding-bottom: max(14px, env(safe-area-inset-bottom));
  border-top: 1px solid rgba(74, 93, 35, 0.12);
  background: var(--cream, #faf7f2);
}
.kw-sheet-btn {
  min-height: 48px; /* >=44px touch target */
  border-radius: 12px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition:
    background-color 140ms ease,
    transform 90ms ease;
}
.kw-sheet-btn:active {
  transform: scale(0.97);
}
.kw-sheet-btn:focus-visible {
  outline: 2px solid var(--olive, #4a5d23);
  outline-offset: 2px;
}
.kw-sheet-clear {
  flex: 0 0 auto;
  padding: 0 22px;
  background: transparent;
  color: var(--olive, #4a5d23);
  border: 1.5px solid rgba(74, 93, 35, 0.3);
}
.kw-sheet-confirm {
  flex: 1 1 auto;
  border: none;
  /* Disabled state: dark olive on a light tint (>=4.5:1), never white-on-
     translucent-olive (which would fall under AA). */
  background: rgba(74, 93, 35, 0.22);
  color: #33401a;
}
.kw-sheet-confirm.is-ready {
  background: var(--olive, #4a5d23);
  color: #fff;
}
.kw-sheet-confirm[aria-disabled="true"] {
  cursor: not-allowed;
}

/* Hide the bottom-corner floaters under ANY modal (incl. the picker sheet) so
   they can't overlap the sticky Confirm button or tap through it (§8). */
body.kw-modal-open .kw-install-bubble,
body.kw-modal-open .btt {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Reduced motion: sheet appears in place (no translate), opacity-only fade;
   no press scaling anywhere. */
@media (prefers-reduced-motion: reduce) {
  .kw-sheet,
  .kw-sheet-back.is-open .kw-sheet {
    transform: none;
    transition: opacity 120ms linear;
  }
  .kw-sheet {
    opacity: 0;
  }
  .kw-sheet-back.is-open .kw-sheet {
    opacity: 1;
  }
  .kw-sheet-back {
    transition: background 120ms linear;
  }
  .kw-avail-pick .kw-avail-day[role="gridcell"]:active,
  .kw-sheet-btn:active,
  .kw-sheet-x:active {
    transform: none;
  }
}

/* ── All-rooms availability search (Task 4) ─────────────────────── */
.kw-avail-search {
  background: var(--cream, #faf7f2);
  border: 1px solid rgba(74, 93, 35, 0.18);
  border-radius: 14px;
  padding: 14px 16px;
  margin: 8px 0 28px;
}
.kw-avail-search-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
}
.kw-avail-search-field {
  flex: 1 1 140px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.kw-avail-search-lbl {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-m, #8a9182);
}
.kw-avail-search-field input[type="date"] {
  padding: 10px 12px;
  border: 1.5px solid rgba(74, 93, 35, 0.2);
  border-radius: 10px;
  /* 16px (NOT 14px) is mandatory on the booking path: iOS Safari auto-zooms
     the viewport whenever a focused <input> has font-size < 16px, which yanks
     a guest mid-search. min-height 44px meets the booking-critical touch
     target (WCAG 2.5.5 / Apple HIG) and matches the 44px search buttons. */
  font-size: 16px;
  min-height: 44px;
  font-family: var(--sans);
  background: #fff;
  color: var(--text-d, var(--text));
}
.kw-avail-search-field input[type="date"]:focus-visible {
  outline: 2px solid var(--gold, #c8a951);
  outline-offset: 1px;
  border-color: var(--olive, #4a5d23);
}
.kw-avail-search-btn,
.kw-avail-search-clear {
  flex-shrink: 0;
  /* 44px (was 42px) matches the date inputs' new min-height and the
     booking-critical touch-target floor. */
  height: 44px;
  padding: 0 18px;
  border-radius: 10px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition:
    background 140ms,
    border-color 140ms;
}
.kw-avail-search-btn {
  background: var(--olive, #4a5d23);
  border: 1px solid var(--olive, #4a5d23);
  color: #fff;
}
.kw-avail-search-btn:hover {
  background: #3a4a1c;
  /* Wave 3 (golden thread): gold rim on hover — the sun-rim language on the
     booking path's primary search action. */
  border-color: rgba(200, 169, 81, 0.6);
}
/* Wave 3 (golden thread + a11y): explicit gold focus rings on the search
   controls, matching the date inputs' existing gold focus-visible ring. */
.kw-avail-search-btn:focus-visible,
.kw-avail-search-clear:focus-visible {
  outline: 2px solid var(--gold, #c8a951);
  outline-offset: 2px;
}
.kw-avail-search-btn svg {
  width: 16px;
  height: 16px;
}
.kw-avail-search-clear {
  background: transparent;
  border: 1px solid rgba(74, 93, 35, 0.22);
  color: var(--text-m, #8a9182);
}
.kw-avail-search-clear:hover {
  border-color: var(--olive, #4a5d23);
  color: var(--olive, #4a5d23);
}
.kw-avail-search-result {
  margin-top: 10px;
  font-size: 13px;
  color: var(--text-d, var(--text));
  min-height: 1.2em;
}
.rc.is-hidden-by-avail {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  .kw-avail-search-btn,
  .kw-avail-search-clear {
    transition: none;
  }
}

/* ── Admin "All Bookings" pill subtypes (Task 3) ── */
.pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 100px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2px;
  line-height: 1.3;
}
.pill-olive {
  background: rgba(74, 93, 35, 0.12);
  color: var(--olive);
  border: 1px solid rgba(74, 93, 35, 0.25);
}
.pill-gold {
  background: rgba(200, 169, 81, 0.16);
  color: #9a7d2e;
  border: 1px solid rgba(200, 169, 81, 0.35);
}
.pill-pending {
  background: rgba(217, 119, 6, 0.1);
  color: #d97706;
  border: 1px solid rgba(217, 119, 6, 0.3);
}
.pill-danger {
  background: rgba(220, 38, 38, 0.1);
  color: #dc2626;
  border: 1px solid rgba(220, 38, 38, 0.3);
}
.pill-sub {
  display: block;
  margin-top: 2px;
  font-family: var(--sans);
  font-size: 10.5px;
  color: var(--text-m);
  letter-spacing: 0.1px;
}

/* ── Hold-countdown banner on pending Trips cards (Task 4a + 4d) ── */
.hold-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 12px 0 0;
  padding: 10px 14px;
  border-radius: var(--rs, 12px);
  background: rgba(200, 169, 81, 0.12);
  border: 1px solid rgba(200, 169, 81, 0.35);
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text-d, var(--text));
}
.hold-clock {
  flex-shrink: 0;
}
.hold-text {
  flex: 1;
  min-width: 0;
}
.hold-count {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.hold-pay {
  flex-shrink: 0;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 12px;
  color: #fff;
  background: var(--olive);
  border: none;
  padding: 7px 14px;
  border-radius: 100px;
  cursor: pointer;
  transition:
    background var(--t-fast, 140ms) ease,
    transform var(--t-fast, 140ms) ease;
}
.hold-pay:hover {
  background: #3d4f1d;
  transform: translateY(-1px);
}
.hold-pay:active {
  transform: translateY(0);
}
.hold-pay:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.hold-banner.is-expired {
  background: var(--olive-3, rgba(74, 93, 35, 0.06));
  border-color: var(--brd, #e6e3da);
  color: var(--text-m);
}

/* ── Trip-card payment lines (Task 4b/4c) ── */
.trip-pay-line {
  font-family: var(--sans);
  font-size: 13px;
  margin: 10px 0 0;
}
.trip-pay-deposit {
  color: #9a7d2e;
  font-weight: 600;
}
.trip-pay-full {
  color: var(--olive);
  font-weight: 600;
}
.trip-pay-balance {
  margin-top: 8px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13px;
  color: #fff;
  background: var(--olive);
  border: none;
  padding: 9px 16px;
  border-radius: 100px;
  cursor: pointer;
  transition: background var(--t-fast, 140ms) ease;
}
.trip-pay-balance:hover {
  background: #3d4f1d;
}
.trip-pay-balance:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .hold-pay:hover,
  .hold-pay:active {
    transform: none !important;
  }
}

/* ── Receipt — native print, no library (Task 5) ── */
#receiptPrintable {
  display: none;
}
.ticket-receipt-btn {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13px;
  color: var(--olive);
  background: transparent;
  border: 1.5px solid var(--olive);
  border-radius: 100px;
  padding: 9px 18px;
  cursor: pointer;
  margin-top: 8px;
  transition:
    background var(--t-fast, 140ms) ease,
    color var(--t-fast, 140ms) ease;
}
.ticket-receipt-btn:hover {
  background: var(--olive);
  color: #fff;
}
.ticket-receipt-btn:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

@media print {
  body.printing-receipt * {
    visibility: hidden !important;
  }
  body.printing-receipt #receiptPrintable,
  body.printing-receipt #receiptPrintable * {
    visibility: visible !important;
  }
  body.printing-receipt #receiptPrintable {
    display: block !important;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    padding: 40px;
    color: #1a1a1a;
    background: #fff;
  }
  .rcpt-brand {
    font-family: var(--serif);
    font-size: 26px;
    margin: 0 0 4px;
    color: var(--olive);
  }
  .rcpt-sub {
    font-family: var(--sans);
    font-size: 12px;
    color: #555;
    margin: 0 0 16px;
  }
  .rcpt-rule {
    border-top: 1px solid #c8a951;
    margin: 16px 0;
  }
  .rcpt-title {
    font-family: var(--sans);
    font-size: 13px;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #777;
    margin: 0 0 16px;
  }
  .rcpt-table {
    display: grid;
    gap: 8px;
    margin: 0 0 8px;
  }
  .rcpt-row,
  .rcpt-total {
    display: flex;
    justify-content: space-between;
    font-family: var(--sans);
    font-size: 14px;
  }
  .rcpt-k {
    color: #555;
  }
  .rcpt-v {
    color: #1a1a1a;
    font-weight: 600;
    text-align: right;
  }
  .rcpt-total {
    font-size: 18px;
    font-weight: 700;
    margin-top: 4px;
  }
  .rcpt-total .rcpt-v {
    color: var(--olive);
  }
  .rcpt-thanks {
    font-family: var(--sans);
    font-size: 13px;
    color: #555;
    margin-top: 24px;
    font-style: italic;
  }
  @page {
    margin: 1.5cm;
  }
}

/* ── CHAT NOTIFICATION BANNER ────── */
.chat-notif-banner {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  background: linear-gradient(135deg, var(--gold-light), #fff8e1);
  border: 1px solid rgba(200, 169, 81, 0.25);
  border-radius: var(--r);
  margin-bottom: 20px;
}
.chat-notif-icon {
  font-size: 28px;
  flex-shrink: 0;
}
.chat-notif-txt {
  flex: 1;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-s);
}
.chat-notif-txt strong {
  color: var(--text);
  font-size: 14px;
}
.chat-notif-txt span {
  font-size: 12px;
}
.chat-notif-btn {
  padding: 10px 20px;
  border-radius: var(--rs);
  background: var(--olive);
  color: #fff;
  border: none;
  font-weight: 700;
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
  transition: 0.2s var(--ease);
  flex-shrink: 0;
}
.chat-notif-btn:hover {
  background: var(--olive-60);
  transform: translateY(-1px);
}

/* ── GUEST FEATURED CHAT CARD ───── */
.chat-item-featured {
  background: var(--wh);
  border-radius: var(--rl);
  border: 1px solid var(--olive-10);
  cursor: pointer;
  transition: 0.35s var(--ease);
  overflow: hidden;
}
.chat-item-featured:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-m);
  transform: translateY(-3px);
}
.chat-item-top {
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 22px 22px 0;
}
.chat-item-body {
  padding: 14px 22px;
  font-size: 14px;
  color: var(--text-s);
  line-height: 1.6;
}
.chat-item-action {
  padding: 16px 22px;
  background: var(--olive-3);
  color: var(--olive);
  font-weight: 600;
  font-size: 14px;
  text-align: center;
  border-top: 1px solid var(--olive-10);
  transition: 0.2s;
}
.chat-item-featured:hover .chat-item-action {
  background: var(--olive);
  color: #fff;
}

/* ── IN-APP CHAT NOTIFICATION ───── */
.chat-inapp-notif {
  position: fixed;
  /* Phase B/4 — safe-area max() keeps the toast clear of the iOS
     notch when launched as a PWA, but stays at 16px in normal mode. */
  top: max(16px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%) translateY(-140px);
  z-index: 500;
  background: var(--wh);
  border-radius: var(--r);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.14),
    0 2px 8px rgba(74, 93, 35, 0.12);
  border: 1px solid var(--olive-10);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 380px;
  width: calc(100% - 32px);
  cursor: pointer;
  transition: transform 0.4s var(--spring);
  pointer-events: none;
}
.chat-inapp-notif.show {
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.cin-close {
  background: none;
  border: none;
  color: var(--text-m);
  font-size: 13px;
  cursor: pointer;
  padding: 4px;
  line-height: 1;
  flex-shrink: 0;
  border-radius: 50%;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
}
.cin-close:hover {
  background: var(--cream-2, #f0ece3);
}
.chat-inapp-notif .cin-av {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  flex-shrink: 0;
  color: #fff;
  font-family: var(--serif);
}
.chat-inapp-notif .cin-txt {
  flex: 1;
  min-width: 0;
}
.chat-inapp-notif .cin-name {
  font-weight: 700;
  font-size: 13px;
  margin-bottom: 1px;
}
.chat-inapp-notif .cin-msg {
  font-size: 12px;
  color: var(--text-s);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-m);
  font-size: 14px;
}

/* ── Typing indicator ─────────────────────────────────── */
.typing-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 2px 24px 10px;
}
.typing-bubble {
  display: flex;
  gap: 4px;
  align-items: center;
  background: var(--cream-2, #f0ece3);
  padding: 8px 12px;
  border-radius: 18px;
  border-bottom-left-radius: 4px;
}
.typing-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-m);
  animation: typingBounce 1.2s infinite ease-in-out;
  flex-shrink: 0;
}
.typing-dot:nth-child(2) {
  animation-delay: 0.2s;
}
.typing-dot:nth-child(3) {
  animation-delay: 0.4s;
}
@keyframes typingBounce {
  0%,
  60%,
  100% {
    transform: translateY(0);
    opacity: 0.4;
  }
  30% {
    transform: translateY(-5px);
    opacity: 1;
  }
}
.typing-label {
  font-size: 11px;
  color: var(--text-m);
  font-style: italic;
}

/* ── Mute button in chat header ───────────────────────── */
.chat-mute-btn {
  margin-left: auto;
  background: none;
  border: none;
  font-size: 16px;
  cursor: pointer;
  padding: 6px;
  border-radius: 8px;
  transition: background 0.2s;
  flex-shrink: 0;
  line-height: 1;
}
.chat-mute-btn:hover {
  background: var(--cream-2, #f0ece3);
}

/* ── Unread badge (red) on nav ────────────────────────── */
.nbadge-unread {
  background: #ef4444 !important;
  animation: badgePop 0.3s var(--spring) both;
}
@keyframes badgePop {
  0% {
    transform: scale(0);
  }
  70% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}
.role-toggle {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--olive-3);
  border-radius: var(--rs);
  margin-bottom: 20px;
  width: fit-content;
}
.role-toggle button {
  padding: 8px 20px;
  border-radius: 8px;
  border: none;
  font-size: 13px;
  font-weight: 500;
  background: none;
  color: var(--text-m);
  transition: 0.2s;
}
.role-toggle button.active {
  background: var(--olive);
  color: #fff;
  box-shadow: var(--sh-s);
}
.ph {
  background: linear-gradient(135deg, var(--olive-5), var(--warm));
  border-radius: var(--rxl);
  padding: 36px;
  display: flex;
  gap: 24px;
  align-items: center;
  margin-bottom: 36px;
  border: 1px solid var(--olive-10);
  flex-wrap: wrap;
}
.p-av {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-family: var(--serif);
  font-size: 32px;
  color: #fff;
  position: relative;
}
.p-av .bd {
  position: absolute;
  bottom: 2px;
  right: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #22c55e;
  border: 3px solid #fff;
}
.p-info {
  flex: 1;
  min-width: 0;
}
.p-nm {
  font-family: var(--serif);
  font-size: 26px;
  margin-bottom: 3px;
}
.p-em {
  color: var(--text-m);
  font-size: 13px;
  margin-bottom: 4px;
  word-break: break-word;
}
.edit-prof-btn {
  background: none;
  border: 1px solid var(--brd);
  border-radius: var(--rs);
  padding: 10px 18px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-s);
  transition: 0.2s;
  white-space: nowrap;
  cursor: pointer;
  margin-top: 8px;
}
.edit-prof-btn:hover,
.edit-prof-btn:active {
  border-color: var(--olive);
  color: var(--olive);
  background: var(--olive-3);
}
.pgrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
}
.pstit {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-m);
  letter-spacing: 2px;
  text-transform: uppercase;
  margin-bottom: 12px;
  padding-left: 4px;
}
.pmi {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  background: var(--wh);
  border-radius: var(--r);
  cursor: pointer;
  margin-bottom: 5px;
  border: 1px solid var(--brd-l);
  transition: 0.25s;
}
.pmi:hover {
  border-color: var(--olive-20);
  background: var(--olive-3);
  transform: translateX(3px);
}
.pmi-ic {
  width: 40px;
  height: 40px;
  border-radius: var(--rs);
  background: var(--olive-3);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  flex-shrink: 0;
}
.pmi-t {
  flex: 1;
}
.pmi-l {
  font-weight: 600;
  font-size: 13px;
}
.pmi-s {
  color: var(--text-m);
  font-size: 11px;
}
.pmi-ar {
  color: var(--text-m);
  transition: 0.2s;
  font-size: 14px;
}
.pmi:hover .pmi-ar {
  color: var(--olive);
  transform: translateX(3px);
}
.lout {
  width: 100%;
  padding: 14px;
  border-radius: var(--r);
  background: none;
  border: 1.5px solid #fca5a5;
  color: #dc2626;
  font-weight: 600;
  font-size: 13px;
  transition: 0.2s;
  margin-top: 12px;
}
.lout:hover {
  background: #fef2f2;
  border-color: #f87171;
}
.sb {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  border-radius: var(--rs);
  background: none;
  border: 1px solid var(--brd);
  color: var(--text-s);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 24px;
  transition: 0.2s;
}
.sb:hover {
  background: var(--olive-3);
  border-color: var(--olive-20);
  color: var(--olive);
}
.stl {
  font-family: var(--serif);
  font-size: 28px;
  margin-bottom: 28px;
}
.ic {
  background: var(--wh);
  padding: 24px;
  border-radius: var(--r);
  margin-bottom: 10px;
  border: 1px solid var(--brd-l);
  transition: 0.25s;
}
.ic:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
}
.ic-hd {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.ic-hd .ici {
  font-size: 22px;
}
.ic-hd h4 {
  font-family: var(--serif);
  font-size: 17px;
}
.ic-bd {
  color: var(--text-s);
  font-size: 13px;
  line-height: 1.8;
  white-space: pre-line;
}
.faq-i {
  background: var(--wh);
  border-radius: var(--r);
  margin-bottom: 6px;
  border: 1px solid var(--brd-l);
  overflow: hidden;
  transition: 0.3s var(--ease);
}
.faq-i.active {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
}
.faq-q {
  padding: 16px 20px;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: 0.2s;
}
.faq-q:hover {
  background: var(--olive-3);
}
.faq-q .faq-toggle {
  transition: transform 0.3s var(--ease);
  font-size: 18px;
  flex-shrink: 0;
}
.faq-i.active .faq-q .faq-toggle {
  transform: rotate(45deg);
}
.faq-a {
  max-height: 0;
  overflow: hidden;
  padding: 0 20px;
  color: var(--text-s);
  font-size: 13px;
  line-height: 1.7;
  transition:
    max-height 0.4s var(--ease),
    padding 0.4s var(--ease);
}
.faq-a.open {
  max-height: 300px;
  padding: 0 20px 16px;
}
.empty {
  text-align: center;
  padding: 80px 20px;
}
.empty-ic {
  font-size: 56px;
  margin-bottom: 16px;
  opacity: 0.3;
}
.empty h3 {
  font-family: var(--serif);
  font-size: 22px;
  margin-bottom: 6px;
}
.empty p {
  color: var(--text-m);
  font-size: 14px;
  max-width: 340px;
  margin: 0 auto 24px;
}
.toast {
  position: fixed;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: #fff;
  padding: 14px 28px;
  border-radius: var(--r);
  font-size: 13px;
  font-weight: 500;
  z-index: 400;
  box-shadow: var(--sh-l);
  /* Reveal via a STATIC visible resting state (.toast:not(.hidden) below) —
     deliberately NOT a CSS transition or one-shot animation. Two traps ruled
     those out: (1) the old `animation: fadeUp` had no fill-mode and its
     translateY fought the translateX(-50%) centering, and after a mid-action
     re-render (the auth-token refresh fired by updatePassword during Change
     Password) the recreated #toast never re-ran it and stayed at opacity:0 —
     the action succeeded but the user saw NO confirmation ("nothing happens");
     (2) a CSS transition cannot animate an element un-hiding from display:none
     (.hidden), so it would stick at opacity:0 as well. A static opacity flip is
     bulletproof. The exit (.toast.is-dismissing → kwToastDismiss) keeps its
     graceful fade-out. */
  opacity: 0;
}
.toast:not(.hidden) {
  opacity: 1;
}
.toast::before {
  content: "";
  width: 100%;
  height: 3px;
  background: var(--olive);
  position: absolute;
  bottom: 0;
  left: 0;
  border-radius: 0 0 var(--r) var(--r);
  /* Phase 11 A4: align with flash() auto-dismiss (3.5s, §11.4). Pre-Phase 10
     the timer was 2.5s and the bar matched; Phase 10 extended to 3.5s but
     this bar was left at 2.5s, draining 1s early. */
  animation: shrink 3.5s linear forwards;
}
.hidden {
  display: none !important;
}

/* ── EDIT PROFILE ────────────────────── */
.ep-avatar {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  font-family: var(--serif);
  font-size: 40px;
  color: #fff;
  position: relative;
  transition: 0.3s;
  overflow: hidden;
}
.ep-avatar:hover {
  opacity: 0.85;
}
.ep-photo-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 18px;
  border-radius: 100px;
  background: var(--olive-5);
  border: 1px solid var(--olive-10);
  color: var(--olive);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: 0.2s;
}
.ep-photo-btn:hover {
  background: var(--olive-10);
}

/* ── SAVED DOCUMENTS ────────────────── */
.doc-card {
  background: var(--wh);
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  overflow: hidden;
  margin-bottom: 12px;
  transition: 0.25s;
}
.doc-card:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
}
.doc-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px;
}
.doc-card-info {
  display: flex;
  align-items: center;
  gap: 12px;
}
.doc-card-icon {
  font-size: 24px;
  flex-shrink: 0;
}
.doc-card-name {
  font-weight: 700;
  font-size: 14px;
}
.doc-card-meta {
  font-size: 12px;
  color: var(--text-m);
  margin-top: 1px;
}
.doc-card-photo {
  position: relative;
  cursor: pointer;
  border-top: 1px solid var(--brd-l);
}
.doc-card-photo img {
  width: 100%;
  height: 180px;
  object-fit: cover;
  display: block;
  transition: 0.2s;
}
.doc-card-photo:hover img {
  opacity: 0.9;
}
.doc-card-photo-label {
  position: absolute;
  bottom: 8px;
  left: 8px;
  padding: 4px 10px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 500;
}
.doc-card-nophoto {
  padding: 12px 18px;
  font-size: 12px;
  color: var(--text-m);
  border-top: 1px solid var(--brd-l);
  background: var(--olive-3);
}

.doc-upload-area {
  position: relative;
}
.doc-upload-btn {
  display: block;
  cursor: pointer;
  transition: 0.2s;
}
.doc-upload-inner {
  border: 2px dashed var(--olive-20);
  border-radius: var(--r);
  padding: 32px 20px;
  text-align: center;
  transition: 0.2s;
  background: var(--olive-3);
}
.doc-upload-btn:hover .doc-upload-inner {
  border-color: var(--olive);
  background: var(--olive-5);
}
.doc-upload-preview {
  position: relative;
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--brd-l);
}
.doc-upload-preview img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  display: block;
}

/* ── TOGGLE SWITCH ───────────────────── */
.pref-toggle {
  width: 48px;
  height: 28px;
  border-radius: 14px;
  background: var(--brd);
  position: relative;
  transition: 0.3s var(--ease);
  cursor: pointer;
  flex-shrink: 0;
}
.pref-toggle.on {
  background: var(--olive);
}
.pref-knob {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  position: absolute;
  top: 3px;
  left: 3px;
  transition: 0.3s var(--ease);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
.pref-toggle.on .pref-knob {
  left: 23px;
}

/* ── ADMIN USER CARDS ────────────────── */
.adm-users-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.adm-user-mini {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--wh);
  padding: 14px 18px;
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  transition: 0.2s;
}
.adm-user-mini:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
}
.adm-user-mini-av {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 17px;
  color: #fff;
  flex-shrink: 0;
}
.adm-user-mini-info {
  flex: 1;
  min-width: 0;
}
.adm-user-mini-name {
  font-weight: 700;
  font-size: 14px;
  margin-bottom: 1px;
}
.adm-user-mini-detail {
  font-size: 12px;
  color: var(--text-m);
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-word;
}

.adm-user-card {
  background: var(--wh);
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  padding: 20px;
  margin-bottom: 10px;
  transition: 0.25s;
}
.adm-user-card:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
}
.adm-user-top {
  display: flex;
  align-items: center;
  gap: 14px;
}
.adm-role-btn {
  margin-left: auto;
  flex-shrink: 0;
  padding: 5px 14px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  border: none;
  transition: 0.2s;
  letter-spacing: 0.3px;
}
.adm-role-btn.promote {
  background: var(--olive-10);
  color: var(--olive);
}
.adm-role-btn.promote:hover {
  background: var(--olive);
  color: #fff;
}
.adm-role-btn.demote {
  background: #fee2e2;
  color: #dc2626;
}
.adm-role-btn.demote:hover {
  background: #dc2626;
  color: #fff;
}
.adm-user-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--olive);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-size: 20px;
  color: #fff;
  flex-shrink: 0;
  overflow: hidden;
}
.adm-user-info {
  flex: 1;
  min-width: 0;
}
.adm-user-name {
  font-weight: 700;
  font-size: 15px;
  margin-bottom: 2px;
}
.adm-user-meta {
  font-size: 12px;
  color: var(--text-m);
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: break-word;
}
.adm-user-prefs {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--brd-l);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.adm-prefs-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-m);
  margin-right: 4px;
}
.adm-pref-tag {
  padding: 4px 10px;
  border-radius: 20px;
  background: var(--olive-3);
  border: 1px solid var(--olive-10);
  font-size: 11px;
  font-weight: 500;
  color: var(--olive);
}

/* ── ADMIN ROOM MANAGEMENT ──────────── */
.rm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 20px;
}
.rm-card {
  background: var(--wh);
  border-radius: var(--rl);
  overflow: hidden;
  border: 1px solid var(--brd-l);
  transition: 0.3s;
}
.rm-card:hover {
  box-shadow: var(--sh);
  border-color: var(--olive-20);
}
.rm-card-img {
  height: 180px;
  overflow: hidden;
  background: var(--olive-3);
  display: flex;
  align-items: center;
  justify-content: center;
}
.rm-card-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.rm-card-placeholder {
  font-size: 40px;
  color: var(--text-m);
  opacity: 0.3;
}
.rm-card-body {
  padding: 20px;
}
.rm-card-top {
  display: flex;
  justify-content: space-between;
  align-items: start;
  margin-bottom: 10px;
}
.rm-card-name {
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 600;
}
.rm-card-type {
  font-size: 12px;
  color: var(--text-m);
  margin-top: 2px;
}
.rm-card-price {
  font-weight: 700;
  font-size: 18px;
  color: var(--olive);
  white-space: nowrap;
}
.rm-card-price span {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-m);
}
.rm-card-amenities {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.rm-card-amenities span {
  padding: 4px 10px;
  background: var(--olive-3);
  border-radius: 20px;
  font-size: 11px;
  color: var(--text-s);
}
.rm-card-actions {
  display: flex;
  gap: 8px;
}

/* ── ACCEPTED PAYMENT METHODS (.pm-*) ──────────────────────────────
   On-brand chips shown on the homepage "Accepted Payment Methods"
   section AND (compact variant) inside the payment screen. Mirrors
   .rm-card's surface language (white card, --rl radius, --brd-l border,
   hover lift). Monogram TILES only — NO logo image files (brief
   constraint). Built from Kwarto's olive/gold tokens so it never looks
   like a generic payment-logo strip. */
.pm-card {
  /* Wave 5 (golden thread): relative+hidden exist solely to host and clip
     the ::after grain layer below. */
  position: relative;
  overflow: hidden;
  background: var(--wh);
  border: 1px solid var(--brd-l);
  border-radius: var(--rl);
  padding: 20px;
  transition: box-shadow 0.3s, border-color 0.3s;
}
.pm-card:hover {
  box-shadow: var(--sh);
  /* Wave 5 (golden thread): hover rim warms to gold, matching svc/rc/attr. */
  border-color: rgba(200, 169, 81, 0.5);
}
/* Wave 5 (golden thread): the hero/auth film-grain language at card scale —
   2% multiply, static, pointer-events:none. Visual-only; the payment copy,
   QR flow, and DOM are untouched. */
.pm-card::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.02;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
}
.pm-featured {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--brd-l);
}
.pm-featured-name {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  color: var(--text-d);
}
.pm-featured-desc {
  font-size: 13px;
  color: var(--text-m);
  margin-top: 3px;
  line-height: 1.45;
}
.pm-group {
  margin-top: 16px;
}
.pm-group-lbl {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-m);
  margin-bottom: 10px;
}
.pm-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.pm-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px 6px 6px;
  background: var(--olive-3);
  /* Wave 5 (golden thread): gold hairline on the method chips (decorative
     border only — chip text/bg unchanged, AA unaffected). */
  border: 1px solid rgba(200, 169, 81, 0.35);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-s);
  max-width: 100%;
}
/* Typographic monogram tile (NOT a logo). Olive on white keeps every
   brand visually consistent with Kwarto's palette. min-width + auto
   width lets multi-char monos ("BPI") expand without clipping. */
.pm-mono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  padding: 0 7px;
  border-radius: 8px;
  background: var(--olive);
  color: var(--wh);
  font-family: var(--sans);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: -0.01em;
  flex: none;
}
.pm-mono-qr {
  background: var(--gold-light);
  color: var(--olive);
  border: 1px solid var(--olive-20);
  padding: 5px;
  /* The QR glyph is an <svg width="100%" height="100%">. With only a definite
     HEIGHT + min-width, the tile's WIDTH is content-derived — and iOS Safari
     resolves the 100%-wide SVG to its ~300px replaced-element default. Because
     min-width is a FLOOR (never a ceiling), it can't cap that, so the tile
     balloons, crushes the sibling text, and forces horizontal overflow.
     aspect-ratio:1 derives a DEFINITE width from the definite height in every
     responsive state (46 / 40 / 24px), so the 100% SVG resolves against a real
     box and is capped in all engines. Preferred over hardcoded per-breakpoint
     widths, which would also mis-size the compact tile (its height cascades to
     24px via `.pm-strip .pm-mono`, not 26px). */
  aspect-ratio: 1;
}
.pm-mono-lg {
  min-width: 46px;
  height: 46px;
  border-radius: 12px;
  padding: 8px;
}
/* Compact strip — payment screen (under the trust rows). */
.pm-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid #ece9df;
}
.pm-strip-lead {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-m);
}
.pm-strip-lead .pm-mono-qr {
  min-width: 26px;
  height: 26px;
  padding: 4px;
}
.pm-strip-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 8px;
}
.pm-strip .pm-chip {
  padding: 4px 10px 4px 4px;
  font-size: 12px;
}
.pm-strip .pm-mono {
  min-width: 24px;
  height: 24px;
  font-size: 10px;
}
/* Step-2 Maya method-card monogram (fills the existing .co-method-icon). */
.co-mic-maya {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-family: var(--sans);
  font-weight: 800;
  color: var(--olive);
}
/* Step-3 hosted-checkout 50% / full toggle. */
.co-pay-plan {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 14px 0;
}
.co-pay-plan-opt {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  min-height: 44px;
  background: var(--wh);
  border: 1.5px solid var(--brd);
  border-radius: var(--rs);
  font-family: var(--sans);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.co-pay-plan-opt:hover {
  border-color: var(--olive-60);
}
.co-pay-plan-opt.selected {
  border-color: var(--olive);
  background: var(--olive-3);
}
.co-pay-plan-opt:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.co-pay-plan-lbl {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-m);
}
.co-pay-plan-amt {
  font-size: 16px;
  font-weight: 700;
  color: var(--olive);
}

/* Phones are ~85% of guests — tighten the chips + stack the toggle. */
@media (max-width: 599px) {
  .pm-card {
    padding: 16px;
    border-radius: var(--rs);
  }
  .pm-featured-name {
    font-size: 16px;
  }
  .pm-mono-lg {
    min-width: 40px;
    height: 40px;
  }
}
@media (max-width: 380px) {
  .co-pay-plan {
    grid-template-columns: 1fr;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pm-card,
  .co-pay-plan-opt {
    transition: none;
  }
}

.rm-editor-section {
  margin-bottom: 24px;
}
.rm-editor-label {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 10px;
  display: block;
}

/* ── FORM GRID HELPERS ─────────────── */
.form-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.form-grid-2-1 {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 16px;
}
.form-grid-4 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr 1fr;
  gap: 12px;
}
.form-row-flex {
  display: flex;
  gap: 12px;
}

.rm-photos-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.rm-photo-item {
  position: relative;
  width: 120px;
  height: 90px;
  border-radius: var(--rs);
  overflow: hidden;
  border: 1px solid var(--brd-l);
}
.rm-photo-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.rm-photo-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: none;
  font-size: 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rm-photo-cover {
  position: absolute;
  bottom: 4px;
  left: 4px;
  padding: 2px 8px;
  background: var(--olive);
  color: #fff;
  border-radius: 6px;
  font-size: 9px;
  font-weight: 700;
}
.rm-photo-add {
  width: 120px;
  height: 90px;
  border-radius: var(--rs);
  border: 2px dashed var(--olive-20);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: 0.2s;
}
.rm-photo-add:hover {
  border-color: var(--olive);
  background: var(--olive-3);
}
.rm-photo-add-inner {
  text-align: center;
  font-size: 20px;
  color: var(--olive);
}
.rm-photo-add-inner span {
  font-size: 11px;
  display: block;
  margin-top: 2px;
}
.rm-manage-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}
.rm-photo-btns {
  display: none;
  gap: 8px;
  margin-top: 10px;
}
.rm-photo-mobile-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: 1;
  padding: 14px 16px;
  border-radius: var(--rs);
  background: var(--olive-5);
  border: 1.5px dashed var(--olive-20);
  color: var(--olive);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: 0.2s;
  font-family: var(--sans);
  text-align: center;
}
.rm-photo-mobile-btn:hover,
.rm-photo-mobile-btn:active {
  background: var(--olive-10);
  border-color: var(--olive);
}

.rm-amenities-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.rm-amenity-btn {
  padding: 7px 14px;
  border-radius: 100px;
  border: 1.5px solid var(--brd);
  background: none;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-s);
  cursor: pointer;
  transition: 0.2s;
}
.rm-amenity-btn:hover {
  border-color: var(--olive-20);
  background: var(--olive-3);
}
.rm-amenity-btn.active {
  background: var(--olive);
  color: #fff;
  border-color: var(--olive);
}

/* ── ADMIN DASHBOARD ────────────────── */
.adm-stat {
  background: var(--wh);
  padding: 28px 24px;
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  text-align: center;
  transition: 0.25s;
}
.adm-stat:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
}
.adm-stat-num {
  font-family: var(--serif);
  font-size: 36px;
  color: var(--olive);
  margin-bottom: 4px;
}
.adm-stat-label {
  font-size: 13px;
  color: var(--text-m);
  font-weight: 500;
}

.adm-table {
  background: var(--wh);
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  overflow-x: auto;
}
.adm-row {
  display: flex;
  border-bottom: 1px solid var(--brd-l);
  transition: 0.15s;
}
.adm-row:last-child {
  border-bottom: none;
}
.adm-row:hover:not(.adm-header) {
  background: var(--olive-3);
}
.adm-row.adm-header {
  background: var(--cream);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--text-m);
}
.adm-cell {
  flex: 1;
  padding: 14px 16px;
  font-size: 13px;
  min-width: 80px;
  word-break: break-word;
}
.adm-row.adm-header .adm-cell {
  padding: 12px 16px;
}

/* ── AVAILABILITY GRID ─────────────── */
.avail-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--wh);
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--brd-l);
  min-width: 700px;
}
.avail-table th,
.avail-table td {
  padding: 12px 10px;
  text-align: center;
  font-size: 12px;
  border: 1px solid var(--brd-l);
}
.avail-table th {
  background: var(--cream);
  font-weight: 700;
  color: var(--text-s);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-size: 10px;
  padding: 10px 8px;
}
.avail-table .avail-room-col {
  text-align: left;
  min-width: 140px;
  background: var(--cream);
  position: sticky;
  left: 0;
  z-index: 1;
}
.avail-table tbody .avail-room-col {
  background: var(--wh);
}
.avail-today {
  background: var(--olive-3) !important;
}
.avail-cell {
  min-width: 90px;
  transition: 0.15s;
}
.avail-cell:hover {
  background: var(--olive-3);
}
.avail-tag {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 10px;
  font-weight: 600;
}
.avail-tag.free {
  background: #f0fdf4;
  color: #16a34a;
}
.avail-tag.olive {
  background: var(--olive-5);
  color: var(--olive);
}
.avail-tag.gold {
  background: var(--gold-light);
  color: #92710a;
}
.avail-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  vertical-align: middle;
  margin-right: 4px;
}
/* ═══════════════════════════════════════════════════════════════════
   RESPONSIVE — Tablet
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
  .hero-overlay {
    padding: 60px clamp(16px, 4vw, 48px) 40px;
  }
  .det-lay {
    grid-template-columns: 1fr;
  }
  .bk {
    position: static;
  }
  .pgrid {
    grid-template-columns: 1fr;
  }
  .cta,
  .island-cta {
    text-align: center;
  }
  .ft-main {
    grid-template-columns: 1fr 1fr;
    gap: 36px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   RESPONSIVE — Mobile
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
  /* ── NAV ── */
  .nav {
    height: 60px;
    padding: 0 16px;
  }
  .nav.scr {
    height: 56px;
  }
  .nlinks,
  .nav .ncta {
    display: none;
  }
  .mtog {
    display: block;
    font-size: 24px;
  }
  .brand {
    font-size: 22px;
  }
  .mnav button {
    font-size: 17px;
    padding: 14px 28px;
    width: 200px;
  }

  /* ── CONTAINER ── */
  .ctn {
    padding: 0 16px;
  }
  .main {
    padding-bottom: 20px;
  }

  /* ── AUTH ── */
  .auth-page {
    padding: 16px;
  }
  .auth-card {
    max-width: 100%;
  }
  .auth-brand {
    margin-bottom: 24px;
  }
  .auth-brand .auth-icon {
    width: 56px;
    height: 56px;
    font-size: 24px;
    border-radius: 16px;
  }
  .auth-brand h1 {
    font-size: 24px;
  }
  .auth-form {
    padding: 24px 20px;
    border-radius: var(--r);
  }
  .auth-form h2 {
    font-size: 20px;
    margin-bottom: 20px;
  }
  .auth-field input,
  .auth-field select {
    padding: 12px 14px;
    font-size: 16px; /* >=16px so iOS Safari does not auto-zoom on focus */
  }
  .auth-submit {
    padding: 14px;
    font-size: 15px;
  }

  /* ── HERO ── */
  .hero-full {
    min-height: auto;
  }
  .hero-bg-art {
    position: absolute;
    inset: 0;
  }
  .hero-bg-art::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
      180deg,
      rgba(250, 249, 246, 0.6) 0%,
      rgba(250, 249, 246, 0.85) 40%,
      rgba(250, 249, 246, 0.75) 70%,
      rgba(250, 249, 246, 0.5) 100%
    );
    z-index: 1;
  }
  .hero-overlay {
    min-height: auto;
    padding: 90px 16px 40px;
    position: relative;
    z-index: 2;
  }
  .hero-full h1 {
    font-size: 28px;
    line-height: 1.15;
  }
  .hero-sub {
    font-size: 14px;
  }
  .hero-eye {
    font-size: 11px;
    padding: 6px 14px;
    background: rgba(255, 255, 255, 0.9);
  }
  .hero-loc {
    font-size: 13px;
    margin-bottom: 20px;
  }
  .hero-acts {
    flex-direction: column;
    gap: 10px;
    align-items: stretch;
  }
  .hero-acts .ncta,
  .hero-acts .det-back {
    width: 100%;
    text-align: center;
    justify-content: center;
    display: flex;
  }
  .hero-rating {
    width: fit-content;
    background: rgba(255, 255, 255, 0.9);
  }

  /* ── MARQUEE ── */
  .marq {
    padding: 10px 0;
    font-size: 11px;
  }

  /* ── SECTIONS ── */
  .sec {
    padding: 40px 0;
  }
  .sec-hd {
    margin-bottom: 28px;
  }
  .sec-hd h2 {
    font-size: 24px;
  }
  .sec-hd p {
    font-size: 13px;
  }

  /* ── ROOM CARDS ── */
  .rgrid {
    grid-template-columns: 1fr;
    gap: 18px;
  }
  .rc-img {
    height: 200px;
  }
  .rc-bod {
    padding: 18px;
  }
  .rc-nm {
    font-size: 17px;
  }
  .rc-pr {
    font-size: 18px;
  }

  /* ── ROOM DETAIL ── */
  .det {
    padding: 20px 0 40px;
  }
  .det-gal {
    grid-template-columns: 1fr;
    height: auto;
    border-radius: var(--r);
    gap: 4px;
  }
  .dg-main {
    height: 220px;
  }
  .dg-side {
    grid-template-columns: 1fr 1fr;
    gap: 4px;
  }
  .dg-side img {
    height: 110px;
  }
  .det-info h1 {
    font-size: 24px;
  }
  .det-meta {
    gap: 10px;
    margin-bottom: 18px;
  }
  .det-desc {
    font-size: 14px;
  }
  .am-list {
    gap: 6px;
  }
  .am-tag {
    font-size: 11px;
    padding: 6px 12px;
  }
  .bk {
    border-radius: var(--r);
    padding: 22px;
    margin-top: 20px;
  }
  .bk-pr {
    font-size: 24px;
  }
  .bk-note {
    font-size: 10px;
    padding: 8px;
  }

  /* ── ATTRACTIONS / SERVICES / REVIEWS ── */
  .attr-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .attr-card {
    padding: 16px;
    gap: 12px;
  }
  .attr-card::before {
    display: none;
  }
  .attr-icon {
    width: 44px;
    height: 44px;
    font-size: 22px;
    border-radius: 12px;
  }
  .attr-dist {
    font-size: 10px;
    padding: 2px 8px;
  }
  .svc-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .svc-card {
    padding: 18px;
    gap: 14px;
  }
  .svc-icon {
    width: 44px;
    height: 44px;
    font-size: 20px;
  }
  .svc-arrow {
    display: none;
  }
  .rev-grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .rev-card {
    padding: 22px 20px 20px;
  }
  .rev-card::before {
    display: none;
  }
  .rev-quote {
    font-size: 32px;
    margin-bottom: 4px;
  }
  .rev-text {
    font-size: 13px;
  }
  .rev-carousel .rev-card {
    flex: 0 0 280px;
  }
  .rev-nav {
    display: none;
  }
  /* ── WRITE REVIEW MOBILE ── */
  .write-rev-card {
    padding: 22px 18px;
  }
  .write-rev-header {
    gap: 12px;
    margin-bottom: 18px;
  }
  .write-rev-icon {
    width: 46px;
    height: 46px;
    font-size: 26px;
    border-radius: 12px;
  }
  .write-rev-title {
    font-size: 17px;
  }
  .wr-star {
    font-size: 30px;
  }
  .write-rev-textarea {
    min-height: 80px;
    font-size: 16px;
  }
  .write-rev-footer {
    flex-wrap: wrap;
    gap: 10px;
  }
  .write-rev-btn {
    width: 100%;
    text-align: center;
    padding: 14px;
  }
  /* ── COCONUT TREES MOBILE ── */
  .coco-tree {
    width: 100px;
  }
  .coco-left {
    left: -10px;
  }
  .coco-right {
    right: -10px;
  }

  /* ── STATS STRIP ── */
  .stats-strip {
    padding: 32px 0;
  }
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
  }
  .stat-item:nth-child(2)::after {
    display: none;
  }
  .stat-item:nth-child(3)::after,
  .stat-item:nth-child(4)::after {
    display: none;
  }
  .stat-num {
    font-size: 32px;
  }
  .stat-plus,
  .stat-slash {
    font-size: 16px;
  }
  .stat-label {
    font-size: 11px;
  }

  /* ── BACK TO TOP ── */
  .btt {
    bottom: 20px;
    right: 20px;
    width: 42px;
    height: 42px;
    font-size: 18px;
  }

  /* ── CTA BANNER ── */
  .island-cta-content {
    padding: 36px 20px 32px;
  }
  .island-cta-icon {
    font-size: 36px;
    margin-bottom: 12px;
  }
  .island-cta h2 {
    font-size: 22px;
  }
  .island-cta p {
    font-size: 13px;
    margin-bottom: 22px;
  }
  .island-cta-features {
    gap: 8px;
  }
  .island-feat {
    padding: 6px 12px;
    font-size: 12px;
  }
  .island-feat span {
    font-size: 14px;
  }
  .island-cta-btn {
    width: 100%;
    padding: 14px 24px;
    font-size: 15px;
  }
  .island-cta-note {
    font-size: 11px;
  }

  /* ── FOOTER ── */
  .ft-main {
    grid-template-columns: 1fr;
    gap: 32px;
    padding: 40px 0 32px;
  }
  .ft-brand {
    font-size: 24px;
  }
  .ft-desc {
    font-size: 13px;
    max-width: 100%;
  }
  .ft-links-col h3 {
    margin-bottom: 14px;
    padding-bottom: 10px;
  }
  .ft a {
    font-size: 13px;
    padding: 5px 0;
  }
  .ft-bot {
    flex-direction: column;
    gap: 6px;
    text-align: center;
  }

  /* ── PROFILE ── */
  .ph {
    flex-direction: column;
    text-align: center;
    padding: 24px 20px;
    gap: 12px;
    border-radius: var(--r);
  }
  .p-av {
    width: 70px;
    height: 70px;
    font-size: 28px;
    margin: 0 auto;
  }
  .p-info {
    width: 100%;
  }
  .p-nm {
    font-size: 22px;
  }
  .p-em {
    font-size: 12px;
    word-break: break-word;
  }
  .edit-prof-btn {
    width: 100%;
    text-align: center;
    padding: 12px;
    margin-top: 8px;
    display: block;
  }
  .pmi {
    padding: 12px 14px;
    gap: 12px;
  }
  .pmi-ic {
    width: 36px;
    height: 36px;
    font-size: 15px;
  }
  .pmi-l {
    font-size: 13px;
  }
  .stl {
    font-size: 24px;
    margin-bottom: 20px;
  }
  .lout {
    margin-top: 8px;
  }

  /* ── EDIT PROFILE ── */
  .ep-avatar {
    width: 80px;
    height: 80px;
    font-size: 32px;
  }

  /* ── CHAT ── */
  .chat-notif-banner {
    flex-direction: row;
    padding: 14px 16px;
    gap: 10px;
  }
  .chat-notif-icon {
    font-size: 24px;
  }
  .chat-notif-txt strong {
    font-size: 13px;
  }
  .chat-notif-btn {
    padding: 8px 16px;
    font-size: 12px;
  }
  .chat-item-top {
    padding: 18px 18px 0;
  }
  .chat-item-body {
    padding: 12px 18px;
    font-size: 13px;
  }
  .chat-item-action {
    padding: 14px 18px;
    font-size: 13px;
  }
  .chat-room {
    height: calc(100vh - 80px);
    height: calc(100dvh - 80px);
    border-radius: 0;
    border: none;
    box-shadow: none;
  }
  .chat-header {
    padding: 14px 16px;
    gap: 10px;
  }
  .chat-header img,
  .chat-av-initial {
    width: 36px;
    height: 36px;
    font-size: 15px;
  }
  .chat-header-info h3 {
    font-size: 15px;
  }
  .chat-messages {
    padding: 16px;
  }
  .chat-msg {
    max-width: 85%;
    padding: 10px 14px;
    font-size: 13px;
  }
  .chat-input-bar {
    padding: 12px 16px;
    padding-bottom: max(12px, env(safe-area-inset-bottom));
    gap: 8px;
    position: sticky;
    bottom: 0;
  }
  .chat-input-bar input {
    padding: 10px 14px;
    font-size: 16px;
  }
  .chat-input-bar button {
    width: 44px;
    height: 44px;
    font-size: 16px;
    min-width: 44px;
  }
  .chat-list {
    gap: 6px;
  }
  .chat-item {
    padding: 14px 16px;
    gap: 10px;
  }
  .chat-av,
  .chat-av-icon,
  .chat-av-initial {
    width: 40px;
    height: 40px;
    font-size: 18px;
  }

  /* ── TICKET MODAL ── */
  .tov {
    padding: 10px;
    align-items: flex-end;
  }
  .tkt {
    max-width: 100%;
    border-radius: var(--r) var(--r) 0 0;
    max-height: 90vh;
    overflow-y: auto;
  }
  .tkt-img {
    height: 140px;
  }
  .tkt-bod {
    padding: 22px 20px;
  }
  .tkt-bod h3 {
    font-size: 20px;
  }
  .tkt-ft {
    padding: 14px;
    font-size: 12px;
  }

  /* ── TRIPS ── */
  .rc[style*="max-width:800px"] .rc-img {
    height: 160px;
  }

  /* ── ADMIN TABS ── */
  .role-toggle {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap;
    gap: 2px;
    padding: 3px;
  }
  .role-toggle button {
    padding: 8px 14px;
    font-size: 11px;
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* ── ADMIN STATS ── */
  .adm-stat {
    padding: 20px 16px;
  }
  .adm-stat-num {
    font-size: 28px;
  }
  .adm-stat-label {
    font-size: 11px;
  }

  /* ── ADMIN TABLES ── */
  .adm-table {
    border-radius: var(--rs);
  }
  .adm-cell {
    padding: 10px 12px;
    font-size: 12px;
    min-width: 60px;
  }
  .adm-row.adm-header .adm-cell {
    padding: 10px 12px;
    font-size: 10px;
  }
  .adm-row {
    flex-wrap: wrap;
  }

  /* ── ADMIN USER CARDS ── */
  .adm-user-card {
    padding: 16px;
  }
  .adm-user-avatar {
    width: 40px;
    height: 40px;
    font-size: 16px;
  }
  .adm-user-name {
    font-size: 14px;
  }
  .adm-user-meta {
    font-size: 11px;
  }
  .adm-pref-tag {
    padding: 3px 8px;
    font-size: 10px;
  }
  .adm-user-mini {
    padding: 12px 14px;
    gap: 10px;
  }
  .adm-user-mini-av {
    width: 36px;
    height: 36px;
    font-size: 15px;
  }
  .adm-user-mini-name {
    font-size: 13px;
  }
  .adm-user-mini-detail {
    font-size: 11px;
  }

  /* ── ADMIN ROOM MANAGEMENT ── */
  .rm-manage-header {
    flex-direction: column;
    gap: 12px;
    align-items: stretch;
  }
  .rm-add-btn {
    width: 100%;
    text-align: center;
    padding: 14px;
    font-size: 15px;
  }
  .rm-grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .rm-card-img {
    height: 160px;
  }
  .rm-card-body {
    padding: 16px;
  }
  .rm-card-name {
    font-size: 16px;
  }
  .rm-card-actions {
    flex-direction: column;
    gap: 6px;
  }
  .rm-card-actions button {
    width: 100%;
    text-align: center;
    padding: 12px;
  }
  .rm-photos-grid {
    gap: 8px;
  }
  .rm-photo-item,
  .rm-photo-add {
    width: 100px;
    height: 80px;
  }
  .rm-photo-add-inner {
    font-size: 16px;
  }
  .rm-photo-btns {
    display: flex;
  }
  .rm-amenities-grid {
    gap: 4px;
  }
  .rm-amenity-btn {
    padding: 8px 14px;
    font-size: 12px;
  }
  .rm-editor-section {
    margin-bottom: 20px;
  }
  .rm-editor-label {
    font-size: 15px;
    margin-bottom: 12px;
  }

  /* ── ROOM EDITOR GRIDS ── */
  .form-grid-2,
  .form-grid-2-1,
  .form-grid-4 {
    grid-template-columns: 1fr;
  }
  .form-row-flex {
    flex-direction: column;
  }

  /* ── SUB PAGES ── */
  .ic {
    padding: 18px 16px;
  }
  .ic-hd h4 {
    font-size: 15px;
  }

  /* ── TOAST ── */
  .toast {
    left: 16px;
    right: 16px;
    transform: none;
    text-align: center;
    padding: 12px 20px;
    font-size: 12px;
    bottom: 16px;
    border-radius: var(--rs);
  }

  /* ── EMPTY STATES ── */
  .empty {
    padding: 50px 16px;
  }
  .empty-ic {
    font-size: 44px;
  }
  .empty h3 {
    font-size: 18px;
  }

  /* ── AVAILABILITY GRID ── */
  .avail-table {
    min-width: 600px;
  }
  .avail-table th,
  .avail-table td {
    padding: 8px 6px;
    font-size: 10px;
  }
  .avail-table .avail-room-col {
    min-width: 100px;
  }
  .avail-tag {
    padding: 2px 6px;
    font-size: 9px;
  }

  /* ── SAFE AREA (notched phones) ── */
  .nav {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }
  .chat-input-bar {
    padding-bottom: max(12px, env(safe-area-inset-bottom));
  }
  .mnav {
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .toast {
    bottom: max(16px, env(safe-area-inset-bottom));
  }

  /* ── MISC ── */
  .sb {
    padding: 8px 16px;
    font-size: 13px;
    margin-bottom: 18px;
  }
  .det-back {
    padding: 8px 16px;
    font-size: 13px;
  }
  .ncta {
    padding: 10px 20px;
    font-size: 13px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   RESPONSIVE — Small phones (375px and under)
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 380px) {
  .hero-full h1 {
    font-size: 24px;
  }
  .hero-overlay {
    padding: 80px 16px 32px;
  }
  .auth-form {
    padding: 20px 16px;
  }
  .auth-brand h1 {
    font-size: 22px;
  }
  .bk {
    padding: 18px;
  }
  .bk-pr {
    font-size: 22px;
  }
  .ph {
    padding: 20px 16px;
  }
  .p-nm {
    font-size: 20px;
  }
  .chat-msg {
    max-width: 90%;
  }
  .rm-photo-item,
  .rm-photo-add {
    width: 90px;
    height: 72px;
  }
  .role-toggle button {
    padding: 6px 10px;
    font-size: 10px;
  }
  .adm-stat-num {
    font-size: 24px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   PREMIUM ENHANCEMENTS — Added April 2026
   ═══════════════════════════════════════════════════════════════════ */

/* ── SKELETON LOADING ──────────────────────────────────────────── */
.skel {
  background: linear-gradient(90deg, #f0ece3 0%, #f6f2e9 50%, #f0ece3 100%);
  background-size: 200% 100%;
  animation: skelShimmer 1.4s infinite;
  border-radius: 8px;
  display: block;
}
@keyframes skelShimmer {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}
.skel-card {
  background: var(--wh);
  border-radius: var(--r);
  padding: 16px;
  box-shadow: var(--sh);
  overflow: hidden;
}
.skel-img {
  height: 200px;
  border-radius: 12px;
  margin-bottom: 14px;
}
.skel-line {
  height: 14px;
  margin-bottom: 8px;
  width: 100%;
}
.skel-line.w60 {
  width: 60%;
}
.skel-line.w40 {
  width: 40%;
}
.skel-line.w80 {
  width: 80%;
}

/* ── PAGE TRANSITIONS ──────────────────────────────────────────── */
.page-fade {
  animation: pageFade 0.35s var(--ease) both;
}
@keyframes pageFade {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ── FOOTER WHATSAPP LINK ─────────────────────────────────────── */
.ft-social-wa {
  color: #25d366 !important;
}
.ft-social-wa:hover {
  color: #1ea951 !important;
}
.ft-wa-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #25d366;
  text-decoration: none;
  font-weight: 600;
  transition: color 0.2s;
}
.ft-wa-link:hover {
  color: #1ea951;
}

/* ── STICKY MOBILE BOOK NOW BAR ───────────────────────────────── */
.sticky-book {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: #fff;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.08);
  z-index: 300;
  display: none;
  transform: translateY(100%);
  transition: transform 0.3s var(--spring);
  border-top: 1px solid var(--olive-10);
}
.sticky-book.show {
  transform: translateY(0);
}
.sticky-book-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 600px;
  margin: 0 auto;
}
.sticky-book-info {
  flex: 1;
  min-width: 0;
}
.sticky-book-price {
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 700;
  color: var(--olive);
  line-height: 1.1;
}
.sticky-book-lbl {
  font-size: 11px;
  color: var(--text-m);
}
.sticky-book-btn {
  background: var(--olive);
  color: #fff;
  border: none;
  padding: 12px 24px;
  border-radius: 100px;
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  font-family: var(--sans);
  letter-spacing: 0.3px;
  transition: 0.2s;
  flex-shrink: 0;
}
.sticky-book-btn:hover {
  background: var(--olive-dark, #3a4a1b);
  transform: scale(1.03);
}
@media (min-width: 900px) {
  .sticky-book {
    display: none !important;
  }
}

/* ── LIGHTBOX (Photo Gallery) ─────────────────────────────────── */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.93);
  z-index: 600;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  opacity: 0;
  transition: opacity 0.3s;
}
.lightbox.show {
  display: flex;
  opacity: 1;
  animation: fadeUp 0.3s var(--ease);
}
.lb-img {
  max-width: 94vw;
  max-height: 85vh;
  max-height: 85dvh;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  animation: lbZoom 0.35s var(--spring);
}
@keyframes lbZoom {
  from {
    transform: scale(0.9);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}
.lb-close,
.lb-nav {
  position: absolute;
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: none;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.25s var(--spring);
  border-radius: 50%;
}
.lb-close {
  top: 20px;
  right: 20px;
  width: 44px;
  height: 44px;
  font-size: 22px;
}
.lb-nav {
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  font-size: 24px;
}
.lb-nav.prev {
  left: 20px;
}
.lb-nav.next {
  right: 20px;
}
.lb-close:hover,
.lb-nav:hover {
  background: rgba(255, 255, 255, 0.25);
  transform: scale(1.1);
}
.lb-nav.prev:hover,
.lb-nav.next:hover {
  transform: translateY(-50%) scale(1.1);
}
.lb-counter {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  color: #fff;
  background: rgba(0, 0, 0, 0.5);
  padding: 6px 14px;
  border-radius: 20px;
  font-size: 13px;
  font-weight: 600;
}
.lb-thumbs {
  position: absolute;
  bottom: 60px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 6px;
  max-width: 90vw;
  overflow-x: auto;
  padding: 0 10px;
}
.lb-thumb {
  width: 48px;
  height: 48px;
  border-radius: 6px;
  cursor: pointer;
  opacity: 0.5;
  object-fit: cover;
  transition: 0.2s;
  flex-shrink: 0;
  border: 2px solid transparent;
}
.lb-thumb:hover {
  opacity: 0.8;
}
.lb-thumb.active {
  opacity: 1;
  border-color: #fff;
}

/* Room image click cue */
.dg-main,
.dg-side img {
  cursor: zoom-in;
  position: relative;
}
.dg-main::after {
  content: "🔍 Click to expand";
  position: absolute;
  bottom: 12px;
  right: 12px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  padding: 5px 12px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s;
}
.dg-main:hover::after {
  opacity: 1;
}

/* ── 404 PAGE ─────────────────────────────────────────────────── */
.page-404 {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px 20px;
}
.page-404-inner {
  max-width: 500px;
}
.page-404-num {
  font-family: var(--serif);
  font-size: 120px;
  font-weight: 700;
  background: linear-gradient(135deg, var(--olive) 0%, #6b8a3e 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  line-height: 1;
  margin-bottom: 12px;
  animation: fadeUp 0.6s var(--ease);
}
.page-404-title {
  font-family: var(--serif);
  font-size: 32px;
  font-weight: 600;
  margin-bottom: 12px;
}
.page-404-txt {
  color: var(--text-m);
  margin-bottom: 28px;
  font-size: 15px;
}

/* ── MICRO-ANIMATIONS ─────────────────────────────────────────── */
.rc {
  transition:
    transform 0.35s var(--ease),
    box-shadow 0.35s;
}
.rc:hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 40px rgba(74, 93, 35, 0.12);
}
.rc-img img {
  transition: transform 0.6s var(--ease);
}
.rc:hover .rc-img img {
  transform: scale(1.06);
}
.ncta,
.bk-go,
.rc-btn,
.chat-send-btn {
  transition:
    transform 0.2s var(--spring),
    box-shadow 0.2s,
    background 0.2s;
}
.ncta:hover:not(:disabled),
.rc-btn:hover,
.chat-send-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(74, 93, 35, 0.3);
}
.attr-card,
.svc-card {
  transition:
    transform 0.35s var(--ease),
    box-shadow 0.35s;
}
.attr-card:hover,
.svc-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 14px 30px rgba(74, 93, 35, 0.1);
}
button:active:not(:disabled) {
  transform: scale(0.97);
}

/* Scroll smooth */
html {
  scroll-behavior: smooth;
}

/* ── GOOGLE MAPS EMBED ────────────────────────────────────────── */
.map-section {
  /* Wave 2 (golden thread): translucent olive wash (was opaque --olive-3) so
     the kwGoldenHour page warming shows through — the section now rides the
     existing engine with zero JS. Pre-JS the body is cream, so the composite
     still reads as the familiar pale olive. */
  background: rgba(238, 243, 229, 0.55);
  padding: 60px 0;
}
.map-wrap {
  position: relative;
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
  border: 1px solid var(--olive-10);
  max-width: 1100px;
  margin: 0 auto;
}
.map-wrap iframe {
  display: block;
  width: 100%;
  height: 420px;
  border: 0;
}
.map-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 20px;
}
.map-btn {
  background: #fff;
  color: var(--olive);
  border: 1px solid var(--olive-10);
  padding: 10px 20px;
  border-radius: 100px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: 0.2s;
  font-family: var(--sans);
}
.map-btn:hover {
  background: var(--olive);
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(74, 93, 35, 0.2);
}
@media (max-width: 600px) {
  .map-wrap iframe {
    height: 320px;
  }
}

/* ── REVIEW AVATARS ──────────────────────────────────────────── */
.rev-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--olive), #6b8a3e);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-weight: 700;
  font-size: 18px;
  flex-shrink: 0;
  margin-right: 12px;
  box-shadow: 0 2px 8px rgba(74, 93, 35, 0.2);
}
.rev-author {
  display: flex !important;
  align-items: center;
  gap: 0;
}
.rev-author .rev-author-txt {
  display: flex;
  flex-direction: column;
  text-align: left;
}

/* ── IMAGE LAZY LOADING (fade-in as it arrives) ────────────── */
img[loading="lazy"] {
  opacity: 0;
  transition: opacity 0.5s var(--ease);
}
img[loading="lazy"].loaded,
img[loading="lazy"][src] {
  opacity: 1;
}

/* ── AVAILABILITY BADGE ON DATE PICKER ──────────────────────── */
.bk-availability {
  margin-top: 10px;
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 12px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
  animation: fadeUp 0.3s var(--ease);
}
.bk-availability.avail {
  background: #dcfce7;
  color: #15803d;
}
.bk-availability.unavail {
  background: #fee2e2;
  color: #dc2626;
}
.bk-availability .dot-ind {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.bk-availability.avail .dot-ind {
  background: #22c55e;
  animation: avBlink 1.5s ease-in-out infinite;
}
.bk-availability.unavail .dot-ind {
  background: #ef4444;
}
@keyframes avBlink {
  50% {
    opacity: 0.4;
  }
}

/* ════════════════════════════════════════════════════════════════
   CHECKOUT — Professional multi-step booking flow
   ══════════════════════════════════════════════════════════════ */
.co-modal {
  position: fixed;
  inset: 0;
  background: rgba(20, 25, 18, 0.5);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  overflow: hidden;
  font-family: "Outfit", sans-serif;
}
.co-modal.show {
  opacity: 1;
  pointer-events: auto;
}
.co-sheet {
  background: #fff;
  width: 100%;
  max-width: 560px;
  max-height: 94vh;
  border-radius: 20px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: translateY(30px);
  transition: transform 0.35s cubic-bezier(0.2, 0.9, 0.25, 1);
  margin: 16px;
}
.co-modal.show .co-sheet {
  transform: translateY(0);
}

.co-sheet-head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border-bottom: 1px solid #f0eee8;
  background: #fff;
}
.co-back {
  width: 44px;
  height: 44px;
  border: none;
  background: #f5f2ec;
  border-radius: 50%;
  font-size: 18px;
  color: #4a5d23;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: all 0.2s;
  flex-shrink: 0;
}
.co-back:hover {
  background: #e8e2d5;
  transform: translateX(-2px);
}
.co-head-title {
  flex: 1;
  min-width: 0;
}
.co-head-ov {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: #4a5d23;
}
.co-head-stp {
  font-family: "Playfair Display", serif;
  font-size: 17px;
  font-weight: 600;
  color: #1a1a1a;
  margin-top: 1px;
}
.co-head-spacer {
  width: 40px;
  flex-shrink: 0;
}

.co-progress {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 20px 12px;
  background: linear-gradient(to bottom, #faf9f6, #fff);
  border-bottom: 1px solid #f0eee8;
}
.co-prog-step {
  display: flex;
  align-items: center;
  gap: 8px;
  opacity: 0.4;
  transition: opacity 0.25s;
  flex-shrink: 0;
}
.co-prog-step.active {
  opacity: 1;
}
.co-prog-dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #e8e2d5;
  color: #8a9182;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
  transition: all 0.3s;
}
.co-prog-step.active .co-prog-dot {
  background: #4a5d23;
  color: #fff;
  box-shadow: 0 0 0 4px rgba(74, 93, 35, 0.12);
}
.co-prog-step.done .co-prog-dot {
  background: #22c55e;
  color: #fff;
}
.co-prog-lbl {
  font-size: 12px;
  font-weight: 600;
  color: #5a5a5a;
  white-space: nowrap;
}
.co-prog-line {
  flex: 1;
  height: 2px;
  background: #e8e2d5;
  border-radius: 1px;
  min-width: 20px;
}

.co-hold {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 16px;
  background: #fef3c7;
  color: #92400e;
  font-size: 12px;
  border-bottom: 1px solid #fde68a;
}
.co-hold-ic {
  font-size: 14px;
}
.co-hold-time {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: #fff;
  padding: 2px 8px;
  border-radius: 6px;
  color: #4a5d23;
}
.co-hold.co-hold-expired {
  background: #fee2e2;
  color: #991b1b;
  border-color: #fecaca;
}

.co-sheet-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 22px 0;
  -webkit-overflow-scrolling: touch;
}

.co-section {
  padding-bottom: 22px;
  margin-bottom: 22px;
  border-bottom: 1px solid #f0eee8;
}
.co-section:last-of-type {
  border-bottom: none;
  margin-bottom: 0;
}
.co-h3 {
  font-family: "Playfair Display", serif;
  font-size: 18px;
  font-weight: 600;
  color: #1a1a1a;
  margin: 0 0 12px;
}
.co-lead {
  font-size: 13px;
  color: #5a5a5a;
  margin: 0 0 14px;
  line-height: 1.5;
}

.co-room-card {
  display: flex;
  gap: 14px;
  align-items: center;
  margin-bottom: 18px;
}
.co-room-img {
  width: 90px;
  height: 90px;
  border-radius: 12px;
  object-fit: cover;
  flex-shrink: 0;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.co-room-info {
  min-width: 0;
}
.co-room-name {
  font-family: "Playfair Display", serif;
  font-size: 17px;
  font-weight: 600;
  color: #1a1a1a;
  margin-bottom: 4px;
}
.co-room-meta {
  font-size: 12px;
  color: #8a9182;
}

.co-trip-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
  background: #faf9f6;
  border-radius: 14px;
  padding: 14px;
}
.co-trip-item {
  text-align: center;
  padding: 6px 4px;
}
.co-trip-item:not(:last-child) {
  border-right: 1px solid #e8e2d5;
}
.co-trip-lbl {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  color: #8a9182;
  text-transform: uppercase;
  margin-bottom: 4px;
}
.co-trip-val {
  font-size: 14px;
  font-weight: 600;
  color: #1a1a1a;
  line-height: 1.2;
}
.co-trip-sub {
  font-size: 10px;
  color: #8a9182;
  margin-top: 3px;
}

.co-price {
  background: #fff;
  border: 1px solid #f0eee8;
  border-radius: 12px;
  padding: 14px 16px;
}
.co-price-row {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  font-size: 13px;
  color: #5a5a5a;
}
.co-price-total {
  border-top: 1px solid #f0eee8;
  margin-top: 6px;
  padding-top: 12px;
  font-size: 15px;
  font-weight: 700;
  color: #1a1a1a;
}

.co-payment-split {
  margin-top: 14px;
  background: linear-gradient(135deg, #f0f7e8, #e8f2d8);
  border: 1px solid #d4e4b8;
  border-radius: 12px;
  padding: 12px 14px;
}
.co-split-hd {
  font-size: 11px;
  font-weight: 700;
  color: #4a5d23;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
}
.co-split-row {
  display: flex;
  justify-content: space-between;
  padding: 4px 0;
  font-size: 13px;
  color: #4a5d23;
  font-weight: 600;
}
.co-split-row strong {
  font-size: 14px;
}
.co-split-row-muted {
  color: #8a9182;
  font-weight: 500;
}
.co-split-row-muted strong {
  color: #8a9182;
  font-weight: 600;
}

.co-field {
  margin-bottom: 14px;
}
.co-field label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: #4a5d23;
  margin-bottom: 6px;
  letter-spacing: 0.2px;
}
.co-req {
  color: #dc2626;
}
.co-opt {
  color: #8a9182;
  font-weight: 400;
  font-size: 11px;
}
.co-field input,
.co-field textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1.5px solid #e8e2d5;
  border-radius: 10px;
  font-size: 16px; /* >=16px so iOS Safari doesn't auto-zoom on focus (checkout path) */
  font-family: "Outfit", sans-serif;
  background: #fff;
  transition: all 0.2s;
  box-sizing: border-box;
  color: #1a1a1a;
}
.co-field textarea {
  resize: vertical;
  min-height: 72px;
}
.co-field input:focus,
.co-field textarea:focus {
  outline: none;
  border-color: #4a5d23;
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.co-field input:focus-visible,
.co-field textarea:focus-visible {
  outline: 2px solid var(--olive, #4a5d23);
  outline-offset: 1px;
}
.co-hint {
  font-size: 11px;
  color: #8a9182;
  margin-top: 5px;
}

.co-policy {
  display: flex;
  gap: 12px;
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  border-radius: 12px;
  padding: 14px;
  border-bottom: 1px solid #bbf7d0;
}
.co-policy-ic {
  width: 32px;
  height: 32px;
  background: #22c55e;
  color: #fff;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 16px;
  flex-shrink: 0;
}
.co-policy-title {
  font-size: 13px;
  font-weight: 600;
  color: #166534;
  margin-bottom: 2px;
}
.co-policy-txt {
  font-size: 12px;
  color: #166534;
  opacity: 0.85;
  line-height: 1.5;
}

/* PAYMENT METHOD SELECTION */
.co-methods {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 18px;
}
.co-method {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  background: #fff;
  border: 1.5px solid #e8e2d5;
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.2s;
  font-family: "Outfit", sans-serif;
  text-align: left;
  width: 100%;
}
.co-method:hover {
  border-color: #c4cbb0;
  background: #faf9f6;
}
.co-method.selected {
  border-color: #4a5d23;
  background: #f0f7e8;
  box-shadow: 0 4px 14px rgba(74, 93, 35, 0.1);
}
/* Solo confirmation card (single payment method): present, not a chooser. */
.co-method.is-solo {
  cursor: default;
}
.co-method.is-solo:hover {
  border-color: #4a5d23;
  background: #f0f7e8;
}
.co-method-icon {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  font-size: 20px;
  font-weight: 800;
  color: #fff;
}
.co-mic-gcash {
  background: linear-gradient(135deg, #0070e0, #0051b8);
  font-family: "Playfair Display", serif;
  color: #fff;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 20px;
}
.co-mic-qr {
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #fff;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 22px;
}
.co-method-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.co-method-name {
  font-size: 14px;
  font-weight: 600;
  color: #1a1a1a;
  display: flex;
  align-items: center;
  gap: 8px;
}
.co-method-tag {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  background: #4a5d23;
  color: #fff;
  padding: 2px 7px;
  border-radius: 10px;
  text-transform: uppercase;
}
.co-method-desc {
  font-size: 12px;
  color: #8a9182;
  line-height: 1.4;
}
.co-method-radio {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid #d4cdb6;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  transition: all 0.2s;
}
.co-method.selected .co-method-radio {
  border-color: #4a5d23;
  background: #4a5d23;
}
.co-method-radio-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
  opacity: 0;
  transition: opacity 0.2s;
}
.co-method.selected .co-method-radio-dot {
  opacity: 1;
}

.co-trust {
  display: flex;
  justify-content: space-around;
  gap: 10px;
  padding: 12px;
  background: #faf9f6;
  border-radius: 10px;
  border: 1px dashed #e8e2d5;
}
.co-trust-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: #5a5a5a;
  font-weight: 500;
}

/* GCASH DIRECT / QR */
.co-pay-hero {
  background: linear-gradient(135deg, #0070e0, #0051b8);
  color: #fff;
  border-radius: 16px;
  padding: 20px;
  margin-bottom: 16px;
  box-shadow: 0 10px 28px rgba(0, 112, 224, 0.25);
  position: relative;
  overflow: hidden;
}
.co-pay-hero::after {
  content: "";
  position: absolute;
  top: -40%;
  right: -10%;
  width: 60%;
  height: 180%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.12),
    transparent 70%
  );
  pointer-events: none;
}
.co-pay-hero-top {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
  position: relative;
  z-index: 1;
}
.co-pay-logo {
  width: 46px;
  height: 46px;
  border-radius: 12px;
  background: #fff;
  color: #0070e0;
  display: grid;
  place-items: center;
  font-family: "Playfair Display", serif;
  font-weight: 800;
  font-size: 24px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.co-pay-hero-lbl {
  font-size: 11px;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.8);
  text-transform: uppercase;
  margin-bottom: 3px;
}
.co-pay-hero-amt {
  font-family: "Playfair Display", serif;
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.3px;
}
.co-pay-big-btn {
  position: relative;
  z-index: 1;
  width: 100%;
  background: #fff;
  color: #0070e0;
  border: none;
  padding: 14px 16px;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: all 0.2s;
  font-family: "Outfit", sans-serif;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}
.co-pay-big-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
}
.co-pay-big-btn:active {
  transform: translateY(0);
}
.co-pay-hint {
  position: relative;
  z-index: 1;
  font-size: 11px;
  text-align: center;
  margin-top: 10px;
  color: rgba(255, 255, 255, 0.85);
}

.co-pay-info {
  background: #faf9f6;
  border-radius: 12px;
  padding: 4px 14px;
  border: 1px solid #f0eee8;
}
.co-pay-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid #f0eee8;
  font-size: 13px;
  gap: 12px;
}
.co-pay-row:last-child {
  border-bottom: none;
}
.co-pay-lbl {
  color: #8a9182;
  flex-shrink: 0;
}
.co-pay-val {
  display: flex;
  align-items: center;
  gap: 8px;
}
.co-pay-val strong {
  font-size: 14px;
  color: #1a1a1a;
}
.co-pay-copy {
  background: #0070e0;
  color: #fff;
  border: none;
  padding: 5px 10px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}
.co-pay-copy:hover {
  background: #0051b8;
}
.co-pay-copy.copied {
  background: #22c55e;
}

/* QR-specific */
.co-qr-hero {
  background: linear-gradient(135deg, #faf9f6, #f5f2ec);
  border: 1px solid #f0eee8;
  border-radius: 16px;
  padding: 20px;
  text-align: center;
}
.co-qr-hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.co-qr-hero-top .co-pay-hero-lbl {
  color: #8a9182;
}
.co-qr-hero-top .co-pay-hero-amt {
  color: #4a5d23;
  font-size: 24px;
}
.co-qr-badge {
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  padding: 5px 10px;
  border-radius: 8px;
}
.co-qr-wrap {
  background: #fff;
  border-radius: 14px;
  padding: 16px;
  display: inline-block;
  margin-bottom: 16px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
}
.co-qr-img {
  width: 240px;
  height: 240px;
  display: block;
}
.co-qr-steps {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
  max-width: 320px;
  margin: 0 auto;
}
.co-qr-step {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: #5a5a5a;
}
.co-qr-step span:first-child {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #4a5d23;
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
}

/* PAY AT PROPERTY */
.co-cash-hero {
  text-align: center;
  padding: 24px 16px;
  background: linear-gradient(135deg, #fef3c7, #fde68a);
  border-radius: 16px;
  margin-bottom: 14px;
  border: 1px solid #fcd34d;
}
.co-cash-ic {
  font-size: 44px;
  margin-bottom: 8px;
}
.co-cash-title {
  font-family: "Playfair Display", serif;
  font-size: 20px;
  font-weight: 600;
  color: #92400e;
  margin: 0 0 6px;
}
.co-cash-sub {
  font-size: 13px;
  color: #92400e;
  margin: 0;
  line-height: 1.5;
}
.co-cash-notice {
  display: flex;
  gap: 12px;
  padding: 14px;
  background: #eff6ff;
  border: 1px solid #bfdbfe;
  border-radius: 12px;
}
.co-cash-notice-ic {
  font-size: 20px;
  flex-shrink: 0;
}
.co-cash-notice-title {
  font-size: 13px;
  font-weight: 600;
  color: #1e40af;
  margin-bottom: 6px;
}
.co-cash-list {
  margin: 0;
  padding: 0 0 0 18px;
  font-size: 12px;
  color: #1e40af;
  line-height: 1.7;
}

/* FOOTER ACTIONS */
.co-footer {
  background: #fff;
  padding: 16px 22px 22px;
  border-top: 1px solid #f0eee8;
  position: sticky;
  bottom: 0;
  margin: 0 -22px -20px;
  /* Phase I — iOS Safari fix. position:sticky inside an overflow-y:auto
     parent + negative margins + box-shadow on children was producing
     a hit-test offset where taps "near" the sticky footer registered
     somewhere else, so the Pay button on step 3 never received the
     click. Forcing a new compositing layer (translateZ + isolate)
     normalises the layer geometry and resolves the offset. */
  transform: translateZ(0);
  isolation: isolate;
  z-index: 2;
}
.co-next,
.co-submit {
  width: 100%;
  padding: 15px;
  background: linear-gradient(135deg, #4a5d23, #6b8234);
  color: #fff;
  border: none;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.25s;
  font-family: "Outfit", sans-serif;
  letter-spacing: 0.3px;
  box-shadow: 0 6px 18px rgba(74, 93, 35, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* Phase I — explicit iOS Safari hit-test guarantees. Without these,
     the sticky .co-footer + negative margins + nested overflow on the
     mobile checkout sheet caused tap events on step 3 to miss the
     button entirely (the "stuck on step 3, can't touch anything"
     bug). Forcing a new compositing layer (translateZ) plus
     touch-action and pointer-events both auto resolves the hit-test
     offset that iOS Safari produces in this layout. */
  touch-action: manipulation;
  pointer-events: auto;
  position: relative;
  z-index: 2;
  transform: translateZ(0);
  -webkit-tap-highlight-color: rgba(74, 93, 35, 0.15);
}
.co-next:hover:not(:disabled),
.co-submit:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(74, 93, 35, 0.32);
}
.co-next:disabled,
.co-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: #c4cbb0;
  box-shadow: none;
}
.co-footer-note {
  text-align: center;
  font-size: 11px;
  color: #8a9182;
  margin-top: 10px;
  line-height: 1.5;
}

/* SUCCESS STATE */
.co-success {
  text-align: center;
  padding: 24px 10px;
}
.co-success-ic {
  width: 80px;
  height: 80px;
  margin: 0 auto 20px;
  border-radius: 50%;
  background: linear-gradient(135deg, #22c55e, #16a34a);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 40px;
  box-shadow: 0 12px 32px rgba(34, 197, 94, 0.35);
  animation: coSuccessPop 0.5s cubic-bezier(0.2, 1.4, 0.3, 1);
}
@keyframes coSuccessPop {
  0% {
    transform: scale(0);
  }
  60% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}
.co-success-title {
  font-family: "Playfair Display", serif;
  font-size: 26px;
  color: #1a1a1a;
  margin: 0 0 8px;
  font-weight: 600;
}
.co-success-sub {
  font-size: 14px;
  color: #5a5a5a;
  line-height: 1.5;
  margin: 0 0 20px;
  max-width: 380px;
  margin-left: auto;
  margin-right: auto;
}
.co-success-card {
  background: linear-gradient(135deg, #faf9f6, #f5f2ec);
  border: 1px solid #f0eee8;
  border-radius: 14px;
  padding: 20px;
  margin: 0 auto 18px;
  max-width: 380px;
  text-align: left;
}
.co-success-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.5px;
  color: #8a9182;
  text-transform: uppercase;
  text-align: center;
}
.co-success-ref {
  font-family: "Playfair Display", serif;
  font-size: 22px;
  font-weight: 700;
  color: #4a5d23;
  letter-spacing: 3px;
  text-align: center;
  margin: 4px 0 12px;
}
.co-success-divider {
  height: 1px;
  background: #e8e2d5;
  margin: 10px 0;
  position: relative;
}
.co-success-divider::before,
.co-success-divider::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  top: -8px;
}
.co-success-divider::before {
  left: -26px;
}
.co-success-divider::after {
  right: -26px;
}
.co-success-row {
  display: flex;
  justify-content: space-between;
  padding: 4px 0;
  font-size: 13px;
  color: #5a5a5a;
}
.co-success-row strong {
  color: #1a1a1a;
  font-weight: 600;
}
.co-success-next {
  text-align: left;
  background: #faf9f6;
  border-radius: 12px;
  padding: 16px;
  margin: 0 auto 20px;
  max-width: 380px;
}
.co-success-next h4 {
  margin: 0 0 10px;
  font-size: 13px;
  color: #4a5d23;
  font-weight: 700;
  letter-spacing: 0.3px;
}
.co-success-next ul {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 12px;
  color: #5a5a5a;
  line-height: 2;
}

/* ADMIN — Payment status badges (kept for dashboard) */
.pay-badge-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 12px;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.pay-badge-paid {
  background: #dcfce7;
  color: #166534;
}
.pay-badge-pending {
  background: #fef3c7;
  color: #92400e;
}
.pay-badge-unpaid {
  background: #f3f4f6;
  color: #6b7280;
}

/* MOBILE — Full-screen sheet */
@media (max-width: 600px) {
  .co-modal {
    padding: 0;
  }
  .co-sheet {
    margin: 0;
    max-width: 100%;
    /* Phase B/4 — 100dvh covers the visible viewport on mobile after
       browser chrome collapses; 100vh kept as fallback for browsers
       without dvh support so the sheet always reaches edge-to-edge. */
    max-height: 100vh;
    max-height: 100dvh;
    height: 100vh;
    height: 100dvh;
    border-radius: 0;
  }
  .co-sheet-body {
    padding: 16px 18px 0;
  }
  .co-footer {
    padding: 14px 18px calc(14px + env(safe-area-inset-bottom, 0px));
    margin: 0 -18px -16px;
  }
  .co-prog-lbl {
    display: none;
  }
  .co-progress {
    padding: 12px 16px;
  }
  .co-head-stp {
    font-size: 15px;
  }
  .co-trip-grid {
    grid-template-columns: 1fr;
    gap: 0;
    padding: 4px 14px;
  }
  .co-trip-item:not(:last-child) {
    border-right: none;
    border-bottom: 1px solid #e8e2d5;
  }
  .co-trip-item {
    text-align: left;
    display: grid;
    grid-template-columns: 100px 1fr auto;
    gap: 10px;
    align-items: center;
    padding: 12px 0;
  }
  .co-trip-lbl {
    margin-bottom: 0;
  }
  .co-trip-sub {
    margin-top: 0;
  }
  .co-pay-hero-amt {
    font-size: 24px;
  }
  .co-qr-img {
    width: 200px;
    height: 200px;
  }
  .co-success-card,
  .co-success-next {
    max-width: 100%;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   HERO — Premium entry choreography + ambient motion
   Uses a custom expo-out curve, clip-path line reveals, and a slow
   parallax on the background art. Everything is opt-out friendly via
   prefers-reduced-motion and a body-level .no-hero-anim flag.
   ═══════════════════════════════════════════════════════════════════ */

/* The curve — buttery expo.out-style easing */
:root {
  --hero-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --hero-ease-soft: cubic-bezier(0.33, 1, 0.68, 1);
}

/* --- Initial states (before .is-visible lands) ---------------------- */
.hero-fx {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  will-change: transform, opacity;
}
.hero-fx-h1 {
  display: block;
  overflow: hidden;
}
.hero-fx-h1 .hero-line {
  display: block;
  opacity: 0;
  transform: translate3d(0, 110%, 0);
  clip-path: inset(0 0 100% 0);
  will-change: transform, clip-path, opacity;
}

/* Background art: starts very slightly zoomed + faded, then settles in */
[data-hero-art] {
  opacity: 0;
  transform: scale(1.04);
  transition:
    opacity 1.4s var(--hero-ease),
    transform 1.6s var(--hero-ease);
  will-change: transform, opacity;
}

/* --- Reveal states -------------------------------------------------- */
.hero-fx.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity 1s var(--hero-ease),
    transform 1.1s var(--hero-ease);
  transition-delay: calc(var(--hero-step, 0) * 90ms + 80ms);
}

.hero-fx-h1 .hero-line.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  clip-path: inset(0 0 0 0);
  transition:
    opacity 1s var(--hero-ease),
    transform 1.1s var(--hero-ease),
    clip-path 1.2s var(--hero-ease);
  transition-delay: calc(var(--hero-step, 0) * 90ms + 80ms);
}

[data-hero-art].is-visible {
  opacity: 1;
  transform: scale(1);
}

/* --- Ambient continuous motion ------------------------------------- */
/* Slow sway lives on the wrapper so the JS parallax on the inner SVG
   doesn't conflict with the keyframe transform. Delay matches the
   entry transition so the animation picks up where the reveal ends. */
[data-hero-art].is-visible {
  animation: heroArtDrift 18s var(--hero-ease-soft) 1.6s infinite alternate;
}

@keyframes heroArtDrift {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  100% {
    transform: translate3d(-6px, -4px, 0) scale(1.012);
  }
}

/* NOTE: Sun/halo animations now live inside the SVG itself as SMIL
   <animate> tags, so they scale with the SVG's own coordinate system.
   Do not re-add CSS keyframes targeting [fill="url(#hglow)"] / [fill="url(#hsun)"]
   — they would conflict with the SMIL timing and were written for the
   old sun position (950,220) that no longer exists. */

/* Pill dot — already has `animation: pulse 2s infinite` in existing CSS;
   we just make sure it keeps running during the reveal. */

/* --- prefers-reduced-motion: pop in, no movement ------------------- */
@media (prefers-reduced-motion: reduce) {
  .hero-fx,
  .hero-fx-h1 .hero-line,
  [data-hero-art] {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
    animation: none !important;
  }
  [data-hero-art] svg,
  .hero-bg-art svg circle[fill="url(#hglow)"],
  .hero-bg-art svg circle[fill="url(#hsun)"] {
    animation: none !important;
  }
}

/* --- Global opt-out flag (JS sets this if something goes wrong) ---- */
body.no-hero-anim .hero-fx,
body.no-hero-anim .hero-fx-h1 .hero-line,
body.no-hero-anim [data-hero-art] {
  opacity: 1 !important;
  transform: none !important;
  clip-path: none !important;
  transition: none !important;
}

/* ====================================================================
   HERO v4 - Flat-illustration "Island of Fire" (centered + animated).
   (Reference-driven redesign of HERO_REDESIGN_PROMPT.md.)

   - Pure flat SVG scene (.hero__art): pale sky, gold sun, drifting clouds,
     gliding birds, layered olive palm silhouettes + foreground dunes.
     Fully visible with ZERO JS. anime.js only adds the entrance; the
     ambient loops (sway/drift/glide/pulse) are CSS (off-main-thread,
     smoother under load, and alive even if anime.js never loads).
   - Centered, confident composition. DARK olive text on the PALE sky
     clears WCAG AA without a scrim; a soft cream focus-halo keeps the
     centre crisp. Brand palette only: olive / gold / cream.
   - Reliability unchanged: visible-by-default, static shell in index.html,
     motion is enhancement, reduced-motion + reduced-data honoured.
   ==================================================================== */
.hero--cinematic {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 100vh; /* fallback for browsers without dvh */
  min-height: 100dvh; /* grow to fit the stack — never hard-clip on mobile */
  overflow: hidden;
  isolation: isolate;
  background: #e7eedd;
}

.hero__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
  pointer-events: none;
}

/* Mobile-only corner palms. The hero__art SVG is xMidYMax `slice`, which on a
   portrait phone scales-to-cover and crops the sides — so the two framing
   palms (near x=200 / x=1240 of the 1440 canvas) fall off-screen. This layer
   tucks two small coconut palms into the bottom corners, behind the text, so
   phones still get the palm framing. Its own 390-wide viewBox keeps the palms
   at the screen edges across phone widths. Same z-index/pointer-events as the
   art; hidden >=600px (desktop/landscape use the hero__art palms). */
.hero__palms-m {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  display: none;
}
@media (max-width: 599px) {
  .hero__palms-m { display: block; }
}

.hero__halo {
  position: absolute;
  left: 50%;
  top: 46%;
  width: min(940px, 94vw);
  height: min(560px, 64vh);
  transform: translate(-50%, -50%);
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(250, 249, 246, 0.7), rgba(250, 249, 246, 0) 78%);
}

/* Wave 1 (5): film grain + corner vignette — CSS-only atmosphere, zero JS,
   zero animation (nothing for reduced-motion to neutralize). Grain reuses the
   auth-bg__grain SVG-noise data-URI at 3% multiply. The vignette is a faint
   warm darkening pinned to the corners — the centre stays untouched well past
   the text column, so hero-text contrast can only gain from it. Both share the
   halo's z-plane; the halo is later in the DOM, paints last, keeps the centre
   crisp. */
.hero__grain {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.03;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
}
.hero__vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 42%, rgba(58, 52, 28, 0) 58%, rgba(58, 52, 28, 0.16) 100%);
}

.palm-crown-left,
.palm-crown-right { transform-box: fill-box; transform-origin: 50% 100%; }
.art-sun { transform-box: fill-box; transform-origin: 50% 50%; }
/* Wave 1 (2+3): the bloom breathes (scale) around its own centre and richens
   (opacity) as the sun descends — both written per-frame by kwGoldenHour, so
   promote it alongside the wrapper. */
.art-sun-bloom { transform-box: fill-box; transform-origin: 50% 50%; will-change: transform, opacity; }
/* Golden Hour (Wave 1A): the sun-descent wrapper. transform-box:view-box so the
   scale origin resolves in viewBox coords (sun centre 1052,208). Translated on
   scroll by kwGoldenHour; promoted to its own layer for smooth compositing. */
.art-sun-shift { transform-box: view-box; transform-origin: 1052px 208px; will-change: transform; }
/* Wave 1 (1+4): scroll-driven wash + parallax dunes — promoted so kwGoldenHour's
   per-frame opacity/transform writes composite instead of repainting the SVG. */
.art-sky-warm { will-change: opacity; }
.art-dune-back,
.art-dune { will-change: transform; }
.art-cloud-1,
.art-cloud-2,
.art-birds { transform-box: fill-box; }

.hero__content {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 900px;
  margin: 0 auto;
  padding: clamp(80px, 13vh, 150px) clamp(20px, 5vw, 48px) clamp(40px, 8vh, 96px);
  color: var(--text-d);
}
.hero__inner { margin: 0 auto; }

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 16px;
  margin: 0 0 22px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid var(--olive-10);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  border-radius: 100px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--olive);
}
.hero__geo {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 0 rgba(200, 169, 81, 0.6);
  animation: heroGeoPulse 2.8s ease-in-out infinite;
}

.hero__title {
  margin: 0 auto 22px;
  max-width: 16ch;
  font-family: var(--serif);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.015em;
  font-size: clamp(2.8rem, 1.4rem + 5.4vw, 6rem);
  color: var(--text-d);
  text-wrap: balance;
}
.hero__line { display: block; }
/* Wave 1 (6): warm gradient text-fill on the accent. AA re-check: the old flat
   --gold (#c8a951) measured only ~1.9:1 against the pale sky #f5efda — under
   the 3:1 large-text floor — so the gradient runs deeper bronze-gold stops
   that all clear 3:1 on the hero backdrop even in the worst case: the fully
   warmed sky (≈#f6e1b4) with NO halo behind it (lightest stop #9c7a1e ≈ 3.1:1
   there, ≈3.4:1 on the base #f5efda sky; the cream halo behind the title only
   raises contrast further). The solid color outside @supports is the fallback
   for engines without background-clip:text. */
.hero__title .hero__accent { font-style: italic; color: #8a6a1c; }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero__title .hero__accent {
    background-image: linear-gradient(105deg, #7c5e16 0%, #9c7a1e 48%, #8a6a1c 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}

.hero__sub {
  margin: 0 auto 26px;
  max-width: 54ch;
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(1rem, 0.94rem + 0.45vw, 1.2rem);
  line-height: 1.6;
  color: #3c4626;
}

.hero__loc {
  margin: 0 0 26px;
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 500;
  color: #4a5d23;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin: 0 0 26px;
}
.hero__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 14px 30px;
  border-radius: 14px;
  font-family: var(--sans);
  font-size: 0.98rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform 160ms cubic-bezier(0.23, 1, 0.32, 1),
    box-shadow 160ms cubic-bezier(0.23, 1, 0.32, 1),
    background-color 160ms ease,
    color 160ms ease;
}
.hero__btn--primary {
  background: var(--gold);
  color: var(--text-d);
  border: 1px solid var(--gold);
  box-shadow: 0 10px 26px rgba(120, 86, 20, 0.28);
}
.hero__btn--primary:hover {
  background: #d8b95f;
  transform: translateY(-2px);
  box-shadow: 0 16px 36px rgba(120, 86, 20, 0.36);
}
.hero__btn--ghost {
  background: rgba(255, 255, 255, 0.5);
  color: var(--olive);
  border: 1.5px solid var(--olive);
}
.hero__btn--ghost:hover {
  background: var(--olive);
  color: var(--cream);
  transform: translateY(-2px);
}
.hero__btn:active { transform: scale(0.97); }
.hero__btn:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }

/* ═══════════════════════════════════════════════════════════════════
   OCEAN-WAVE BUTTON (.ocean-btn) — native WebGL liquid CTA
   Vanilla port of the reactbits "LiquidChrome" shader, brand-colored:
   olive deep-water → gold wet-sand → cream foam, swept sideways like
   surf receding over sand. The static gradient below is BOTH the
   pre-paint look AND the no-WebGL / context-lost fallback, so the
   button is always on-brand even if the canvas never renders. JS
   (script.js → initOceanButtons) layers the animated <canvas> on top
   and pauses it off-screen / on reduced-motion / when the tab is hidden.
   ═══════════════════════════════════════════════════════════════════ */
.ocean-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px; /* ≥44px touch target (mobile mandate) */
  padding: 14px 32px;
  border-radius: 14px; /* matches .hero__btn */
  border: 1px solid rgba(74, 93, 35, 0.55);
  /* Static fallback: deep-water olive → wet-sand gold. */
  background: linear-gradient(120deg, var(--olive) 0%, #5d7430 45%, var(--gold) 100%);
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate; /* button owns its canvas/scrim stacking context */
  box-shadow: 0 10px 26px rgba(74, 93, 35, 0.28);
  transition:
    transform 160ms cubic-bezier(0.23, 1, 0.32, 1),
    box-shadow 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.ocean-btn__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
}
/* Legibility scrim — a center-weighted dark band so the cream label keeps
   ≥4.5:1 even when a bright gold/foam sweep passes directly behind the text.
   Darkest at the vertical middle (where the label sits), light at the top/
   bottom rims so the surf crest still breathes around it. Worst case: cream
   over a gold sweep composites to ~rgb(112,103,52) → ≈5.2:1 (AA), before the
   per-glyph text-shadow halo adds further margin. */
.ocean-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(31, 42, 26, 0.16) 0%,
    rgba(31, 42, 26, 0.52) 50%,
    rgba(31, 42, 26, 0.16) 100%
  );
}
.ocean-btn__label {
  position: relative;
  z-index: 2;
  color: var(--cream);
  letter-spacing: 0.2px;
  /* Per-glyph dark halo — reliable legibility over a moving multi-color field. */
  text-shadow:
    0 1px 2px rgba(31, 42, 26, 0.75),
    0 0 10px rgba(31, 42, 26, 0.45);
}
.ocean-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 36px rgba(74, 93, 35, 0.36);
}
.ocean-btn:active {
  transform: scale(0.97);
}
.ocean-btn:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

.hero__rating {
  display: flex;
  align-items: baseline;
  gap: 10px;
  justify-content: center;
  margin: 0;
  font-family: var(--sans);
}
.hero__rate-num { font-weight: 700; font-size: 1.05rem; color: var(--olive); }
.hero__rate-sub { font-size: 0.85rem; color: #5a6147; }

.hero__scroll-indicator {
  position: absolute;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  width: 22px;
  height: 14px;
  z-index: 2;
  pointer-events: none;
  animation: heroBreath 3s ease-in-out infinite;
}
.hero__scroll-indicator .hero__scroll-line {
  position: absolute;
  display: block;
  width: 13px;
  height: 2px;
  border-radius: 2px;
  background: var(--olive);
  opacity: 0.6;
}
.hero__scroll-indicator .hero__scroll-line:nth-child(1) { transform: rotate(38deg) translateX(-3px); }
.hero__scroll-indicator .hero__scroll-line:nth-child(2) { transform: rotate(-38deg) translateX(3px); }

@keyframes heroGeoPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200, 169, 81, 0.55); }
  50% { box-shadow: 0 0 0 6px rgba(200, 169, 81, 0); }
}
@keyframes heroBreath {
  0%, 100% { opacity: 0.4; transform: translateX(-50%) translateY(0); }
  50% { opacity: 0.85; transform: translateX(-50%) translateY(4px); }
}
@keyframes heroSwayL { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(2.5deg); } }
@keyframes heroSwayR { 0%, 100% { transform: rotate(2deg); } 50% { transform: rotate(-2.5deg); } }
@keyframes heroCloud1 { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(46px); } }
@keyframes heroCloud2 { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-38px); } }
@keyframes heroBirds { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(26px, -12px); } }
@keyframes heroSunPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.04); } }

/* HERO OCEAN — golden-hour horizon sea. Additive; ambient only. Promote the
   group to its own layer so the swell/drift composite instead of repainting the
   SVG. Pure px translate3d, so transform-box is irrelevant (no rotate/scale/%).
   Gated EXACTLY like the cloud/bird ambient motion below: animates only under
   no-preference, killed under reduced-data; absent under reduced-motion (the
   rules live only in the no-preference block) — the scene stays a full poster. */
.art-ocean { will-change: transform; }
.art-ocean-shift { will-change: transform; }              /* Phase B: scroll-parallax target (writeSun) */
.art-ocean-glint, .art-ocean-foam { will-change: opacity; } /* Phase B: bound repaint of the opacity loops */
@keyframes heroOceanSwell  { from { transform: translate3d(0,0,0); } to { transform: translate3d(0,4px,0); } }
@keyframes heroOceanDrift1 { from { transform: translate3d(0,0,0); } to { transform: translate3d(34px,0,0); } }
@keyframes heroOceanDrift2 { from { transform: translate3d(0,0,0); } to { transform: translate3d(-28px,0,0); } }
@keyframes heroOceanDrift3 { from { transform: translate3d(0,0,0); } to { transform: translate3d(22px,0,0); } }
@keyframes heroOceanFoam   { 0%, 100% { opacity: 0.24; } 50% { opacity: 0.42; } } /* soft waterline breathe */
@keyframes heroOceanGlint  { 0%, 100% { opacity: 0.62; } 50% { opacity: 1; } }   /* unison shimmer, not twinkle */

@media (prefers-reduced-motion: no-preference) {
  .palm-crown-left { animation: heroSwayL 6s ease-in-out infinite; }
  .palm-crown-right { animation: heroSwayR 7s ease-in-out infinite; }
  .art-cloud-1 { animation: heroCloud1 56s ease-in-out infinite; }
  .art-cloud-2 { animation: heroCloud2 74s ease-in-out infinite; }
  .art-birds { animation: heroBirds 24s ease-in-out infinite; }
  .art-sun { animation: heroSunPulse 9s ease-in-out infinite; }
  /* Ocean: a slow vertical swell on the whole group, plus two crest layers
     drifting opposite directions at different speeds (gentle parallax). Long
     durations keep it calm and never competing with the headline. */
  .art-ocean        { animation: heroOceanSwell 11s ease-in-out infinite alternate; }
  .art-ocean-crest-1{ animation: heroOceanDrift1 46s ease-in-out infinite alternate; }
  .art-ocean-crest-2{ animation: heroOceanDrift2 62s ease-in-out infinite alternate; }
  .art-ocean-crest-3{ animation: heroOceanDrift3 52s ease-in-out infinite alternate; }
  .art-ocean-foam   { animation: heroOceanFoam 31s ease-in-out infinite; }
  .art-ocean-glint  { animation: heroOceanGlint 5.5s ease-in-out infinite; }
}
@media (prefers-reduced-data: reduce) {
  .palm-crown-left,
  .palm-crown-right,
  .art-cloud-1,
  .art-cloud-2,
  .art-birds,
  .art-ocean,
  .art-ocean-crest-1,
  .art-ocean-crest-2,
  .art-ocean-crest-3,
  .art-ocean-foam,
  .art-ocean-glint,
  .art-sun { animation: none !important; }
}

@media (max-width: 1023px) {
  .hero__content { padding-top: clamp(72px, 11vh, 120px); }
  .hero__title { font-size: clamp(2.6rem, 1.3rem + 5vw, 4.4rem); }
}

@media (max-width: 599px) {
  /* iOS Safari fit (root cause of the "hero doesn't fit / rating cut off" bug):
     the .nav is position:sticky AND in normal flow (60px tall), so a hero of
     min-height:100dvh sits BELOW it and the first screen becomes 100dvh + 60px
     — i.e. always 60px TALLER than the visible viewport, pushing the bottom of
     the hero (and the rating) below the fold. Subtracting the nav makes
     nav + hero = exactly one screen. (Desktop Chrome at 100vh hid this because
     it measured against the full screen height, not the smaller area iOS Safari
     actually shows once its address/toolbar chrome is visible.)
     There is also no green "dune" at the bottom on mobile, so the old 180px
     bottom reserve only shoved the rating off-screen; a small pad is enough.
     Rhythm is tightened so the whole stack — eyebrow > title > sub > location
     > CTAs > rating — fits one screen on a real iPhone (~660px visible). */
  .hero--cinematic {
    min-height: calc(100vh - 60px);  /* fallback for browsers without dvh */
    min-height: calc(100dvh - 60px); /* nav (60px, sticky/in-flow) + hero = 1 screen */
  }
  .hero__content {
    padding:
      clamp(12px, 2vh, 22px)
      18px
      calc(44px + env(safe-area-inset-bottom, 0px));
  }
  .hero__title { font-size: clamp(1.95rem, 1.2rem + 4.4vw, 2.3rem); line-height: 1.02; max-width: 14ch; margin-bottom: 10px; }
  .hero__sub { font-size: 1rem; margin-bottom: 10px; }
  .hero__cta { flex-direction: column; align-items: stretch; gap: 10px; margin-bottom: 10px; }
  .hero__btn { width: 100%; }
  .hero__scroll-indicator { display: none; }
  .hero__halo { top: 38%; height: min(520px, 64vh); }

  /* Tighten vertical rhythm so the whole stack fits one screen. */
  .hero__eyebrow { margin-bottom: 8px; }
  .hero__loc { margin-bottom: 10px; }
  .hero__rating { margin: 0; }
}

/* Small phones (<=380px): the title fits comfortably in 3 lines here, so keep
   the same compact reserve/rhythm as the 599 block. Do NOT re-inflate the
   bottom pad (the old 160px is what pushed the rating off-screen). */
@media (max-width: 380px) {
  .hero__title { font-size: clamp(1.85rem, 1.2rem + 5vw, 2.2rem); max-width: 15ch; margin-bottom: 8px; }
  .hero__sub { font-size: 1rem; margin-bottom: 10px; } /* keep >=16px body for AA */
  .hero__content { padding-bottom: calc(40px + env(safe-area-inset-bottom, 0px)); }
  .hero__eyebrow { margin-bottom: 8px; }
  .hero__loc { margin-bottom: 10px; }
  .hero__cta { gap: 10px; margin-bottom: 10px; }
}

/* Landscape phones / very short windows: let the hero size to content (page
   scrolls) and drop the big dune reserve so the stack stays usable. */
@media (max-height: 600px) and (orientation: landscape) {
  .hero--cinematic { min-height: 0; }
  .hero__content {
    padding-top: clamp(20px, 4vh, 36px);
    padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  }
  .hero__sub { margin-bottom: 12px; }
  .hero__cta { margin-bottom: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__geo,
  .hero__scroll-indicator { animation: none !important; }
}

/* === PROCEDURAL PALMS (§4) === */
.magic {
  position: relative;
  isolation: isolate;
}
.magic__palms {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 240px;
  pointer-events: none;
  z-index: 0;
}
.magic__palms--left {
  left: 0;
}
.magic__palms--right {
  right: 0;
  transform: scaleX(-1); /* mirror right-side trees */
}
.magic > *:not(.magic__palms) {
  position: relative;
  z-index: 1;
}

@media (max-width: 768px) {
  .magic__palms {
    width: 168px;
    opacity: 0.7;
  } /* 70% scale via width reduction + opacity for depth */
}

@media (prefers-reduced-motion: reduce) {
  .magic__palms {
    opacity: 0.85;
  } /* slightly mute; static palms are still visible */
}

/* ═══════════════════════════════════════════════════════════════════
   === SECTION POLISH §5 (Phase 4) ===
   Per-section micro-interaction layer. Each subsection scopes
   selectors to the existing class names rendered by script.js.
   Only transform/opacity/filter animated. Reduced-motion gated.
   ═══════════════════════════════════════════════════════════════════ */

/* ─── §5.1 NAV ──────────────────────────────────────────────────────
   Glass background ramps from 88% → 94% opaque as user scrolls past
   20px. Brand mark color-shifts to olive on hover. Nav links get a
   ribbon-unroll underline (right→left origin swap). Active tab has
   a FLIP indicator absolutely positioned over the rail. Mobile menu
   stagger fades nav items in 80ms apart on open. */
.nav {
  /* Resting glass — softer blur than legacy, smoother ramp. Animation
     of background-color is fine (paint-only, not layout). Height stays
     on the legacy transition (preserved by re-listing here so the new
     property list does not regress the legacy 72→64px ease on scroll).
     Height transition is NOT new to Phase 4 — it pre-existed on the
     legacy `.nav { transition: 0.3s var(--ease) }` rule (line ~491). */
  background: rgba(250, 249, 246, 0.88);
  backdrop-filter: blur(12px) saturate(180%);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
  transition:
    background-color var(--t-med) var(--ease-out-expo),
    backdrop-filter var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    height var(--t-med) var(--ease-out-expo),
    box-shadow var(--t-med) var(--ease-out-expo);
}
.nav.scr {
  background: rgba(250, 249, 246, 0.94);
}
.brand {
  transition:
    color var(--t-med) var(--ease-out-expo),
    opacity var(--t-med) var(--ease-out-expo);
}
.brand:hover {
  color: var(--olive);
}
/* Ribbon-unroll underline: origin swap is the key trick. */
.nl::before {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 6px;
  height: 2px;
  background: var(--olive);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 300ms var(--ease-out-expo);
  pointer-events: none;
  opacity: 0.85;
}
.nl:hover::before,
.nl:focus-visible::before {
  transform: scaleX(1);
  transform-origin: left center;
}
.nl.act::before {
  /* Active link suppresses ribbon (the FLIP indicator owns the bar). */
  display: none;
}
/* FLIP active-tab indicator — single olive bar, transform-only slides. */
.nlinks {
  position: relative;
}
.nlinks::after {
  /* Single 24px base bar; JS computes a translate offset + scaleX factor
     so the bar both moves and resizes via composited transform — never
     animating the width property itself (composite-safe). */
  content: "";
  position: absolute;
  bottom: 4px;
  left: 0;
  width: 24px;
  height: 3px;
  border-radius: 2px;
  background: var(--olive);
  transform-origin: left center;
  transform: translateX(var(--nlinks-ind-x, 0px))
    scaleX(var(--nlinks-ind-sx, 1));
  transition:
    transform 400ms var(--ease-out-back),
    opacity 200ms var(--ease-out-expo);
  pointer-events: none;
  opacity: 0;
}
.nlinks.has-act::after {
  opacity: 1;
}
/* Suppress the legacy ::after dot on .nl.act since the FLIP rail owns it. */
.nl.act::after {
  display: none;
}
/* Mobile menu nav-item stagger — 80ms each, fade + translateY 20px. */
.mnav button {
  animation: mnavIn 360ms var(--ease-out-expo) both;
}
.mnav button:nth-of-type(1) {
  animation-delay: 80ms;
}
.mnav button:nth-of-type(2) {
  animation-delay: 160ms;
}
.mnav button:nth-of-type(3) {
  animation-delay: 240ms;
}
.mnav button:nth-of-type(4) {
  animation-delay: 320ms;
}
.mnav button:nth-of-type(5) {
  animation-delay: 400ms;
}
.mnav button:nth-of-type(6) {
  animation-delay: 480ms;
}
.mnav button:nth-of-type(7) {
  animation-delay: 560ms;
}
@keyframes mnavIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* Olive leaf silhouette corner — pure CSS gradient, no DOM. */
.mnav::after {
  content: "";
  position: absolute;
  bottom: -40px;
  right: -40px;
  width: 220px;
  height: 220px;
  background: radial-gradient(
    ellipse at top left,
    rgba(74, 93, 35, 0.1),
    transparent 65%
  );
  pointer-events: none;
  z-index: -1;
}
@media (prefers-reduced-motion: reduce) {
  .nav,
  .brand {
    transition: none !important;
  }
  .nl::before {
    transition: none !important;
  }
  .nlinks::after {
    transition: opacity 150ms ease !important;
  }
  .mnav button {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ─── §5.2 HERO COPY ────────────────────────────────────────────────
   Phase 2 already wires the split-reveal mask for the headline via
   .hero-fx-h1 .hero-line steps. This block adds: magnetic-hover for
   the primary CTA on desktop ≥1024px (JS sets --magnet-x/--magnet-y
   CSS variables; transform composites them), and a "Watch the
   island" pulse if a .hero-watch element appears in the markup. */
.hero-acts .ncta {
  --magnet-x: 0px;
  --magnet-y: 0px;
  transform: translate3d(var(--magnet-x), var(--magnet-y), 0);
  transition:
    transform 220ms var(--ease-out-expo),
    box-shadow 300ms var(--ease-out-expo),
    background-color 200ms var(--ease-out-expo);
  position: relative;
}
/* Soft gold edge-glow on hover via pseudo-element opacity (no box-shadow keyframe). */
.hero-acts .ncta::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  box-shadow:
    0 0 0 1px rgba(200, 169, 81, 0),
    0 8px 28px rgba(200, 169, 81, 0);
  opacity: 0;
  transition:
    opacity 300ms var(--ease-out-expo),
    box-shadow 300ms var(--ease-out-expo);
  pointer-events: none;
}
.hero-acts .ncta:hover::after {
  opacity: 1;
  box-shadow:
    0 0 0 1px rgba(200, 169, 81, 0.5),
    0 8px 28px rgba(200, 169, 81, 0.35);
}
.hero-acts .ncta:active {
  transform: translate3d(var(--magnet-x), 1px, 0) scale(0.98);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.15);
}
.hero-acts .ncta.is-magnetic {
  will-change: transform;
}
/* Secondary "Watch the island" link — gentle 2s breath ONLY when hero is
   in view (brief §5.2). JS toggles .is-in-view on the .hero-full section
   via IntersectionObserver; CSS uses animation-play-state to start/stop
   the breath without restarting the loop. */
.hero-watch .hero-watch-icon {
  animation: heroWatchBreath 2s ease-in-out infinite;
  animation-play-state: paused;
  transform-origin: center;
}
.hero-full.is-in-view .hero-watch .hero-watch-icon,
[data-hero].is-in-view .hero-watch .hero-watch-icon {
  animation-play-state: running;
}
@keyframes heroWatchBreath {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.85;
  }
  50% {
    transform: scale(1.08);
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero-acts .ncta {
    transition: none !important;
    transform: none !important;
  }
  .hero-acts .ncta::after {
    transition: opacity 150ms ease !important;
  }
  .hero-watch .hero-watch-icon {
    animation: none !important;
  }
}

/* ─── §5.3 ROOMS GRID ───────────────────────────────────────────────
   Masonry-style diagonal stagger via inline --row/--col CSS vars +
   delay function. Hover lifts the card with pseudo-element shadow
   intensification (no box-shadow keyframe). Heart pop on favourite.
   Ken Burns 12s loop on the detail gallery main image. */
.rgrid {
  /* Provide context for stagger; cards set --row/--col via inline style. */
  --rgrid-base-delay: 0ms;
}
.rgrid .rc.reveal {
  /* Diagonal wave: row × 80ms + col × 40ms. Inline style sets
     --row and --col on each card; this expression converts them. */
  transition-delay: calc(var(--row, 0) * 80ms + var(--col, 0) * 40ms);
}
.rc {
  position: relative;
  isolation: isolate;
}
.rc::after {
  /* Composite-cheap shadow intensifier — opacity transitions only. */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 24px 56px -16px rgba(31, 42, 26, 0.28);
  opacity: 0;
  transition: opacity 320ms var(--ease-out-expo);
  pointer-events: none;
  z-index: -1;
}
.rc:hover::after {
  opacity: 1;
}
.rc:hover .rc-img img {
  transform: scale(1.06);
  filter: saturate(1.08);
}
.rc-img img {
  transition:
    transform 500ms var(--ease-out-expo),
    filter 500ms var(--ease-out-expo);
}
.rc:hover .rc-pr {
  transform: translateY(-4px);
}
.rc-pr {
  position: relative;
  transition: transform 280ms var(--ease-out-expo);
}
.rc-pr::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 2px;
  background: var(--gold);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 280ms var(--ease-out-expo);
}
.rc:hover .rc-pr::after {
  transform: scaleX(1);
}
/* Heart icon: scale bounce on hover (unfavorited), pop on click. */
.rc-fav {
  transition:
    transform 240ms var(--ease-out-back),
    background-color 200ms;
}
.rc-fav.is-popping {
  animation: heartPop 400ms var(--ease-out-back) both;
}
@keyframes heartPop {
  0% {
    transform: scale(1);
  }
  35% {
    transform: scale(1.3);
  }
  70% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
  }
}
/* Detail gallery Ken Burns — slow scale + pan, seamless 12s loop.
   No will-change: the continuous animation already lifts the element
   to a composite layer in modern browsers; we don't want a permanent
   GPU layer per brief §21 anti-patterns. */
.dg-main img {
  animation: kenBurns 12s ease-in-out infinite alternate;
}
@keyframes kenBurns {
  0% {
    transform: scale(1) translate3d(0, 0, 0);
  }
  100% {
    transform: scale(1.04) translate3d(-1.5%, -1%, 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .rgrid .rc.reveal {
    transition-delay: 0ms !important;
  }
  .rc::after {
    transition: opacity 150ms ease !important;
  }
  .rc-img img,
  .rc-pr,
  .rc-pr::after,
  .rc-fav {
    transition: none !important;
  }
  .rc-fav.is-popping {
    animation: none !important;
  }
  .dg-main img {
    animation: none !important;
    transform: none !important;
  }
}

/* ─── §5.4 FEATURES STRIP (.svc-card / .attr-card) ──────────────────
   The brief calls for SVG line-art icons with stroke-draw-in. The
   existing markup uses emoji icons; we add support for an optional
   .svc-icon-svg path[data-draw] selector so designers can swap in
   line-art and get the draw-in for free. Also enables number
   count-up via data-count on any element entering viewport. */
.svc-icon svg path[data-draw],
.attr-icon svg path[data-draw] {
  stroke: var(--olive);
  stroke-width: 1.5;
  fill: none;
  stroke-dasharray: var(--draw-len, 220);
  stroke-dashoffset: var(--draw-len, 220);
  transition: stroke-dashoffset 600ms var(--ease-out-expo);
}
.reveal.is-in .svc-icon svg path[data-draw],
.reveal.is-in .attr-icon svg path[data-draw],
.reveal-child.is-in .svc-icon svg path[data-draw],
.reveal-child.is-in .attr-icon svg path[data-draw] {
  stroke-dashoffset: 0;
}
.svc-grid .reveal-child:nth-of-type(1) .svc-icon svg path[data-draw],
.attr-grid .reveal-child:nth-of-type(1) .attr-icon svg path[data-draw] {
  transition-delay: 0ms;
}
.svc-grid .reveal-child:nth-of-type(2) .svc-icon svg path[data-draw],
.attr-grid .reveal-child:nth-of-type(2) .attr-icon svg path[data-draw] {
  transition-delay: 120ms;
}
.svc-grid .reveal-child:nth-of-type(3) .svc-icon svg path[data-draw],
.attr-grid .reveal-child:nth-of-type(3) .attr-icon svg path[data-draw] {
  transition-delay: 240ms;
}
.svc-grid .reveal-child:nth-of-type(4) .svc-icon svg path[data-draw],
.attr-grid .reveal-child:nth-of-type(4) .attr-icon svg path[data-draw] {
  transition-delay: 360ms;
}
.svc-grid .reveal-child:nth-of-type(5) .svc-icon svg path[data-draw],
.attr-grid .reveal-child:nth-of-type(5) .attr-icon svg path[data-draw] {
  transition-delay: 480ms;
}
.svc-grid .reveal-child:nth-of-type(6) .svc-icon svg path[data-draw],
.attr-grid .reveal-child:nth-of-type(6) .attr-icon svg path[data-draw] {
  transition-delay: 600ms;
}
[data-count] {
  font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: reduce) {
  .svc-icon svg path[data-draw],
  .attr-icon svg path[data-draw] {
    stroke-dashoffset: 0 !important;
    transition: none !important;
  }
}

/* ─── §5.5 REVIEWS CAROUSEL ─────────────────────────────────────────
   Existing .rev-carousel already provides horizontal scroll snap.
   We add 6s auto-advance (JS), star-row fill-in on viewport enter
   (left-to-right 80ms stagger, ease-out-back scale 0.8→1), and
   barely-visible dot affordance with chevrons fading in on hover. */
.rev-carousel-wrap {
  /* When carousel hovered/focused/touched, dim nav-chevrons revealed. */
  --rev-nav-opacity: 0;
}
.rev-carousel-wrap:hover,
.rev-carousel-wrap:focus-within {
  --rev-nav-opacity: 1;
}
.rev-nav {
  opacity: var(--rev-nav-opacity);
  transition:
    opacity 240ms var(--ease-out-expo),
    background-color 200ms,
    color 200ms,
    transform 200ms;
}
@media (hover: none) {
  /* Touch devices: keep chevrons visible (no hover surface). */
  .rev-carousel-wrap {
    --rev-nav-opacity: 0.85;
  }
}
.rev-stars {
  /* Stars become character-spans rendered as inline-block so each can scale. */
  position: relative;
}
.rev-stars .rev-star {
  display: inline-block;
  opacity: 0;
  transform: scale(0.8);
  transition:
    opacity 220ms var(--ease-out-back),
    transform 220ms var(--ease-out-back);
}
.rev-card.is-in .rev-stars .rev-star,
.reveal-child.is-in .rev-stars .rev-star {
  opacity: 1;
  transform: scale(1);
}
.rev-card.is-in .rev-stars .rev-star:nth-child(1),
.reveal-child.is-in .rev-stars .rev-star:nth-child(1) {
  transition-delay: 0ms;
}
.rev-card.is-in .rev-stars .rev-star:nth-child(2),
.reveal-child.is-in .rev-stars .rev-star:nth-child(2) {
  transition-delay: 80ms;
}
.rev-card.is-in .rev-stars .rev-star:nth-child(3),
.reveal-child.is-in .rev-stars .rev-star:nth-child(3) {
  transition-delay: 160ms;
}
.rev-card.is-in .rev-stars .rev-star:nth-child(4),
.reveal-child.is-in .rev-stars .rev-star:nth-child(4) {
  transition-delay: 240ms;
}
.rev-card.is-in .rev-stars .rev-star:nth-child(5),
.reveal-child.is-in .rev-stars .rev-star:nth-child(5) {
  transition-delay: 320ms;
}
@media (prefers-reduced-motion: reduce) {
  .rev-stars .rev-star {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .rev-nav {
    transition: opacity 150ms ease !important;
  }
}

/* ─── §5.6 BOOKING / PRICING PANEL ──────────────────────────────────
   Extra-guests pill keeps the dashed border but layered with an
   animated rotating dashed flow via background-image gradient
   (no border keyframe). Pulse on increment past 0; row stagger
   on dates change (JS adds .is-stagger class); total cross-fade;
   three-dot wave loader for the Confirm button. */
.bk-xguests {
  position: relative;
  isolation: isolate;
  transition:
    transform 350ms var(--ease-out-back),
    border-color 200ms ease,
    background 200ms ease;
}
.bk-xguests::before {
  /* Dashed-flow overlay — two horizontal repeating-gradient strokes
     (top + bottom edges of the pill). Animation drives background-
     position only, which composites cheaply (no layout, no paint of
     the gradient image — just a re-blit on the GPU). */
  content: "";
  position: absolute;
  inset: -1.5px;
  border-radius: inherit;
  background-image:
    repeating-linear-gradient(
      90deg,
      rgba(74, 93, 35, 0.22) 0 6px,
      transparent 6px 12px
    ),
    repeating-linear-gradient(
      90deg,
      rgba(74, 93, 35, 0.22) 0 6px,
      transparent 6px 12px
    );
  background-size:
    200% 1.5px,
    200% 1.5px;
  background-position:
    0 0,
    0 100%;
  background-repeat: no-repeat, no-repeat;
  animation: dashFlow 8s linear infinite;
  pointer-events: none;
  z-index: -1;
  opacity: 0.65;
}
@keyframes dashFlow {
  0% {
    background-position:
      0 0,
      0 100%;
  }
  100% {
    background-position:
      200% 0,
      -200% 100%;
  }
}
.bk-xguests.is-pulsing {
  animation: bkPulse 350ms var(--ease-out-back);
  will-change: transform;
}
@keyframes bkPulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.015);
  }
  100% {
    transform: scale(1);
  }
}
/* Price breakdown row stagger when dates change — JS adds .is-stagger. */
#breakdown.is-stagger .bk-row,
#breakdown.is-stagger .bk-total {
  animation: bkRowIn 360ms var(--ease-out-expo) both;
}
#breakdown.is-stagger .bk-row:nth-of-type(1) {
  animation-delay: 0ms;
}
#breakdown.is-stagger .bk-row:nth-of-type(2) {
  animation-delay: 80ms;
}
#breakdown.is-stagger .bk-row:nth-of-type(3) {
  animation-delay: 160ms;
}
#breakdown.is-stagger .bk-row:nth-of-type(4) {
  animation-delay: 240ms;
}
#breakdown.is-stagger .bk-total {
  animation-delay: 320ms;
}
@keyframes bkRowIn {
  from {
    opacity: 0;
    transform: translateX(16px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
/* Total numeric cross-fade — old slides up + fades, new slides up from below. */
.bk-total .bk-tot-num {
  display: inline-block;
  position: relative;
  min-width: 1ch;
}
.bk-total .bk-tot-num.is-cross-old {
  animation: bkTotalOut 240ms var(--ease-in-quart) both;
}
.bk-total .bk-tot-num.is-cross-new {
  animation: bkTotalIn 280ms var(--ease-out-expo) both;
}
@keyframes bkTotalOut {
  from {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  to {
    opacity: 0;
    transform: translateY(-6px) scale(1.04);
  }
}
@keyframes bkTotalIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* Three-dot wave loader for Confirm button (and any other olive CTA).
   Built from three child .bk-dot pseudo-elements via a flexbox container
   so each dot can transform independently — composite-cheap. JS toggles
   .is-loading and injects the three-dot DOM, OR we keep this simple
   CSS-only version using three pseudo-elements: ::before, ::after on
   the host plus a single child wrapper isn't available without DOM.
   Simplest robust solution: three transform-animated children rendered
   via a single radial-gradient backdrop on the pseudo-element, with
   a discrete-step animation that visually communicates the wave. */
.bk-go.is-loading,
.ncta.is-loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}
.bk-go.is-loading::after,
.ncta.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56px;
  height: 12px;
  transform: translate(-50%, -50%);
  /* Three filled dots, each centred vertically by `100%` background-size
     and a y-shift in the animation. */
  background-image:
    radial-gradient(circle 4px at center, #fff 60%, transparent 65%),
    radial-gradient(circle 4px at center, #fff 60%, transparent 65%),
    radial-gradient(circle 4px at center, #fff 60%, transparent 65%);
  background-repeat: no-repeat, no-repeat, no-repeat;
  background-size:
    12px 12px,
    12px 12px,
    12px 12px;
  background-position:
    0 0,
    22px 0,
    44px 0;
  animation: bkDotsWave 1.2s var(--ease-in-out-quart) infinite;
}
@keyframes bkDotsWave {
  0%,
  75%,
  100% {
    background-position:
      0 0,
      22px 0,
      44px 0;
    opacity: 0.85;
  }
  15% {
    background-position:
      0 -6px,
      22px 0,
      44px 0;
    opacity: 1;
  }
  35% {
    background-position:
      0 0,
      22px -6px,
      44px 0;
    opacity: 1;
  }
  55% {
    background-position:
      0 0,
      22px 0,
      44px -6px;
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .bk-xguests::before {
    animation: none !important;
  }
  .bk-xguests.is-pulsing {
    animation: none !important;
  }
  #breakdown.is-stagger .bk-row,
  #breakdown.is-stagger .bk-total,
  .bk-total .bk-tot-num.is-cross-old,
  .bk-total .bk-tot-num.is-cross-new {
    animation: none !important;
  }
  .bk-go.is-loading::after,
  .ncta.is-loading::after {
    animation: none !important;
    opacity: 0.8;
  }
}

/* ─── §5.7 FAQ ACCORDION ────────────────────────────────────────────
   We layer a new grid-template-rows accordion on top of the existing
   max-height implementation. The .faq-a still uses max-height as
   fallback, but when wrapped (via JS) in a .faq-a-wrap with display:grid
   the row template animates 0fr → 1fr smoothly. Chevron rotates
   0→180° via transform. Olive-3 tint fades in on the whole item. */
.faq-i {
  position: relative;
  isolation: isolate;
}
.faq-i::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--olive-3);
  opacity: 0;
  transition: opacity 200ms var(--ease-out-expo);
  pointer-events: none;
  z-index: -1;
}
.faq-i.active::before,
.faq-i.is-open::before {
  opacity: 1;
}
.faq-q .faq-toggle {
  /* Rotate 0 → 180° per brief (legacy uses 45° + glyph; this still
     works because the icon glyph is "+", which becomes a vertical bar
     pivot point. We override to use rotate(180deg) on .is-open). */
  transition: transform 300ms var(--ease-out-expo);
}
.faq-i.is-open .faq-q .faq-toggle {
  transform: rotate(180deg);
}
/* The grid-template-rows accordion — when JS wraps .faq-a in .faq-a-wrap. */
.faq-a-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 320ms var(--ease-out-expo);
}
.faq-i.is-open .faq-a-wrap {
  grid-template-rows: 1fr;
}
.faq-a-wrap > .faq-a {
  overflow: hidden;
  min-height: 0;
  max-height: none;
  opacity: 0;
  transition: opacity 220ms var(--ease-out-expo) 100ms;
}
.faq-i.is-open .faq-a-wrap > .faq-a {
  padding: 4px 20px 16px;
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .faq-i::before,
  .faq-q .faq-toggle,
  .faq-a-wrap,
  .faq-a-wrap > .faq-a {
    transition: none !important;
  }
}

/* ─── §5.8 FOOTER ───────────────────────────────────────────────────
   Per brief §5.8: multi-column layout with soft olive-3 background.
   We add the "Made with ♥ in Siquijor" script-gold flourish, social
   icons monochrome→tinted hover (no scale, 120ms), and a newsletter
   focus underline (gold scaleX(0)→(1)) if a .ft-newsletter form is
   added. All text colors flipped from white-on-dark (legacy WIP) to
   dark-on-pale to read against olive-3. */
.ft-made {
  /* Playfair italic flourish (was Pacifico — removed site-wide). */
  font-family: var(--serif);
  font-style: italic;
  /* Phase L (a11y) — Lighthouse caught this: gold #C8A951 on the pale
     olive-3 footer bg measures ~1.6:1, which FAILS 4.5:1 (the old
     "passes WCAG AA" comment was wrong). Olive #4A5D23 on olive-3
     passes ~6:1 and preserves the script-font signature. The gold heart
     ⓘ below stays gold for the brand accent — it's decorative and
     marked aria-hidden by surrounding context. */
  color: var(--olive);
  font-size: 13px;
  letter-spacing: 0.5px;
}
.ft-made .ft-heart {
  display: inline-block;
  color: var(--gold);
  margin: 0 2px;
  animation: ftHeart 2.4s ease-in-out infinite;
  transform-origin: center;
}
@keyframes ftHeart {
  0%,
  100% {
    transform: scale(1);
  }
  35% {
    transform: scale(1.15);
  }
  70% {
    transform: scale(0.96);
  }
}
.ft-social {
  /* Tint-only hover, no scale (per brief). */
  transition:
    background-color 120ms var(--ease-out-expo),
    color 120ms var(--ease-out-expo),
    border-color 120ms var(--ease-out-expo);
}
.ft-social:hover {
  transform: none; /* override legacy translateY(-2px) per brief */
  box-shadow: none;
}
/* Newsletter input — gold underline scales in from left on focus. */
.ft-newsletter {
  position: relative;
  display: inline-block;
}
.ft-newsletter input {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--olive-20);
  color: var(--text-d);
  padding: 10px 0;
  font-family: var(--sans);
  font-size: 14px;
  width: 240px;
  outline: none;
}
.ft-newsletter input::placeholder {
  color: var(--text-m);
}
.ft-newsletter::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease-out-expo);
  pointer-events: none;
}
.ft-newsletter:focus-within::after {
  transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
  .ft-made .ft-heart {
    animation: none !important;
  }
  .ft-social,
  .ft-newsletter::after {
    transition: none !important;
  }
}
/* === END SECTION POLISH §5 (Phase 4) === */

/* ═══════════════════════════════════════════════════════════════════
   §6 AUTH (Phase 5) — Cinematic redesign per CLAUDE_DESIGN_PROMPT_v2
   Re-skins .auth-page / .auth-card / .auth-form without renaming
   classes. Preserves Firebase auth markup; no JS class names changed.
   All motion uses transform / opacity / filter (+ stroke-dashoffset
   for SVG draw-in, which is composite-cheap and brief-approved).
   Motion cheat-sheet ladder = §6.13.
   ═══════════════════════════════════════════════════════════════════ */

/* — Visually-hidden helper for SR-only labels (§6.12). — */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* §6.2 BACKGROUND ─────────────────────────────────────────────── */
.auth-page {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh; /* §6.11 iOS safe area / keyboard */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: hidden;
  background: var(--cream);
  isolation: isolate;
}
/* Neutralize the legacy ::before / ::after corner orbs from the old
   auth styles so they don't compete with the new background. */
.auth-page::before,
.auth-page::after {
  content: none !important;
  display: none !important;
}
.auth-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  animation: authBgFade 1000ms var(--ease-out-expo) 0ms 1 both;
}
.auth-bg__gradient {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      120% 80% at 50% 45%,
      var(--cream) 0%,
      var(--cream) 32%,
      var(--olive-3) 78%,
      rgba(200, 169, 81, 0.1) 100%
    ),
    radial-gradient(
      60% 40% at 50% 100%,
      rgba(200, 169, 81, 0.06) 0%,
      transparent 70%
    );
}
/* 3% grain — same SVG-noise data-URI pattern as the hero. */
.auth-bg__grain {
  position: absolute;
  inset: 0;
  opacity: 0.03;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
}
/* Centered gold halo — 400px, soft-light, ±5% radius pulse over 6s. */
.auth-bg__glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 400px;
  height: 400px;
  margin-left: -200px;
  margin-top: -200px;
  background: radial-gradient(
    circle,
    var(--gold) 0%,
    rgba(200, 169, 81, 0.35) 35%,
    transparent 70%
  );
  border-radius: 50%;
  mix-blend-mode: soft-light;
  opacity: 0.18;
  filter: blur(8px);
  animation: authGlowPulse 6000ms var(--ease-in-out-quart) infinite;
  transform-origin: center;
  will-change: transform, opacity;
}
/* Corner leaves — silhouettes that sway gently. */
.auth-bg__leaf {
  position: absolute;
  width: 240px;
  height: 240px;
  opacity: 0;
  transform-origin: 30% 70%;
  filter: blur(0.3px);
  animation:
    authBgFade 1000ms var(--ease-out-expo) 0ms 1 both,
    authLeafSway 9000ms var(--ease-in-out-quart) 800ms infinite;
  will-change: transform, opacity;
}
.auth-bg__leaf--tl {
  top: -40px;
  left: -40px;
  transform: rotate(-6deg);
}
.auth-bg__leaf--br {
  bottom: -60px;
  right: -60px;
  width: 280px;
  height: 280px;
  transform: rotate(8deg) scaleX(-1);
  transform-origin: 70% 30%;
  animation:
    authBgFade 1000ms var(--ease-out-expo) 0ms 1 both,
    authLeafSway 11000ms var(--ease-in-out-quart) 1200ms infinite;
  animation-delay: 0ms, 1200ms;
}
@keyframes authBgFade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes authGlowPulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.16;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.22;
  }
}
@keyframes authLeafSway {
  0%,
  100% {
    transform: rotate(-6deg) translateX(0);
  }
  50% {
    transform: rotate(-4deg) translateX(2px);
  }
}
.auth-bg__leaf--br {
  /* Override the keyframe to use the mirrored base rotation. */
  animation-name: authBgFade, authLeafSwayR;
}
@keyframes authLeafSwayR {
  0%,
  100% {
    transform: rotate(8deg) scaleX(-1) translateX(0);
  }
  50% {
    transform: rotate(6deg) scaleX(-1) translateX(-2px);
  }
}

/* §6.3 AUTH CARD ─────────────────────────────────────────────── */
.auth-page .auth-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  padding: 40px;
  background: rgba(255, 255, 255, 0.95);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  backdrop-filter: blur(20px) saturate(1.1);
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: var(--r);
  box-shadow:
    0 32px 64px -16px rgba(74, 93, 35, 0.18),
    0 8px 16px -4px rgba(74, 93, 35, 0.1),
    0 1px 2px rgba(0, 0, 0, 0.03);
  /* Override the legacy `animation: fadeUp ...` from the old auth block. */
  animation: none;
  transition:
    transform 320ms var(--ease-out-expo),
    box-shadow 320ms var(--ease-out-expo);
}
/* Scoped under .auth-page to match the specificity (0,2,0) of the
   .auth-page .auth-card rule above. Otherwise that rule's
   'animation: none' (which was intended only to override the legacy
   .auth-card fadeUp) wins by specificity and the entrance animation
   never runs, leaving the card stuck at opacity:0 forever. */
.auth-page .auth-card--enter {
  opacity: 0;
  transform: translateY(24px) scale(0.96);
  animation: authCardEnter 720ms var(--ease-out-expo) 120ms 1 forwards;
  will-change: transform, opacity;
}
@keyframes authCardEnter {
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
/* Desktop hover lift (≥768px in §6.11). */
@media (hover: hover) and (min-width: 768px) {
  .auth-page .auth-card:hover {
    transform: translateY(-2px);
    box-shadow:
      0 36px 72px -16px rgba(74, 93, 35, 0.2),
      0 10px 20px -4px rgba(74, 93, 35, 0.11),
      0 1px 2px rgba(0, 0, 0, 0.03);
  }
}

/* §6.4 BRAND HEADER ─────────────────────────────────────────── */
.auth-page .auth-brand {
  text-align: center;
  margin-bottom: 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* Replace the legacy emoji disc — the inline SVG is now centered in
   an olive-3 circle with a pulsing gold ring. */
.auth-page .auth-brand .auth-icon {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: var(--olive-3);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  margin: 0 auto 16px;
  font-size: 0; /* nullify legacy emoji size */
  color: transparent; /* nullify legacy text-color */
  isolation: isolate;
  opacity: 0;
  transform: scale(0.96);
  animation:
    authIconBox 520ms var(--ease-out-expo) 200ms 1 forwards,
    authIconBreath 4000ms var(--ease-in-out-quart) 1400ms infinite;
  will-change: transform, opacity;
}
.auth-page .auth-brand .auth-icon::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--gold);
  opacity: 0.4;
  animation: authGoldRing 3000ms var(--ease-in-out-quart) 1800ms infinite;
  pointer-events: none;
}
.auth-icon-svg {
  width: 64px;
  height: 64px;
  display: block;
}
.auth-icon-shape {
  /* Brief approves stroke-dashoffset for SVG draw-in (composite-cheap). */
  animation: authIconDraw 900ms var(--ease-out-expo) 280ms 1 forwards;
}
.auth-icon-accent {
  animation: authIconAccent 300ms var(--ease-out-expo) 1100ms 1 forwards;
}
@keyframes authIconBox {
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes authIconBreath {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.03);
  }
}
@keyframes authIconDraw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes authIconAccent {
  to {
    opacity: 1;
  }
}
@keyframes authGoldRing {
  0%,
  100% {
    opacity: 0.4;
    transform: scale(1);
  }
  50% {
    opacity: 0.7;
    transform: scale(1.04);
  }
}

.auth-page .auth-brand h1,
.auth-brand__title {
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 600;
  color: var(--olive);
  letter-spacing: -0.5px;
  line-height: 1.15;
  /* Shimmer reveal — one-shot, then settles to solid color. */
  background: linear-gradient(
    90deg,
    var(--olive) 0%,
    var(--olive) 33%,
    var(--gold) 50%,
    var(--olive) 67%,
    var(--olive) 100%
  );
  background-size: 300% 100%;
  background-position: 100% 0;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: authBrandShimmer 1400ms var(--ease-out-expo) 600ms 1 both;
  will-change: background-position;
}
@keyframes authBrandShimmer {
  0% {
    background-position: 100% 0;
    opacity: 0;
    transform: translateY(4px);
  }
  20% {
    opacity: 1;
    transform: translateY(0);
  }
  100% {
    background-position: -100% 0;
    opacity: 1;
    transform: translateY(0);
  }
}
.auth-page .auth-brand p,
.auth-brand__sub {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-m);
  margin-top: 4px;
  opacity: 0;
  transform: translateY(8px);
  animation: authFadeUp 200ms var(--ease-out-expo) 1200ms 1 forwards;
}
@keyframes authFadeUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* §6.5 FORM BODY ─────────────────────────────────────────────── */
.auth-page .auth-form {
  /* Override the legacy white card — the auth-card itself is the surface now. */
  background: transparent;
  padding: 0;
  border-radius: 0;
  box-shadow: none;
  border: none;
}
.auth-page .auth-form h2 {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 600;
  color: var(--text-d);
  text-align: left;
  margin: 0 0 20px;
  opacity: 0;
  transform: translateY(12px);
  animation: authFadeUp 400ms var(--ease-out-expo) 1100ms 1 forwards;
}

/* §6.5.1 fields. */
.auth-page .auth-field {
  position: relative;
  margin-bottom: 14px;
  opacity: 0;
  transform: translateY(10px);
  animation: authFadeUp 320ms var(--ease-out-expo) forwards;
}
/* §6.5.3 field stagger. Signup f1..f4, login f1..f2. */
.auth-page .auth-field[data-auth-step="f1"] {
  animation-delay: 1250ms;
}
.auth-page .auth-field[data-auth-step="f2"] {
  animation-delay: 1330ms;
}
.auth-page .auth-field[data-auth-step="f3"] {
  animation-delay: 1410ms;
}
.auth-page .auth-field[data-auth-step="f4"] {
  animation-delay: 1490ms;
}

.auth-page .auth-field label {
  display: block;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-m);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin: 0 0 6px;
  transition: color 200ms var(--ease-out-expo);
}
.auth-page .auth-field input {
  width: 100%;
  height: 48px;
  padding: 0 16px;
  font-family: var(--sans);
  font-size: 16px; /* >=16px so iOS Safari doesn't auto-zoom on focus (booking-critical auth path) */
  color: var(--text-d);
  background: #fff;
  border: 1.5px solid var(--brd);
  border-radius: var(--rs);
  outline: none;
  transition:
    border-color 240ms var(--ease-out-expo),
    box-shadow 240ms var(--ease-out-expo),
    background-color 240ms var(--ease-out-expo);
}
.auth-page .auth-field input::placeholder {
  color: var(--text-m);
}
.auth-page .auth-field input:hover {
  border-color: rgba(74, 93, 35, 0.25);
}
.auth-page .auth-field input:focus,
.auth-page .auth-field input:focus-visible {
  border-color: var(--olive);
  background: #fff;
  box-shadow: 0 0 0 4px rgba(74, 93, 35, 0.08);
}
.auth-page .auth-field input:focus + .pw-eye,
.auth-page .auth-field .pw-wrap:focus-within label {
  /* future-proof */
}
.auth-page .auth-field:focus-within label {
  color: var(--text-s);
}
/* Filled-state label shift (when input has any value). */
.auth-page .auth-field:has(input:not(:placeholder-shown)) label {
  color: var(--text-s);
}
/* Left-edge accent bar — scales vertically on focus. */
.auth-page .auth-field::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%) scaleY(0);
  width: 3px;
  height: 60%;
  border-radius: 2px;
  background: var(--olive);
  transition: transform 280ms var(--ease-out-expo);
  pointer-events: none;
  /* Anchor relative to the input bottom, not the label. */
  margin-top: 12px; /* visual nudge below the 18px label area */
  will-change: transform;
}
.auth-page .auth-field:focus-within::before {
  transform: translateY(-50%) scaleY(1);
}
/* Validation error visuals. */
.auth-page .auth-field.is-error input,
.auth-page .auth-field[data-error] input {
  border-color: #dc2626;
}
.auth-page .auth-field.is-error::before,
.auth-page .auth-field[data-error]::before {
  background: #dc2626;
  transform: translateY(-50%) scaleY(1);
}
.auth-page .auth-field.is-error {
  animation: authFieldShake 280ms var(--ease-in-out-quart);
}
@keyframes authFieldShake {
  0% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-4px);
  }
  50% {
    transform: translateX(4px);
  }
  75% {
    transform: translateX(-3px);
  }
  100% {
    transform: translateX(0);
  }
}
/* Disabled state. */
.auth-page .auth-field input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background: #f7f7f5;
}
/* Autofill — override browser yellow + restore brand text colour. */
.auth-page .auth-field input:-webkit-autofill,
.auth-page .auth-field input:-webkit-autofill:hover,
.auth-page .auth-field input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #ffffff inset !important;
  box-shadow: 0 0 0 1000px #ffffff inset !important;
  -webkit-text-fill-color: var(--text-d) !important;
  transition:
    background-color 9999s ease-out,
    color 9999s ease-out;
  caret-color: var(--text-d);
}

/* §6.5.2 password field — eye toggle. */
.auth-page .pw-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.auth-page .pw-wrap input {
  flex: 1;
  padding-right: 48px;
}
.auth-page .pw-eye {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-m);
  padding: 6px;
  cursor: pointer;
  border-radius: 50%;
  transition:
    color 150ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo),
    background-color 150ms var(--ease-out-expo);
  font-size: 0; /* nullify legacy emoji */
}
.auth-page .pw-eye svg {
  width: 20px;
  height: 20px;
  transition:
    transform 280ms var(--ease-in-out-quart),
    opacity 200ms var(--ease-out-expo);
}
.auth-page .pw-eye:hover {
  color: var(--olive);
  background: var(--olive-3);
}
.auth-page .pw-eye:active {
  transform: translateY(-50%) scale(0.92);
}
.auth-page .pw-eye:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
}
.auth-page .pw-eye.pw-eye--morph svg {
  transform: rotate(180deg) scale(0.6);
  opacity: 0;
}

/* §6.6 ERROR BANNER ─────────────────────────────────────────── */
.auth-page .auth-error {
  /* Override legacy padding/animation to match §6.6 spec. */
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #991b1b;
  padding: 12px 14px;
  border-radius: var(--rs);
  font-size: 13px;
  line-height: 1.4;
  margin-bottom: 16px;
  overflow: hidden;
  animation: authErrorIn 280ms var(--ease-out-expo) 1 both;
  will-change: transform, opacity;
}
.auth-error__icon {
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: #dc2626;
  background: rgba(220, 38, 38, 0.1);
  border-radius: 50%;
  font-size: 11px;
  line-height: 1;
  margin-top: 1px;
}
.auth-error__text {
  flex: 1;
}
.auth-error--dismiss {
  animation: authErrorOut 200ms var(--ease-out-expo) 1 forwards;
}
@keyframes authErrorIn {
  from {
    opacity: 0;
    transform: translateY(-8px);
    max-height: 0;
  }
  to {
    opacity: 1;
    transform: translateY(0);
    max-height: 100px;
  }
}
@keyframes authErrorOut {
  from {
    opacity: 1;
    transform: translateY(0);
    max-height: 100px;
  }
  to {
    opacity: 0;
    transform: translateY(-4px);
    max-height: 0;
  }
}

/* §6.7 SUBMIT BUTTON ────────────────────────────────────────── */
.auth-page .auth-submit {
  position: relative;
  width: 100%;
  height: 50px;
  padding: 0 24px;
  margin-top: 12px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(135deg, var(--olive) 0%, #5a7a2e 100%);
  border: none;
  border-radius: var(--rs);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.15),
    0 8px 20px -6px rgba(74, 93, 35, 0.35);
  cursor: pointer;
  overflow: hidden;
  opacity: 0;
  transform: translateY(10px);
  animation: authFadeUp 400ms var(--ease-out-expo) 1600ms 1 forwards;
  transition:
    transform 200ms var(--ease-out-expo),
    box-shadow 300ms var(--ease-out-expo),
    filter 200ms var(--ease-out-expo);
  will-change: transform;
}
/* Gold edge-glow ring on hover — pseudo-element opacity, not box-shadow keyframe. */
.auth-page .auth-submit::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    135deg,
    rgba(200, 169, 81, 0.6),
    rgba(200, 169, 81, 0.15)
  );
  filter: blur(6px);
  z-index: -1;
  transition: opacity 300ms var(--ease-out-expo);
}
.auth-page .auth-submit:hover:not(:disabled) {
  transform: translateY(-1px);
  filter: brightness(1.04);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 12px 28px -6px rgba(74, 93, 35, 0.45);
  /* Override the legacy hover that set background: var(--olive-60). */
  background: linear-gradient(135deg, #51682b 0%, #648432 100%);
}
.auth-page .auth-submit:hover:not(:disabled)::after {
  opacity: 1;
}
.auth-page .auth-submit:active:not(:disabled) {
  transform: translateY(1px) scale(0.99);
  transition-duration: 100ms;
}
.auth-page .auth-submit:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 3px;
}
.auth-page .auth-submit:disabled {
  cursor: progress;
  opacity: 0.95;
  filter: none;
  transform: none;
}
.auth-page .auth-submit.is-loading {
  pointer-events: none;
}
.auth-submit__label {
  display: inline-block;
  transition: opacity 150ms var(--ease-out-expo);
}
.auth-submit.is-loading .auth-submit__label {
  opacity: 0;
}

/* 3-dot pulse loader. */
.auth-submit__dots {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  gap: 6px;
  align-items: center;
}
.auth-submit__dots span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
  display: inline-block;
  animation: authDotPulse 1200ms var(--ease-in-out-quart) infinite;
}
.auth-submit__dots span:nth-child(1) {
  animation-delay: 0ms;
}
.auth-submit__dots span:nth-child(2) {
  animation-delay: 180ms;
}
.auth-submit__dots span:nth-child(3) {
  animation-delay: 360ms;
}
@keyframes authDotPulse {
  0%,
  100% {
    transform: scale(0.6);
    opacity: 0.55;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

/* §6.8 — neutralize the old circular spinner inside .auth-submit so
   we don't double-render with the new dots. The .auth-spinner span
   is no longer emitted by renderAuth(), but a defensive rule keeps
   anything stray invisible. */
.auth-page .auth-submit .auth-spinner {
  display: none;
}

/* §6.9 SWITCH LINK ────────────────────────────────────────── */
.auth-page .auth-switch {
  text-align: center;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--brd-l);
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-m);
  opacity: 0;
  transform: translateY(6px);
  animation: authFadeUp 400ms var(--ease-out-expo) 1800ms 1 forwards;
}
.auth-page .auth-switch button {
  position: relative;
  background: none;
  border: none;
  color: var(--olive);
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  padding: 2px 4px;
  margin-left: 4px;
  cursor: pointer;
  transition:
    color 200ms var(--ease-out-expo),
    transform 150ms var(--ease-out-expo);
}
.auth-page .auth-switch button::after {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: -1px;
  height: 1.5px;
  background: var(--olive);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease-out-expo);
}
.auth-page .auth-switch button:hover {
  color: #3d4e1d;
  text-decoration: none; /* override legacy underline */
}
.auth-page .auth-switch button:hover::after {
  transform: scaleX(1);
}
.auth-page .auth-switch button:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
  border-radius: 4px;
}
.auth-page .auth-switch button:active {
  transform: scale(0.98);
}

/* §6.10 VIEW TRANSITION ─────────────────────────────────────── */
.auth-form--exit {
  animation: authFormExit 220ms var(--ease-in-quart) 1 forwards;
}
.auth-form--exit-left {
  animation-name: authFormExitLeft;
}
.auth-form--exit-right {
  animation-name: authFormExitRight;
}
.auth-form--enter-left {
  animation: authFormEnterLeft 320ms var(--ease-out-expo) 1 both;
}
.auth-form--enter-right {
  animation: authFormEnterRight 320ms var(--ease-out-expo) 1 both;
}
@keyframes authFormExitLeft {
  from {
    opacity: 1;
    transform: translateX(0);
  }
  to {
    opacity: 0;
    transform: translateX(-12px);
  }
}
@keyframes authFormExitRight {
  from {
    opacity: 1;
    transform: translateX(0);
  }
  to {
    opacity: 0;
    transform: translateX(12px);
  }
}
@keyframes authFormEnterLeft {
  from {
    opacity: 0;
    transform: translateX(-12px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
@keyframes authFormEnterRight {
  from {
    opacity: 0;
    transform: translateX(12px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* §6.11 RESPONSIVE ─────────────────────────────────────────── */
/* Tablet (600-767px). */
@media (max-width: 767px) and (min-width: 600px) {
  .auth-page .auth-card {
    max-width: 420px;
    padding: 36px 28px;
  }
}
/* Mobile (<600px) — drop corner leaves, tighter card. */
@media (max-width: 599px) {
  .auth-page {
    padding: 20px;
  }
  .auth-page .auth-card {
    max-width: 100%;
    padding: 32px 22px;
  }
  .auth-page .auth-brand .auth-icon {
    width: 68px;
    height: 68px;
  }
  .auth-icon-svg {
    width: 52px;
    height: 52px;
  }
  .auth-page .auth-brand h1,
  .auth-brand__title {
    font-size: 22px;
  }
  .auth-bg__leaf {
    display: none;
  }
  /* Maintain 44×44 tap target for the eye toggle. */
  .auth-page .pw-eye {
    width: 44px;
    height: 44px;
    right: 2px;
  }
}
/* Existing legacy override (.auth-form padding 20px) at <380px is
   harmless — the form is now transparent. */

/* §6.12 ACCESSIBILITY + REDUCED MOTION ──────────────────────── */
.auth-page input:focus-visible,
.auth-page button:focus-visible {
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  /* Disable decorative motion. Card retains a tiny opacity fade. */
  .auth-bg__leaf,
  .auth-bg__glow {
    animation: none !important;
  }
  .auth-bg {
    opacity: 1 !important;
    animation: none !important;
  }
  .auth-page .auth-brand .auth-icon {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  .auth-page .auth-brand .auth-icon::before {
    animation: none !important;
  }
  .auth-icon-shape {
    stroke-dashoffset: 0 !important;
    animation: none !important;
  }
  .auth-icon-accent {
    opacity: 1 !important;
    animation: none !important;
  }
  .auth-page .auth-brand h1,
  .auth-brand__title {
    animation: none !important;
    background: none !important;
    -webkit-text-fill-color: var(--olive) !important;
    color: var(--olive) !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .auth-page .auth-brand p,
  .auth-brand__sub,
  .auth-page .auth-form h2,
  .auth-page .auth-field,
  .auth-page .auth-submit,
  .auth-page .auth-switch {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  .auth-card--enter {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  /* View transition becomes instant. */
  .auth-form--exit,
  .auth-form--exit-left,
  .auth-form--exit-right,
  .auth-form--enter-left,
  .auth-form--enter-right {
    animation: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════
   PHASE 6 — §7 CHATS POLISH
   ═══════════════════════════════════════════════════════════════ */

/* §7.1 + §7.2 — Section header gold pill accent ─────────────── */
.chat-sec-hd {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
}
.chat-sec-hd .chat-sec-pill {
  display: inline-block;
  width: 4px;
  height: 20px;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--gold), #b3923c);
  flex-shrink: 0;
  align-self: stretch;
  margin: 6px 0;
  animation: chatPillGrow 0.4s var(--ease-out-expo) 0.05s forwards;
  transform-origin: top center;
}
@keyframes chatPillGrow {
  from {
    transform: scaleY(0);
    opacity: 0.4;
  }
  to {
    transform: scaleY(1);
    opacity: 1;
  }
}

/* §7.1 — Notification banner line-art bell ─────────────────── */
.chat-notif-banner {
  background: linear-gradient(135deg, #f3efe1, #ece6d2);
  border-color: rgba(74, 93, 35, 0.18);
}
.chat-notif-icon {
  color: var(--olive);
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.chat-notif-icon .cn-bell {
  width: 28px;
  height: 28px;
  transform-origin: 50% 14%;
  animation: cnBellRing 4s cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
}
@keyframes cnBellRing {
  0%,
  78%,
  100% {
    transform: rotate(0deg);
  }
  82% {
    transform: rotate(-9deg);
  }
  86% {
    transform: rotate(7deg);
  }
  90% {
    transform: rotate(-5deg);
  }
  94% {
    transform: rotate(3deg);
  }
}

/* §7.1 — Isometric guesthouse SVG (replaces 🏠 emoji) ───────── */
.chat-av-house {
  background: linear-gradient(135deg, var(--olive), #5a7a2e);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.chat-av-house .cn-house {
  width: 30px;
  height: 30px;
  stroke-dasharray: 140;
  stroke-dashoffset: 140;
  animation: cnHouseDraw 1.4s var(--ease-out-expo) 0.2s forwards;
}
@keyframes cnHouseDraw {
  to {
    stroke-dashoffset: 0;
  }
}
.cn-house-sm {
  width: 24px;
  height: 24px;
  color: #fff;
}

/* §7.1 + §7.3 — Concentric pulsing online ring ─────────────── */
.chat-online-pulse {
  position: relative;
  width: 10px;
  height: 10px;
  background: transparent;
  display: inline-block;
  vertical-align: middle;
  margin-left: 8px;
}
.chat-online-pulse .chat-online-dot {
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: #22c55e;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.85);
}
.chat-online-pulse .chat-online-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid #22c55e;
  opacity: 0;
  animation: chatOnlineRing 1.6s var(--ease-out-expo) infinite;
}
@keyframes chatOnlineRing {
  0% {
    transform: scale(0.8);
    opacity: 0.6;
  }
  100% {
    transform: scale(2.1);
    opacity: 0;
  }
}

/* §7.1 — Featured card: olive-3 left→right sweep + CTA arrow ── */
.chat-item-featured {
  position: relative;
  isolation: isolate;
}
.chat-item-featured::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    var(--olive-3) 0%,
    rgba(238, 243, 229, 0) 100%
  );
  opacity: 0;
  z-index: 0;
  transform: translateX(-12%);
  transition:
    opacity 0.4s var(--ease-out-expo),
    transform 0.4s var(--ease-out-expo);
  pointer-events: none;
  border-radius: inherit;
}
.chat-item-featured > * {
  position: relative;
  z-index: 1;
}
.chat-item-featured:hover {
  transform: translateY(-4px);
}
.chat-item-featured:hover::before {
  opacity: 1;
  transform: translateX(0);
}
.chat-reply-time {
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-m);
  letter-spacing: 0.01em;
}
.chat-reply-time em {
  font-style: italic;
}
.chat-item-action {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.chat-item-action .cia-arrow {
  display: inline-block;
  transition: transform 0.3s var(--ease-out-expo);
}
.chat-item-featured:hover .chat-item-action {
  background: #43521f;
  color: #fff;
}
.chat-item-featured:hover .cia-arrow {
  transform: translateX(4px);
}

/* §7.2 — Unread count gradient pill (breathes on increase) ─── */
.chat-unread-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 11px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, var(--olive), #5a7a2e);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 1px 3px rgba(74, 93, 35, 0.22);
  letter-spacing: 0.02em;
}
.chat-unread-pill.is-bump {
  animation: chatUnreadBump 0.4s var(--ease-out-back) 1;
}
@keyframes chatUnreadBump {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.08);
  }
  100% {
    transform: scale(1);
  }
}

/* §7.2 — Conversation card stagger + hover sweep + active ──── */
.chat-item {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.chat-item.chat-item-slide {
  animation: chatItemSlideIn 0.34s var(--ease-out-expo) both;
}
@keyframes chatItemSlideIn {
  from {
    opacity: 0;
    transform: translateX(-12px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
.chat-item::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    var(--olive-3) 0%,
    rgba(238, 243, 229, 0) 100%
  );
  opacity: 0;
  transform: translateX(-12%);
  transition:
    opacity 0.4s var(--ease-out-expo),
    transform 0.4s var(--ease-out-expo);
  pointer-events: none;
  z-index: 0;
}
.chat-item > * {
  position: relative;
  z-index: 1;
}
.chat-item:hover {
  transform: translateX(4px);
}
.chat-item:hover::before {
  opacity: 1;
  transform: translateX(0);
}
.chat-item .chat-tm {
  transition:
    color 0.2s var(--ease),
    font-weight 0.2s var(--ease);
}
.chat-item:hover .chat-tm {
  color: var(--text-s);
  font-weight: 600;
}

/* Unread left accent breath. */
.chat-item.unr::after {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 3px;
  background: var(--olive);
  border-radius: 0 3px 3px 0;
  z-index: 2;
  animation: chatUnrAccent 2s ease-in-out infinite;
}
@keyframes chatUnrAccent {
  0%,
  100% {
    opacity: 0.6;
  }
  50% {
    opacity: 1;
  }
}

/* Active chat row. */
.chat-item.is-active {
  background: var(--olive-3);
  border-color: var(--olive-20);
}
.chat-item .chat-active-chev {
  position: absolute;
  right: 18px;
  top: 50%;
  transform: translateY(-50%) translateX(6px);
  font-size: 20px;
  color: var(--olive);
  opacity: 0;
  transition:
    opacity 0.25s var(--ease),
    transform 0.25s var(--ease-out-expo);
  z-index: 3;
}
.chat-item.is-active .chat-active-chev {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

/* Cream ring around guest photo avatars. */
.chat-item.has-photo .chat-av-initial {
  box-shadow:
    0 0 0 2px var(--cream),
    0 0 0 3px rgba(74, 93, 35, 0.08);
}

/* §7.3 — Architectural masked header border ────────────────── */
.chat-header-pro {
  position: relative;
  border-bottom: none;
}
.chat-header-pro::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--olive-20) 18%,
    var(--olive-20) 82%,
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent,
    #000 20%,
    #000 80%,
    transparent
  );
  mask-image: linear-gradient(
    90deg,
    transparent,
    #000 20%,
    #000 80%,
    transparent
  );
  pointer-events: none;
}

/* Back button: gesture-like rotate + translate. */
.chat-header-pro .ch-back .chb-arrow {
  display: inline-block;
  transition: transform 0.25s var(--ease-out-expo);
}
.chat-header-pro .ch-back:hover .chb-arrow {
  transform: translateX(-2px) rotate(-4deg);
}

/* §7.3 — Asymmetric bubbles + entrance keyframe ─────────────── */
.chat-msg-pro {
  animation: chatMsgIn 0.22s var(--ease-out-back) both;
  position: relative;
}
.chat-msg-pro.me {
  background: linear-gradient(135deg, var(--olive), #5a7a2e);
  color: #fff;
  border-radius: 18px 18px 4px 18px;
}
.chat-msg-pro.me .msg-sender {
  color: rgba(255, 255, 255, 0.78);
}
.chat-msg-pro.me .msg-time {
  color: rgba(255, 255, 255, 0.72);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.chat-msg-pro.them {
  background: var(--cream);
  border: 1px solid var(--olive-10);
  color: var(--text);
  border-radius: 18px 18px 18px 4px;
}
.chat-msg-pro .msg-time {
  opacity: 0;
  transform: translateY(2px);
  transition:
    opacity 0.15s var(--ease),
    transform 0.15s var(--ease);
}
.chat-msg-pro:hover .msg-time,
.chat-msg-pro:focus-within .msg-time,
.chat-msg-pro:active .msg-time {
  opacity: 1;
  transform: translateY(0);
}
@keyframes chatMsgIn {
  0% {
    opacity: 0;
    transform: translateY(12px) scale(0.96);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
.msg-tick {
  display: inline-flex;
  width: 14px;
  height: 8px;
  color: rgba(255, 255, 255, 0.9);
  opacity: 0;
  animation: chatTickIn 0.3s var(--ease-out-expo) 0.3s forwards;
}
.msg-tick svg {
  width: 100%;
  height: 100%;
}
@keyframes chatTickIn {
  from {
    opacity: 0;
    transform: translateY(1px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* §7.3 — Typing indicator polish (3-dot stagger, label fade) ── */
.typing-row-pro .typing-bubble {
  background: var(--cream);
  border: 1px solid var(--olive-10);
  border-radius: 18px 18px 18px 4px;
  padding: 10px 14px;
}
.typing-row-pro .typing-dot {
  width: 7px;
  height: 7px;
  background: var(--olive);
  animation: chatTypingDot 1.4s ease-in-out infinite both;
}
.typing-row-pro .typing-dot:nth-child(1) {
  animation-delay: 0s;
}
.typing-row-pro .typing-dot:nth-child(2) {
  animation-delay: 0.2s;
}
.typing-row-pro .typing-dot:nth-child(3) {
  animation-delay: 0.4s;
}
@keyframes chatTypingDot {
  0%,
  80%,
  100% {
    transform: scale(0.6);
    opacity: 0.35;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}
.typing-row-pro .typing-label {
  opacity: 0.6;
  animation: chatTypingLabel 0.35s var(--ease-out-expo) both;
}
@keyframes chatTypingLabel {
  from {
    opacity: 0;
    transform: translateX(-3px);
  }
  to {
    opacity: 0.6;
    transform: translateX(0);
  }
}

/* §7.3 — Input bar: focus grow + pill silhouette ───────────── */
.chat-input-bar-pro {
  background: var(--cream);
  border-top: 1px solid var(--olive-10);
}
.chat-input-bar-pro input {
  border-radius: 100px;
  box-shadow: inset 0 1px 2px rgba(74, 93, 35, 0.06);
  transition:
    border-color 0.25s var(--ease),
    box-shadow 0.25s var(--ease),
    padding 0.2s var(--ease);
}
.chat-input-bar-pro input:focus {
  border-color: var(--olive);
  box-shadow:
    inset 0 1px 2px rgba(74, 93, 35, 0.06),
    0 0 0 3px rgba(74, 93, 35, 0.1);
  padding: 13px 19px;
}

/* §7.3 — Send button paper-plane launch ────────────────────── */
.chat-send-btn-pro {
  background: linear-gradient(135deg, var(--olive), #5a7a2e);
  position: relative;
  overflow: hidden;
}
.chat-send-btn-pro .csb-plane {
  width: 18px;
  height: 18px;
  transition: transform 0.25s var(--ease-out-expo);
  display: block;
}
.chat-send-btn-pro:hover .csb-plane {
  transform: translate(2px, -2px);
}
.chat-send-btn-pro.is-launch .csb-plane {
  animation: chatPlaneLaunch 0.25s var(--ease-out-expo) forwards;
}
@keyframes chatPlaneLaunch {
  0% {
    transform: translate(0, 0);
    opacity: 1;
  }
  100% {
    transform: translate(30px, -30px);
    opacity: 0;
  }
}
.chat-send-btn-pro::after {
  content: "";
  position: absolute;
  inset: 0;
  display: block;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M3 11 21 3l-8 18-2-7-8-3z'/></svg>");
  background-position: center;
  background-repeat: no-repeat;
  background-size: 18px 18px;
  opacity: 0;
  pointer-events: none;
}
.chat-send-btn-pro.is-launch::after {
  animation: chatPlaneArrive 0.3s var(--ease-out-expo) 0.08s forwards;
}
@keyframes chatPlaneArrive {
  0% {
    opacity: 0;
    transform: scale(0.7);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* §7.3 — Floating "↓ New message" pill ─────────────────────── */
.chat-room {
  position: relative;
}
.chat-scroll-pill {
  position: absolute;
  left: 50%;
  bottom: 92px;
  transform: translate(-50%, 8px);
  opacity: 0;
  pointer-events: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--olive);
  color: #fff;
  border: none;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 12px;
  padding: 8px 14px;
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(74, 93, 35, 0.28);
  cursor: pointer;
  z-index: 4;
  transition:
    opacity 0.25s var(--ease-out-expo),
    transform 0.3s var(--ease-out-back);
}
.chat-scroll-pill.show {
  opacity: 1;
  transform: translate(-50%, 0);
  pointer-events: auto;
}
.chat-scroll-pill:hover {
  background: #43521f;
}

/* §7.3 — Empty state envelope ──────────────────────────────── */
.chat-empty-pro {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 40px 20px;
  color: var(--text-m);
  text-align: center;
}
.chat-empty-env {
  width: 88px;
  height: 64px;
  margin-bottom: 18px;
  color: var(--olive);
}
.chat-empty-env svg {
  width: 100%;
  height: 100%;
}
.chat-empty-env .env-flap {
  transform-origin: center;
  animation: chatEnvFlap 3s ease-in-out infinite;
}
@keyframes chatEnvFlap {
  0%,
  100% {
    transform: scaleY(1);
  }
  50% {
    transform: scaleY(0.55);
  }
}

/* §7.3 — Mute button morph (scale-bounce on toggle) ────────── */
.chat-mute-morph .cmm-glyph {
  display: inline-block;
  transition: transform 0.2s var(--ease-out-back);
}
.chat-mute-morph:hover .cmm-glyph {
  transform: scale(1.08);
}
.chat-mute-morph:active .cmm-glyph {
  transform: scale(0.92);
}

/* Pulse hint for the "Enable notifications" state — draws the eye
   to the bell when push permission hasn't been granted yet. */
.chat-notif-pulse {
  position: relative;
  animation: chatNotifPulse 2.2s ease-in-out infinite;
}
@keyframes chatNotifPulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(74, 93, 35, 0.35);
  }
  50% {
    box-shadow: 0 0 0 8px rgba(74, 93, 35, 0);
  }
}

/* ── Reduced-motion safety net for §7 ───────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .chat-sec-hd .chat-sec-pill {
    animation: none;
    height: 20px;
  }
  .chat-notif-icon .cn-bell {
    animation: none;
  }
  .chat-av-house .cn-house {
    animation: none;
    stroke-dashoffset: 0;
  }
  .chat-online-pulse .chat-online-ring {
    animation: none;
    opacity: 0;
  }
  .chat-unread-pill.is-bump {
    animation: none;
  }
  .chat-item.chat-item-slide {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .chat-item.unr::after {
    animation: none;
    opacity: 1;
  }
  .chat-msg-pro {
    animation: none;
  }
  .chat-notif-pulse {
    animation: none;
  }
  .typing-row-pro .typing-dot {
    animation: none;
    opacity: 0.8;
    transform: scale(1);
  }
  .typing-row-pro .typing-label {
    animation: none;
    opacity: 0.6;
  }
  .chat-empty-env .env-flap {
    animation: none;
  }
  .chat-send-btn-pro.is-launch .csb-plane {
    animation: none;
  }
  .chat-send-btn-pro.is-launch::after {
    animation: none;
    opacity: 1;
  }
  .msg-tick {
    animation: none;
    opacity: 1;
  }
  .chat-scroll-pill {
    transition: opacity 0.2s linear;
  }
}
/* === END §6 AUTH (Phase 5) === */

/* ===================================================================
   PROFILE (§8) — Phase 7
   Profile page polish: avatar conic ring, shimmer name, menu items
   with stagger + chevron + edge bar + sweep, edit-profile camera
   overlay, sub-page split-reveal titles + back arrow + empty-state
   breath, and per-route flourishes (manual rotate, guide pin draw,
   help warm gradient, payment shimmer, billing micro-interactions,
   bookings status, prefs ripple, docs perspective tilt, settings
   toast).
   Animates only transform / opacity / filter / clip-path /
   background-position. Reduced-motion overrides at end.
   =================================================================== */

/* — Property registration for animated conic ring (graceful fallback) — */
@property --kw-prof-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* — Profile header card — */
.ph {
  position: relative;
}

/* — Avatar (96px desktop / 72px mobile) w/ 2px gold ring at rest — */
.p-av {
  width: 96px;
  height: 96px;
  font-size: 38px;
  /* Ring is a layered pseudo so the avatar can still use background-image
     for an uploaded photo. We use box-shadow rings (composited cheaply). */
  box-shadow:
    0 0 0 2px var(--gold),
    0 0 0 4px rgba(255, 255, 255, 0.55),
    var(--sh-card);
  transition:
    box-shadow var(--t-med) var(--ease-out-expo),
    transform var(--t-med) var(--ease-out-expo);
}
.ph:hover .p-av,
.p-av:hover,
.p-av:focus-visible {
  will-change: transform, box-shadow;
}
.p-av::before {
  /* Rotating conic-gradient glow — visible only on hover.
     Uses @property when supported (smooth angle interpolation);
     falls back to plain transform: rotate via keyframes otherwise. */
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: inherit;
  background: conic-gradient(
    from var(--kw-prof-angle, 0deg),
    transparent 0deg,
    var(--gold) 45deg,
    transparent 110deg,
    var(--olive-60) 200deg,
    transparent 290deg,
    var(--gold) 340deg,
    transparent 360deg
  );
  opacity: 0;
  filter: blur(6px);
  pointer-events: none;
  transition: opacity var(--t-med) var(--ease-out-expo);
  z-index: -1;
  animation: kwProfRingSpin 3600ms linear infinite paused;
}
.ph:hover .p-av,
.p-av:focus-visible {
  box-shadow:
    0 0 0 3px var(--gold),
    0 0 0 5px rgba(255, 255, 255, 0.55),
    var(--sh-card);
}
.ph:hover .p-av::before,
.p-av:focus-visible::before {
  opacity: 0.85;
  animation-play-state: running;
}
@keyframes kwProfRingSpin {
  to {
    --kw-prof-angle: 360deg;
    transform: rotate(360deg);
  }
}

/* — Online/verified badge — */
.p-av .bd {
  transition: transform var(--t-med) var(--ease-out-back);
}
.ph:hover .p-av .bd {
  transform: scale(1.1);
}

/* — Name shimmer (one-shot 1400ms gold sweep on first paint) — */
.p-nm {
  font-size: 28px;
  position: relative;
  background: linear-gradient(
    90deg,
    var(--text-d) 0%,
    var(--text-d) 35%,
    var(--gold) 50%,
    var(--text-d) 65%,
    var(--text-d) 100%
  );
  background-size: 280% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: kwProfNameShimmer 1400ms var(--ease-out-expo) 200ms 1 both;
}
@keyframes kwProfNameShimmer {
  0% {
    background-position: 100% 0;
  }
  100% {
    background-position: 0% 0;
  }
}

/* — Email/phone fade in 120ms after name shimmer (shimmer ends at 1600ms = 200ms delay + 1400ms duration) — */
.p-em {
  opacity: 0;
  animation: kwProfFadeIn 320ms var(--ease-out-expo) 1720ms forwards;
}
.p-em + .p-em {
  animation-delay: 1840ms;
}
@keyframes kwProfFadeIn {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* — Edit Profile pill — */
.edit-prof-btn {
  background: var(--olive-3);
  border-color: var(--olive-10);
  color: var(--olive);
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition:
    background var(--t-med) var(--ease-out-expo),
    color var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo);
}
.edit-prof-btn .ep-pen {
  display: inline-block;
  transform-origin: 50% 80%;
  transition: transform var(--t-med) var(--ease-out-back);
}
.edit-prof-btn:hover,
.edit-prof-btn:active {
  background: var(--olive-10);
  color: var(--olive);
  border-color: var(--olive-20);
}
.edit-prof-btn:hover .ep-pen {
  animation: kwProfPenWiggle 300ms var(--ease-out-back) 1;
}
@keyframes kwProfPenWiggle {
  0% {
    transform: rotate(0deg);
  }
  30% {
    transform: rotate(-2deg);
  }
  60% {
    transform: rotate(2deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

/* — Section titles with gold accent bar — */
.pstit {
  position: relative;
  padding-left: 14px;
}
.pstit::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 8px;
  height: 2px;
  background: var(--gold);
  transform: translateY(-50%) scaleX(0);
  transform-origin: left center;
  transition: transform 420ms var(--ease-out-expo) 80ms;
}
.pstit.is-in::before,
.pstit.reveal.is-in::before,
.fu .pstit::before {
  transform: translateY(-50%) scaleX(1);
}

/* — Menu items: lift, sweep, edge-bar, icon scale, chevron — */
.pmi {
  position: relative;
  overflow: hidden;
  transition:
    transform var(--t-med) var(--ease-out-expo),
    box-shadow var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    background var(--t-med) var(--ease-out-expo);
}
/* Sweep overlay (left→right) */
.pmi::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--olive-3) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  opacity: 0;
  pointer-events: none;
  transition:
    transform 250ms var(--ease-out-expo),
    opacity 250ms var(--ease-out-expo);
}
/* Left-edge indicator bar (3px olive) */
.pmi::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--olive);
  transform: scaleY(0);
  transform-origin: top center;
  opacity: 0;
  transition:
    transform 240ms var(--ease-out-expo),
    opacity 200ms ease;
  pointer-events: none;
}
.pmi:hover {
  transform: translateY(-1px);
  box-shadow: var(--sh-card);
}
.pmi:hover::after {
  transform: translateX(100%);
  opacity: 1;
}
.pmi:hover::before {
  transform: scaleY(1);
  opacity: 1;
}
.pmi:active {
  transform: scale(0.99);
  transition-duration: 100ms;
}
.pmi-ic {
  position: relative;
  z-index: 1;
  transition:
    background var(--t-med) var(--ease-out-expo),
    transform 200ms var(--ease-out-back);
}
.pmi:hover .pmi-ic {
  background: var(--olive-10);
  transform: scale(1.06);
  will-change: transform;
}
.pmi:hover .pmi-ic > * {
  transform: scale(1.12);
  will-change: transform;
}
.pmi-ic > * {
  display: inline-block;
  transition: transform 200ms var(--ease-out-back);
}
.pmi-t,
.pmi-ar {
  position: relative;
  z-index: 1;
}
.pmi-ar {
  transition:
    transform var(--t-med) var(--ease-out-expo),
    color var(--t-med) var(--ease-out-expo);
}
.pmi:hover .pmi-ar {
  transform: translateX(4px);
  color: var(--olive);
}

/* — Menu stagger reveal (column-then-row 50ms) —
   nth-of-type counts every <div> inside the column, so .pmi #N
   is the (N+1)-th div (pstit is the first). Column 2 starts a
   little later so the row-then-column reveal feels woven. */
.pmi.reveal {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 380ms var(--ease-out-expo),
    transform 380ms var(--ease-out-expo);
}
.pmi.reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}
.pgrid > div:nth-of-type(1) .pmi:nth-of-type(2).reveal {
  transition-delay: 50ms;
}
.pgrid > div:nth-of-type(1) .pmi:nth-of-type(3).reveal {
  transition-delay: 100ms;
}
.pgrid > div:nth-of-type(1) .pmi:nth-of-type(4).reveal {
  transition-delay: 150ms;
}
.pgrid > div:nth-of-type(1) .pmi:nth-of-type(5).reveal {
  transition-delay: 200ms;
}
.pgrid > div:nth-of-type(1) .pmi:nth-of-type(6).reveal {
  transition-delay: 250ms;
}
.pgrid > div:nth-of-type(2) .pmi:nth-of-type(2).reveal {
  transition-delay: 100ms;
}
.pgrid > div:nth-of-type(2) .pmi:nth-of-type(3).reveal {
  transition-delay: 150ms;
}
.pgrid > div:nth-of-type(2) .pmi:nth-of-type(4).reveal {
  transition-delay: 200ms;
}
.pgrid > div:nth-of-type(2) .pmi:nth-of-type(5).reveal {
  transition-delay: 250ms;
}
.pgrid > div:nth-of-type(2) .pmi:nth-of-type(6).reveal {
  transition-delay: 300ms;
}

/* — Log Out — */
.lout {
  border-width: 1px;
  border-color: rgba(220, 38, 38, 0.35);
  transition:
    background var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    color var(--t-med) var(--ease-out-expo);
}
.lout:hover {
  background: #fef2f2;
  border-color: #dc2626;
  color: #b91c1c;
}

/* — Log Out confirm modal (§11 dialog language) — */
.kw-confirm[hidden] {
  display: none;
}
.kw-confirm {
  position: fixed;
  inset: 0;
  z-index: 12000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 25, 18, 0.45);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-med) var(--ease-out-expo);
  padding: 16px;
}
.kw-confirm.show {
  opacity: 1;
  pointer-events: auto;
}
.kw-confirm-card {
  background: #fff;
  border-radius: var(--rl);
  padding: 28px;
  max-width: 380px;
  width: 100%;
  box-shadow: var(--sh-modal);
  transform: translateY(14px) scale(0.97);
  opacity: 0;
  transition:
    transform var(--t-med) var(--ease-out-back),
    opacity var(--t-med) var(--ease-out-expo);
}
.kw-confirm.show .kw-confirm-card {
  transform: translateY(0) scale(1);
  opacity: 1;
}
.kw-confirm-card h3 {
  font-family: var(--serif);
  font-size: 22px;
  margin-bottom: 8px;
  color: var(--text-d);
}
.kw-confirm-card p {
  color: var(--text-m);
  font-size: 14px;
  line-height: 1.55;
  margin-bottom: 22px;
}
.kw-confirm-acts {
  display: flex;
  gap: 10px;
}
.kw-confirm-acts button {
  flex: 1;
  padding: 12px 16px;
  border-radius: var(--rs);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
  transition:
    background var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    color var(--t-med) var(--ease-out-expo),
    transform 120ms var(--ease-out-back);
}
.kw-confirm-cancel {
  background: var(--olive-3);
  border-color: var(--olive-10);
  color: var(--text-s);
}
.kw-confirm-cancel:hover {
  background: var(--olive-10);
  border-color: var(--olive-20);
}
.kw-confirm-go {
  background: #dc2626;
  color: #fff;
}
.kw-confirm-go:hover {
  background: #b91c1c;
}
.kw-confirm-acts button:active {
  transform: scale(0.97);
}

/* — Sub-page back button: arrow slide — */
.sb .sb-arrow {
  display: inline-block;
  transition: transform var(--t-med) var(--ease-out-back);
}
.sb:hover .sb-arrow {
  transform: translateX(-2px);
  will-change: transform;
}

/* — Sub-page title split-reveal (mask slides up) — */
.stl {
  position: relative;
  overflow: hidden;
  display: inline-block;
}
.stl .stl-inner {
  display: inline-block;
  transform: translateY(100%);
  opacity: 0;
  animation: kwSubTitleUp 500ms var(--ease-out-expo) 60ms forwards;
}
@keyframes kwSubTitleUp {
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* — Empty state breath — */
.empty-ic {
  display: inline-flex;
  animation: kwEmptyBreath 3000ms ease-in-out infinite;
  transform-origin: center;
  /* continuous breath animation — exception per §21 */
  will-change: transform, opacity;
}
@keyframes kwEmptyBreath {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.35;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.55;
  }
}
.empty-ic .ei-svg {
  width: 56px;
  height: 56px;
  stroke: var(--olive);
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* — House Manual: card icon rotate + line reveal — */
.ic .ic-hd .ici {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: var(--olive-3);
  border-radius: 10px;
  font-size: 22px;
  line-height: 1;
  transition:
    transform var(--t-med) var(--ease-out-back),
    background var(--t-med) var(--ease-out-expo);
}
.ic:hover .ic-hd .ici {
  transform: rotate(2deg);
  background: var(--olive-10);
}
.ic-bd .ic-line {
  display: block;
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 320ms var(--ease-out-expo),
    transform 320ms var(--ease-out-expo);
}
.ic.is-in .ic-bd .ic-line,
.ic.fu .ic-bd .ic-line {
  opacity: 1;
  transform: translateY(0);
}
.ic.fu .ic-bd .ic-line:nth-child(1) {
  transition-delay: 120ms;
}
.ic.fu .ic-bd .ic-line:nth-child(2) {
  transition-delay: 200ms;
}
.ic.fu .ic-bd .ic-line:nth-child(3) {
  transition-delay: 280ms;
}
.ic.fu .ic-bd .ic-line:nth-child(4) {
  transition-delay: 360ms;
}
.ic.fu .ic-bd .ic-line:nth-child(5) {
  transition-delay: 440ms;
}
.ic.fu .ic-bd .ic-line:nth-child(6) {
  transition-delay: 520ms;
}

/* — Siquijor Guide: map-pin stroke draw + distance slide — */
.attr-pin {
  width: 12px;
  height: 12px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
  vertical-align: -1px;
  margin-right: 4px;
}
.attr-pin path,
.attr-pin circle {
  stroke-dasharray: 70;
  stroke-dashoffset: 70;
  transition: stroke-dashoffset 700ms var(--ease-out-expo);
}
.attr-card.is-in .attr-pin path,
.attr-card.is-in .attr-pin circle,
.attr-card.fu .attr-pin path,
.attr-card.fu .attr-pin circle {
  stroke-dashoffset: 0;
}
.attr-dist {
  display: inline-flex;
  align-items: center;
  opacity: 0;
  transform: translateX(8px);
  transition:
    opacity 380ms var(--ease-out-expo) 200ms,
    transform 380ms var(--ease-out-expo) 200ms;
}
.attr-card.fu .attr-dist,
.attr-card.is-in .attr-dist {
  opacity: 1;
  transform: translateX(0);
}

/* — Help & Support: warm olive contact card + phone pulse — */
.help-contact {
  background: linear-gradient(
    135deg,
    var(--olive-5) 0%,
    var(--gold-light) 100%
  );
  border: 1px solid var(--olive-10);
  position: relative;
  overflow: hidden;
}
.help-contact::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    circle at 80% 0%,
    rgba(200, 169, 81, 0.18),
    transparent 60%
  );
  pointer-events: none;
}
/* Contact Support — warm welcome photo beside the contact details.
   Mobile-first: the photo banners across the TOP and the details stack below
   (≤599px); from 600px up the photo becomes a left column. The panel carries a
   golden-hour wash that ALSO acts as a graceful fallback, so the card looks
   intentional even before images/contact-support.webp exists — no broken-image
   icon. min-height reserves the space so there is no layout shift (CLS). */
.help-contact--media {
  padding: 0;
  display: grid;
  grid-template-columns: 1fr; /* mobile: single column, stacked */
  overflow: hidden; /* clip the photo to the card's rounded corners */
}
.help-contact-photo {
  background-color: var(--olive-5); /* shows if the photo is absent */
  background-image: linear-gradient(
      150deg,
      rgba(91, 107, 71, 0.32),
      rgba(200, 169, 81, 0.22)
    ),
    url("images/contact-support.webp?v=20260615c");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  min-height: 168px; /* mobile banner height; grid-stretch fills taller on desktop */
}
.help-contact-body {
  padding: 24px; /* matches the base .ic padding */
  position: relative;
  z-index: 1; /* keep text above the card's ::after gold wash */
}
@media (min-width: 600px) {
  .help-contact--media {
    grid-template-columns: 190px 1fr; /* tablet/desktop: photo left, details right */
  }
}
.help-phone {
  /* a11y: these tel: links sit on the Help/Contact critical path, so each must
     be a >=44x44px touch target (Mobile-First Mandate + WCAG 2.5.8). Was
     inline-flex at ~27px tall. display:flex makes each link a block-level tap
     ROW so vertical margins reliably separate adjacent rows; width:fit-content
     keeps the box content-width so the :hover translateX(3px) below can never
     push a full-width row past the viewport edge (zero h-overflow rule). */
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 8px 0;
  margin: 4px 0;
  color: var(--olive);
  font-weight: 600;
  text-decoration: none;
  font-size: 15px;
  transition: transform var(--t-med) var(--ease-out-back);
}
.help-phone .phone-icon {
  width: 16px;
  height: 16px;
  stroke: var(--olive);
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
  transition: transform var(--t-med) var(--ease-out-back);
}
.help-phone:hover {
  transform: translateX(3px);
}
.help-phone:hover .phone-icon {
  animation: kwPhonePulse 1.2s ease-in-out infinite;
}
@keyframes kwPhonePulse {
  0%,
  100% {
    transform: scale(1) rotate(0);
  }
  35% {
    transform: scale(1.08) rotate(-8deg);
  }
  70% {
    transform: scale(1.08) rotate(8deg);
  }
}

/* — Payment Methods: gold shimmer sweep on bank card — */
.pay-bank {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.pay-bank::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 40%;
  background: linear-gradient(
    105deg,
    transparent 0%,
    rgba(200, 169, 81, 0) 25%,
    rgba(200, 169, 81, 0.45) 50%,
    rgba(200, 169, 81, 0) 75%,
    transparent 100%
  );
  transform: translateX(0);
  animation: kwPayShimmer 6s var(--ease-in-out-quart) infinite;
  pointer-events: none;
}
@keyframes kwPayShimmer {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(350%);
  }
}

/* — Billing rows: download button micro-interaction — */
.rc-btn.bill-dl {
  transition: transform 120ms var(--ease-out-back);
}
.rc-btn.bill-dl:active {
  transform: scale(0.94);
}
.rc-btn.bill-dl.is-checked {
  background: var(--olive-10);
  color: var(--olive);
}
.rc-btn.bill-dl .bill-icon {
  display: inline-block;
  margin-right: 6px;
  transition:
    transform 220ms var(--ease-out-back),
    opacity 200ms ease;
}
.rc-btn.bill-dl.is-checked .bill-icon {
  transform: scale(1.15);
}

/* — My Bookings: status badge motion accents — */
.bk-status {
  display: inline-block;
  position: relative;
}
.bk-status.is-checked-in {
  animation: kwStatusBreath 2.6s ease-in-out infinite;
}
@keyframes kwStatusBreath {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.78;
    transform: scale(0.98);
  }
}
.bk-status.is-checked-out {
  opacity: 0.7;
}

/* ════════════════════════════════════════════════════════════════
   MY BOOKINGS — editorial card system (mobile-first, designed @360).
   Reuses the .bk-status motion accents above. Filter chips trigger an
   in-memory re-render (setBookingFilter → _renderMyBookings); whole
   cards are role=button → the existing ticket overlay (openBookingTicket).
   ════════════════════════════════════════════════════════════════ */
.bk-filter {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 2px 2px 16px;
  margin: 0 -2px;
}
.bk-filter::-webkit-scrollbar {
  display: none;
}
.bk-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 8px 15px;
  border: 1px solid var(--olive-20);
  border-radius: 999px;
  background: transparent;
  color: var(--olive);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    color var(--t-med) var(--ease-out-expo);
}
.bk-chip-n {
  font-size: 11px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--olive-10);
}
.bk-chip.is-active {
  background: var(--olive);
  border-color: var(--olive);
  color: #fff;
}
.bk-chip.is-active .bk-chip-n {
  background: rgba(255, 255, 255, 0.22);
}
@media (hover: hover) {
  .bk-chip:hover {
    border-color: var(--olive);
    background: var(--olive-5);
  }
  .bk-chip.is-active:hover {
    background: var(--olive);
  }
}
.bk-chip:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.bk-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.bk-card {
  display: flex;
  align-items: stretch;
  width: 100%;
  text-align: left;
  background: #fff;
  border: 1px solid var(--olive-10);
  border-radius: 18px;
  overflow: hidden;
  box-shadow:
    0 1px 2px rgba(31, 42, 26, 0.04),
    0 10px 24px -18px rgba(31, 42, 26, 0.5);
  cursor: pointer;
  transition:
    transform var(--t-med) var(--ease-out-expo),
    box-shadow var(--t-med) var(--ease-out-expo);
}
.bk-card-ph {
  position: relative;
  flex: 0 0 104px;
  align-self: stretch;
  background: var(--olive-3);
  overflow: hidden;
}
.bk-card-ph img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease-out-expo);
}
.bk-card-bd {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 14px 16px;
}
.bk-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.bk-card-nm {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bk-card .bk-status {
  flex: 0 0 auto;
  padding: 4px 11px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: capitalize;
  white-space: nowrap;
  /* currentColor = the inline status colour; color-mix tints a soft pill.
     Unsupported browsers simply omit the bg (colored text stays legible). */
  background: color-mix(in srgb, currentColor 13%, transparent);
}
.bk-card-meta {
  font-size: 13px;
  color: var(--text-m);
}
.bk-card-bot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 2px;
}
.bk-card-pr {
  font-size: 16px;
  font-weight: 700;
  color: var(--olive);
}
.bk-card-go {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-m);
  opacity: 0.85;
  transition: transform var(--t-med) var(--ease-out-expo);
}
.bk-empty {
  text-align: center;
  color: var(--text-m);
  font-size: 14px;
  padding: 44px 16px;
}

@media (hover: hover) {
  .bk-card:hover {
    transform: translateY(-2px);
    box-shadow:
      0 2px 4px rgba(31, 42, 26, 0.06),
      0 18px 32px -18px rgba(31, 42, 26, 0.55);
  }
  .bk-card:hover .bk-card-ph img {
    transform: scale(1.05);
  }
  .bk-card:hover .bk-card-go {
    transform: translateX(3px);
  }
}
.bk-card:active {
  transform: scale(0.992);
}
.bk-card:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
}

@media (min-width: 600px) {
  .bk-card-ph {
    flex-basis: 132px;
  }
  .bk-card-bd {
    padding: 16px 20px;
  }
  .bk-card-nm {
    font-size: 19px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .bk-card,
  .bk-card-ph img,
  .bk-card-go,
  .bk-chip {
    transition: none;
  }
  .bk-card:hover,
  .bk-card:active {
    transform: none;
  }
  .bk-card:hover .bk-card-ph img {
    transform: none;
  }
  .bk-card:hover .bk-card-go {
    transform: none;
  }
}

/* — Travel Preferences: olive ripple on toggle activate — */
.pref-toggle {
  transition: background var(--t-med) var(--ease-out-expo);
}
.pref-knob {
  /* Switch from animating `left` (layout) to `transform` (composite). */
  left: 3px !important;
  transition: transform var(--t-med) var(--ease-out-back);
}
.pref-toggle:hover .pref-knob,
.pref-toggle:active .pref-knob,
.pref-toggle.just-on .pref-knob {
  will-change: transform;
}
.pref-toggle.on .pref-knob {
  left: 3px !important;
  transform: translateX(20px);
}
.pref-toggle::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--olive);
  opacity: 0;
  transform: scale(0.6);
  pointer-events: none;
}
.pref-toggle.just-on::after {
  animation: kwPrefRipple 600ms var(--ease-out-expo) 1;
}
@keyframes kwPrefRipple {
  0% {
    opacity: 0.5;
    transform: scale(0.6);
  }
  100% {
    opacity: 0;
    transform: scale(1.4);
  }
}

/* — Saved Documents: 3° Y-axis perspective tilt — */
.doc-card {
  perspective: 800px;
  transform-style: preserve-3d;
  transition:
    transform 400ms var(--ease-out-expo),
    box-shadow 400ms var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo);
}
.doc-card:hover {
  transform: perspective(800px) rotateY(-3deg) translateY(-2px);
  box-shadow: var(--sh-card);
  will-change: transform;
}

/* — Edit Profile avatar overlay + photo pop / ring flash — */
.ep-avatar {
  width: 112px;
  height: 112px;
  font-size: 44px;
  position: relative;
  cursor: pointer;
  transition:
    transform 400ms var(--ease-out-back),
    box-shadow var(--t-med) var(--ease-out-expo);
  box-shadow: 0 0 0 0 var(--gold);
}
.ep-avatar:hover,
.ep-avatar:focus-within,
.ep-avatar.is-popped,
.ep-avatar.is-flashed {
  will-change: transform;
}
.ep-avatar::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: rgba(74, 93, 35, 0.85);
  opacity: 0;
  transition: opacity var(--t-med) var(--ease-out-expo);
  pointer-events: none;
  display: grid;
  place-items: center;
}
.ep-avatar .ep-cam-overlay {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
  gap: 4px;
  opacity: 0;
  transition: opacity var(--t-med) var(--ease-out-expo);
  pointer-events: none;
  z-index: 2;
}
.ep-avatar:hover,
.ep-avatar:focus-within {
  opacity: 1;
}
.ep-avatar:hover::after,
.ep-avatar:focus-within::after {
  opacity: 0.85;
}
.ep-avatar:hover .ep-cam-overlay,
.ep-avatar:focus-within .ep-cam-overlay {
  opacity: 1;
}
.ep-cam-overlay .ep-cam-icon {
  width: 26px;
  height: 26px;
  stroke: #fff;
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ep-avatar.is-popped {
  animation: kwEpPhotoPop 400ms var(--ease-out-back) 1;
}
.ep-avatar.is-flashed {
  animation:
    kwEpPhotoPop 400ms var(--ease-out-back) 1,
    kwEpRingFlash 600ms var(--ease-out-expo) 1;
}
@keyframes kwEpPhotoPop {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.04);
  }
  100% {
    transform: scale(1);
  }
}
@keyframes kwEpRingFlash {
  0% {
    box-shadow: 0 0 0 0 rgba(200, 169, 81, 0);
  }
  40% {
    box-shadow: 0 0 0 6px rgba(200, 169, 81, 0.55);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(200, 169, 81, 0);
  }
}

/* — Edit Profile field focus accent (scaleX from left) — */
.auth-field {
  position: relative;
}
.auth-field .field-accent {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--olive);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
  transition:
    transform 280ms var(--ease-out-expo),
    opacity 200ms ease;
  pointer-events: none;
  border-radius: 1px;
}
.auth-field.is-focus .field-accent {
  transform: scaleX(1);
  opacity: 1;
}
.auth-field[data-max] {
  margin-bottom: 22px;
}
.auth-field .field-counter {
  position: absolute;
  right: 12px;
  bottom: -16px;
  font-size: 11px;
  color: var(--text-m);
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
}
.auth-field.is-focus .field-counter {
  opacity: 1;
}

/* — Disabled email lock icon — */
.field-lock {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  stroke: var(--text-m);
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
  opacity: 0.7;
}
.field-lock-wrap {
  position: relative;
}
.field-lock-tip {
  position: absolute;
  right: 0;
  bottom: calc(100% + 6px);
  background: var(--text-d);
  color: #fff;
  padding: 6px 10px;
  border-radius: 8px;
  font-size: 11px;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition:
    opacity var(--t-med) var(--ease-out-expo),
    transform var(--t-med) var(--ease-out-expo);
  z-index: 5;
}
.field-lock-wrap:hover .field-lock-tip {
  opacity: 1;
  transform: translateY(0);
}

/* — Validation shake — */
.auth-field.is-error input {
  animation: kwFieldShake 320ms var(--ease-out-expo) 1;
  border-color: #dc2626;
}
@keyframes kwFieldShake {
  0%,
  100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-4px);
  }
  40% {
    transform: translateX(4px);
  }
  60% {
    transform: translateX(-3px);
  }
  80% {
    transform: translateX(2px);
  }
}

/* — Save button success state — */
.auth-submit.is-saving {
  opacity: 0.85;
  cursor: progress;
}
.auth-submit.is-saved {
  background: var(--olive) !important;
  animation: kwSaveGoldPulse 700ms var(--ease-out-expo) 1;
}
.auth-submit .save-check {
  display: inline-block;
  transform: scale(0);
  opacity: 0;
  transition:
    transform 220ms var(--ease-out-back),
    opacity 200ms ease;
}
.auth-submit.is-saved .save-check {
  transform: scale(1);
  opacity: 1;
}
@keyframes kwSaveGoldPulse {
  0% {
    box-shadow: 0 0 0 0 rgba(200, 169, 81, 0.6);
  }
  100% {
    box-shadow: 0 0 0 14px rgba(200, 169, 81, 0);
  }
}

/* — Change Password divider — */
.ep-pw-div {
  position: relative;
  height: 1px;
  margin: 28px 0 20px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--olive-20) 50%,
    transparent 100%
  );
}

/* — Mobile adjustments — */
@media (max-width: 640px) {
  .p-av {
    width: 72px;
    height: 72px;
    font-size: 28px;
  }
  .p-nm {
    font-size: 22px;
  }
  .pgrid {
    grid-template-columns: 1fr;
    gap: 16px;
  }
}

/* — Reduced-motion overrides for §8 — */
@media (prefers-reduced-motion: reduce) {
  .p-av::before {
    animation: none;
    opacity: 0;
  }
  .ph:hover .p-av::before {
    opacity: 0;
  }
  .p-nm {
    animation: none;
    background: var(--text-d);
    -webkit-text-fill-color: currentColor;
    color: var(--text-d);
  }
  .p-em {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .edit-prof-btn:hover .ep-pen {
    animation: none;
    transform: none;
  }
  .pstit::before {
    transition: none;
    transform: translateY(-50%) scaleX(1);
  }
  .pmi:hover {
    transform: none;
  }
  .pmi::after,
  .pmi::before {
    display: none;
  }
  .pmi:hover .pmi-ic,
  .pmi:hover .pmi-ic > * {
    transform: none;
  }
  .pmi:hover .pmi-ar {
    transform: none;
  }
  .pmi.reveal {
    opacity: 1;
    transform: none;
    transition: opacity 150ms ease;
  }
  .kw-confirm,
  .kw-confirm-card {
    transition: opacity 150ms ease;
  }
  .kw-confirm.show .kw-confirm-card {
    transform: none;
  }
  .sb:hover .sb-arrow {
    transform: none;
  }
  .stl .stl-inner {
    animation: none;
    transform: none;
    opacity: 1;
  }
  .empty-ic {
    animation: none;
    opacity: 0.35;
  }
  .ic:hover .ici {
    transform: none;
  }
  .ic-bd .ic-line {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .attr-pin path,
  .attr-pin circle {
    transition: none;
    stroke-dashoffset: 0;
  }
  .attr-dist {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .help-phone:hover {
    transform: none;
  }
  .help-phone:hover .phone-icon {
    animation: none;
  }
  .pay-bank::after {
    animation: none;
    opacity: 0;
  }
  .bk-status.is-checked-in {
    animation: none;
  }
  .pref-toggle.just-on::after {
    animation: none;
    opacity: 0;
  }
  .doc-card:hover {
    transform: none;
  }
  .ep-avatar.is-popped,
  .ep-avatar.is-flashed {
    animation: none;
  }
  .auth-submit.is-saved {
    animation: none;
  }
  .auth-field.is-error input {
    animation: none;
  }
}
/* === END PROFILE (§8) — Phase 7 === */

/* ═══════════════════════════════════════════════════════════════════
   ADMIN (§9) — Phase 8
   Calm, high-signal control panel. Restrained motion. Every animation
   conveys real info (status, change, arrival). No decorative twinkles
   in data tables. Animates ONLY transform/opacity/filter.
   ═══════════════════════════════════════════════════════════════════ */

/* ── 9.1 — Tab bar shell + FLIP indicator ───────────────────────── */
.adm-tab-bar {
  position: relative;
  padding: 6px;
  background: var(--olive-3);
  border-radius: 14px;
  width: fit-content;
  max-width: 100%;
  display: flex;
  gap: 2px;
  flex-wrap: wrap;
  isolation: isolate;
}
.adm-tab-bar button {
  position: relative;
  z-index: 2;
  padding: 9px 18px;
  border-radius: 10px;
  border: none;
  font-size: 13px;
  font-weight: 600;
  background: transparent;
  color: var(--olive);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition:
    color 220ms var(--ease-out-expo),
    background-color 220ms var(--ease-out-expo);
  cursor: pointer;
}
.adm-tab-bar button:hover:not(.active) {
  background: rgba(74, 93, 35, 0.06);
}
.adm-tab-bar button.active {
  color: #fff;
  background: transparent; /* indicator paints below */
}
.adm-tab-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 1;
  transition: transform 250ms var(--ease-out-back);
  will-change: auto;
}
.adm-tab-bar button.active .adm-tab-ic {
  animation: admTabIcPop 250ms var(--ease-out-back) both;
}
@keyframes admTabIcPop {
  0% {
    transform: scale(0.94);
  }
  100% {
    transform: scale(1);
  }
}
.adm-tab-indicator {
  /* Fixed-size base (100×100) — JS animates only transform: translate + scale,
     never width/height (composite-safe per §-1 rule 4). The 100×100 base makes
     scale factors simple (W/100, H/100). Border-radius scales with the box. */
  position: absolute;
  top: 0;
  left: 0;
  width: 100px;
  height: 100px;
  transform-origin: top left;
  background:
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.04) 0%,
      transparent 30%,
      rgba(0, 0, 0, 0.04) 100%
    ),
    var(--olive);
  /* Use 1000% radius so it remains a pill regardless of scale (CSS clamps to half min(w,h)). */
  border-radius: 10000px;
  z-index: 1;
  opacity: 0;
  box-shadow: 0 2px 8px rgba(74, 93, 35, 0.22);
  pointer-events: none;
}
@media (max-width: 720px) {
  .adm-tab-bar button {
    padding: 9px 12px;
    font-size: 12px;
  }
  .adm-tab-lbl {
    display: inline;
  }
}

/* ── 9.1 — Content area fade-up swap ───────────────────────────── */
.adm-content-anim {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 350ms var(--ease-out-expo),
    transform 350ms var(--ease-out-expo);
}
.adm-content-anim.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* ── 9.1 — Branded spinner: olive arc + 3 counter-rotating gold dots ── */
.adm-spinner {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 44px;
}
.adm-spinner-arc {
  width: 100%;
  height: 100%;
  animation: admSpinArc 1s linear infinite;
}
@keyframes admSpinArc {
  to {
    transform: rotate(360deg);
  }
}
.adm-spinner-orbit {
  position: absolute;
  inset: 0;
  animation: admSpinOrbit 2.4s linear infinite reverse;
}
@keyframes admSpinOrbit {
  to {
    transform: rotate(360deg);
  }
}
.adm-spinner-dot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--gold);
}
.adm-spinner-dot.d1 {
  transform: translate(-50%, -50%) rotate(0deg) translateX(20px);
}
.adm-spinner-dot.d2 {
  transform: translate(-50%, -50%) rotate(120deg) translateX(20px);
}
.adm-spinner-dot.d3 {
  transform: translate(-50%, -50%) rotate(240deg) translateX(20px);
}

/* ── 9.2 — Stat cards grid + count-up + status accent + ring ─────── */
.adm-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 36px;
}
.adm-stat {
  position: relative;
  background: var(--wh);
  padding: 28px 24px;
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  text-align: center;
  overflow: hidden;
  transition:
    transform 300ms var(--ease-out-expo),
    box-shadow 300ms var(--ease-out-expo),
    border-color 200ms var(--ease-out-expo);
}
.adm-stat:hover {
  transform: translateY(-4px);
  box-shadow: var(--sh-card);
  border-color: var(--olive-20);
}
.adm-stat-accent {
  position: absolute;
  top: 0;
  left: 0;
  height: 3px;
  width: 100%;
  background: var(--olive);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease-out-expo);
}
.adm-stat[data-accent="green"] .adm-stat-accent {
  background: #22c55e;
}
.adm-stat[data-accent="red"] .adm-stat-accent {
  background: #dc2626;
}
.adm-stat[data-accent="gold"] .adm-stat-accent {
  background: var(--gold);
}
.adm-stat:hover .adm-stat-accent {
  transform: scaleX(1);
}

.adm-stat-num {
  font-family: var(--serif);
  font-size: 36px;
  color: var(--olive);
  margin-bottom: 4px;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 2px;
}
.adm-stat-val {
  display: inline-block;
}
.adm-stat-suffix {
  color: var(--text-m);
  font-size: 22px;
  font-weight: 400;
  margin-left: 2px;
}
.adm-stat-label {
  font-size: 13px;
  color: var(--text-m);
  font-weight: 500;
  position: relative;
  z-index: 2;
}

/* Phase AC — Outstanding Balances stat card.
   Peso-prefixed value (no count-up animation — the source data is a
   centavo sum that's already display-ready), sub-line beneath the
   label showing the booking count, gold accent stripe when the
   total is > 0 to draw the admin's eye. */
.adm-stat-peso {
  /* Slightly tighter than the integer-only stat numbers so the
     full ₱X,XXX fits cleanly in the card width. */
  font-size: 28px;
  letter-spacing: -0.5px;
  line-height: 1.05;
}
.adm-stat-sub {
  font-size: 11.5px;
  color: var(--text-m);
  font-weight: 500;
  margin-top: 4px;
  letter-spacing: 0.2px;
  position: relative;
  z-index: 2;
}
.adm-stat-outstanding.has-balances {
  /* Subtle gold ring + tinted background so the card reads as
     actionable (money still owed). Identical visual weight to the
     existing is-unread/is-empty accent treatments. */
  border-left: 4px solid var(--gold, #c8a951);
  background: linear-gradient(180deg, rgba(200, 169, 81, 0.05), transparent);
}
.adm-stat-outstanding .adm-stat-peso {
  color: var(--olive);
}
.adm-stat-outstanding.has-balances .adm-stat-peso {
  color: #9a7d2e;
}
@media (max-width: 600px) {
  .adm-stat-peso {
    font-size: 24px;
  }
}

/* "Available Today" is 0 — left-border red strobe-pulse (opacity 0.7↔1) */
.adm-stat.is-empty {
  border-left: 4px solid #dc2626;
}
.adm-stat.is-empty::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 4px;
  background: #dc2626;
  animation: admEmptyBreath 2s ease-in-out infinite;
}
@keyframes admEmptyBreath {
  0%,
  100% {
    opacity: 0.7;
  }
  50% {
    opacity: 1;
  }
}

/* Conversations: unread dot pulses gently */
.adm-stat-dot {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 0 rgba(200, 169, 81, 0.5);
  animation: admDotPulse 2.2s ease-in-out infinite;
  z-index: 3;
}
@keyframes admDotPulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.18);
    opacity: 0.85;
  }
}

/* Occupancy Rate — circular SVG progress ring behind the number */
.adm-stat-ring-card {
  position: relative;
  padding-top: 36px;
}
.adm-stat-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 92px;
  height: 92px;
  transform: translate(-50%, -56%);
  z-index: 0;
  opacity: 0.85;
}
.adm-stat-ring-card .adm-stat-num,
.adm-stat-ring-card .adm-stat-label {
  position: relative;
  z-index: 2;
}

/* ── 9.2 — FULLY BOOKED alert ──────────────────────────────────── */
.adm-alert-booked {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 22px 18px 30px;
  background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
  border-radius: var(--r);
  border: 1px solid #fcd34d;
  margin-bottom: 24px;
  overflow: hidden;
}
.adm-alert-stripe {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 6px;
  background-image: repeating-linear-gradient(
    45deg,
    #b45309 0,
    #b45309 6px,
    #fde68a 6px,
    #fde68a 12px
  );
  background-size: 200% 200%;
  animation: admStripeShift 2s linear infinite;
}
@keyframes admStripeShift {
  from {
    background-position: 0% 0%;
  }
  to {
    background-position: 0% 100%;
  }
}
.adm-alert-title {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 700;
  color: #92400e;
  margin-bottom: 2px;
}
.adm-alert-text {
  font-size: 13px;
  color: #78350f;
}

/* ── 9.2 — Section titles + Quick Actions ──────────────────────── */
.adm-section-title {
  font-family: var(--serif);
  font-size: 20px;
  margin-bottom: 16px;
}
.adm-quick-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 36px;
}
.adm-qa-btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition:
    transform 220ms var(--ease-out-expo),
    box-shadow 220ms var(--ease-out-expo);
}
.adm-qa-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: -120%;
  width: 60%;
  height: 100%;
  background: linear-gradient(
    120deg,
    transparent,
    rgba(255, 255, 255, 0.35),
    transparent
  );
  transform: skewX(-20deg);
  transition: transform 600ms var(--ease-out-expo);
  pointer-events: none;
}
.adm-qa-gold::before {
  background: linear-gradient(
    120deg,
    transparent,
    rgba(255, 230, 150, 0.55),
    transparent
  );
}
.adm-qa-btn:hover::before {
  transform: translateX(360%) skewX(-20deg);
}
.adm-qa-btn:hover {
  transform: translateY(-2px);
}
.adm-qa-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  line-height: 1;
  transition: transform 280ms var(--ease-out-back);
}
.adm-qa-btn[data-qa="manage"]:hover .adm-qa-ic {
  transform: rotate(2deg);
}
.adm-qa-btn[data-qa="walkin"]:hover .adm-qa-ic {
  transform: scale(1.1);
}
.adm-qa-btn[data-qa="avail"]:hover .adm-qa-ic {
  transform: perspective(40px) rotateY(-12deg);
}
.adm-qa-btn[data-qa="chats"]:hover .adm-qa-ic {
  transform: translateY(-1px) rotate(-4deg);
}

/* Per-item 40ms stagger via --um-d for Recent Users (overrides data-stagger). */
.adm-user-mini.reveal {
  transition-delay: var(--um-d, 0ms);
}

/* ── 9.2 — Recent users mini list w/ hover sweep + chevron ─────── */
.adm-users-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.adm-user-mini {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--wh);
  padding: 14px 18px;
  border-radius: var(--r);
  border: 1px solid var(--brd-l);
  overflow: hidden;
  cursor: pointer;
  transition:
    border-color 220ms var(--ease-out-expo),
    transform 220ms var(--ease-out-expo),
    box-shadow 220ms var(--ease-out-expo);
}
.adm-user-mini::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--olive-3), transparent);
  opacity: 0;
  transform: translateX(-30%);
  transition:
    opacity 240ms var(--ease-out-expo),
    transform 320ms var(--ease-out-expo);
  pointer-events: none;
}
.adm-user-mini:hover {
  border-color: var(--olive-20);
  box-shadow: var(--sh-s);
  transform: translateY(-1px);
}
.adm-user-mini:hover::before {
  opacity: 1;
  transform: translateX(0);
}
.adm-user-mini > * {
  position: relative;
  z-index: 1;
}
.adm-user-mini-av {
  transition: transform 260ms var(--ease-out-back);
}
.adm-user-mini:hover .adm-user-mini-av {
  transform: scale(1.06);
}
.adm-um-joined {
  color: var(--text-m);
  transition:
    color 220ms var(--ease-out-expo),
    font-weight 220ms var(--ease-out-expo);
}
.adm-user-mini:hover .adm-um-joined {
  color: var(--olive);
  font-weight: 600;
}
.adm-um-chev {
  margin-left: auto;
  font-size: 22px;
  color: var(--olive-20);
  opacity: 0;
  transform: translateX(-6px);
  transition:
    opacity 220ms var(--ease-out-expo),
    transform 220ms var(--ease-out-expo);
}
.adm-user-mini:hover .adm-um-chev {
  opacity: 1;
  transform: translateX(0);
  color: var(--olive);
}

/* ── 9.3 — Manage Rooms: add button + card + Ken Burns ─────────── */
.adm-rm-add {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.adm-rm-plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  font-size: 20px;
  line-height: 1;
  font-weight: 300;
  transition: transform 320ms var(--ease-out-back);
}
.adm-rm-add:hover .adm-rm-plus {
  transform: rotate(90deg);
}

.adm-rm-card {
  transition:
    transform 320ms var(--ease-out-expo),
    box-shadow 320ms var(--ease-out-expo),
    border-color 220ms var(--ease-out-expo);
}
.adm-rm-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--sh-card);
}
.adm-rm-card .rm-card-img {
  overflow: hidden;
}
.adm-rm-card .rm-card-img-inner {
  width: 100%;
  height: 100%;
  transition: transform 600ms var(--ease-out-expo);
  transform-origin: center;
}
.adm-rm-card:hover .rm-card-img-inner {
  transform: scale(1.04) translate(2px, -2px);
}
.adm-rm-card .rm-card-price {
  transition: color 220ms var(--ease-out-expo);
}
.adm-rm-card:hover .rm-card-price {
  color: #a48637;
}
.adm-rm-amenity-more {
  cursor: help;
  border: 1px dashed var(--olive-20);
}
.adm-amenity-pop {
  position: absolute;
  z-index: 200;
  transform: translate(-50%, -100%);
  padding: 8px 12px;
  background: var(--text-d);
  color: var(--cream);
  border-radius: 8px;
  font-size: 12px;
  font-weight: 500;
  max-width: 240px;
  box-shadow: var(--sh-card);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 200ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo);
}
.adm-amenity-pop.show {
  opacity: 1;
  transform: translate(-50%, calc(-100% - 6px));
}
.adm-rm-edit,
.adm-rm-del {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--olive-10);
  background: var(--olive-3);
  color: var(--olive);
  transition:
    background-color 200ms var(--ease-out-expo),
    color 200ms var(--ease-out-expo),
    border-color 200ms var(--ease-out-expo);
}
.adm-rm-edit:hover {
  background: var(--olive);
  color: #fff;
  border-color: var(--olive);
}
.adm-rm-edit:hover .adm-ic-pencil {
  animation: admPencilWiggle 500ms var(--ease-out-back);
}
@keyframes admPencilWiggle {
  0%,
  100% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(-8deg);
  }
  50% {
    transform: rotate(6deg);
  }
  75% {
    transform: rotate(-4deg);
  }
}
.adm-rm-del {
  background: transparent;
  border-color: #fca5a5;
  color: #dc2626;
}
.adm-rm-del:hover {
  background: #fee2e2;
  border-color: #dc2626;
}
.adm-rm-del:hover .adm-ic-trash {
  animation: admTrashShake 380ms var(--ease-out-expo);
}
@keyframes admTrashShake {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-2px) rotate(-4deg);
  }
  50% {
    transform: translateX(2px) rotate(4deg);
  }
  75% {
    transform: translateX(-1px);
  }
}
.adm-ic {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* ── 9.4 — Room Editor: photo grid, marching-ants, drag-over ───── */
.adm-photos-grid .adm-rm-photo-add {
  position: relative;
  border-style: dashed;
  overflow: hidden;
  transition:
    border-color 220ms var(--ease-out-expo),
    background-color 220ms var(--ease-out-expo);
}
.adm-photos-grid .adm-rm-photo-add::before {
  /* Marching-ants animated stroke (rotates the dash offset).
     Uses background-image (gradient) + animate background-position. */
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    linear-gradient(90deg, var(--olive-20) 50%, transparent 50%) repeat-x top,
    linear-gradient(90deg, var(--olive-20) 50%, transparent 50%) repeat-x bottom,
    linear-gradient(0deg, var(--olive-20) 50%, transparent 50%) repeat-y left,
    linear-gradient(0deg, var(--olive-20) 50%, transparent 50%) repeat-y right;
  background-size:
    12px 1.5px,
    12px 1.5px,
    1.5px 12px,
    1.5px 12px;
  animation: admAnts 10s linear infinite;
  opacity: 0;
  transition: opacity 240ms var(--ease-out-expo);
}
.adm-photos-grid .adm-rm-photo-add:hover::before,
.adm-photos-grid .adm-rm-photo-add.is-drag::before {
  opacity: 1;
}
@keyframes admAnts {
  to {
    background-position:
      120px 0,
      -120px 100%,
      0 -120px,
      100% 120px;
  }
}
.adm-photos-grid .adm-rm-photo-add.is-drag {
  background: var(--olive-3);
  border-color: var(--olive);
}
.adm-photos-grid .adm-rm-photo-add.is-drag .adm-photo-add-ic {
  animation: admDropBounce 600ms var(--ease-out-back) infinite alternate;
}
@keyframes admDropBounce {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(-4px);
  }
}
.adm-photo-add-ic {
  width: 28px;
  height: 28px;
}
.adm-rm-photo-add .rm-photo-add-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.adm-rm-photo {
  transition:
    transform 240ms var(--ease-out-expo),
    box-shadow 240ms var(--ease-out-expo);
}
.adm-rm-photo-pop {
  animation: admPhotoPop 480ms var(--ease-out-back) both;
}
@keyframes admPhotoPop {
  0% {
    opacity: 0;
    transform: scale(0.92);
    filter: brightness(1);
  }
  40% {
    opacity: 1;
    filter: brightness(1.25);
  }
  100% {
    opacity: 1;
    transform: scale(1);
    filter: brightness(1);
  }
}
.adm-rm-photo .rm-photo-remove {
  transition:
    background-color 200ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo);
}
.adm-rm-photo .rm-photo-remove:hover {
  background: rgba(220, 38, 38, 0.92);
  transform: scale(1.08);
}
.adm-rm-cover {
  animation: admCoverPulse 2.4s ease-in-out infinite;
  transform-origin: center;
}
@keyframes admCoverPulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.85;
    transform: scale(1.04);
  }
}

/* ── 9.4 — Amenities ripple + custom-add scale-in ──────────────── */
.rm-amenity-btn {
  position: relative;
  overflow: hidden;
}
.adm-ripple {
  position: absolute;
  width: 12px;
  height: 12px;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.55) 0%,
    transparent 70%
  );
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0);
  animation: admRippleAnim 600ms var(--ease-out-expo) forwards;
}
@keyframes admRippleAnim {
  0% {
    transform: translate(-50%, -50%) scale(0);
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -50%) scale(14);
    opacity: 0;
  }
}
.adm-rm-amenity-pop {
  animation: admAmenityPopIn 320ms var(--ease-out-back) both;
}
@keyframes admAmenityPopIn {
  0% {
    opacity: 0;
    transform: scale(0);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* Save button: spinner → checkmark morph */
.adm-rm-save {
  position: relative;
  transition: background-color 200ms var(--ease-out-expo);
}
.adm-rm-save.is-saved {
  background: #22c55e !important;
}
.adm-rm-check {
  width: 22px;
  height: 22px;
  animation: admCheckDraw 200ms var(--ease-out-expo) both;
}
@keyframes admCheckDraw {
  0% {
    opacity: 0;
    transform: scale(0.6);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* ── 9.5 — Availability tab ─────────────────────────────────────── */
.adm-avail-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}
.adm-avail-prev .adm-arrow,
.adm-avail-next .adm-arrow {
  display: inline-block;
  transition: transform 220ms var(--ease-out-expo);
}
.adm-avail-prev:hover .adm-arrow-left {
  transform: translateX(-2px);
}
.adm-avail-next:hover .adm-arrow-right {
  transform: translateX(2px);
}
.adm-avail-legend {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 13px;
  color: var(--text-m);
  flex-wrap: wrap;
}
.adm-leg-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.adm-leg-dot {
  transition: transform 220ms var(--ease-out-expo);
}
.adm-leg-dot.leg-booked {
  animation: admLegBreath 2.6s ease-in-out infinite;
}
.adm-leg-dot.leg-in {
  animation: admLegPulse 1.8s ease-in-out infinite;
}
@keyframes admLegBreath {
  0%,
  100% {
    opacity: 0.85;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.12);
  }
}
@keyframes admLegPulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.7;
    transform: scale(0.92);
  }
}

.adm-avail-table th {
  position: relative;
}
.adm-today-bar {
  position: absolute;
  top: 0;
  left: 50%;
  width: 3px;
  height: 100%;
  background: var(--gold);
  transform: translateX(-50%) scaleY(0);
  transform-origin: top center;
  animation: admTodayBar 540ms var(--ease-out-expo) 120ms forwards;
  border-radius: 0 0 2px 2px;
}
@keyframes admTodayBar {
  from {
    transform: translateX(-50%) scaleY(0);
  }
  to {
    transform: translateX(-50%) scaleY(1);
  }
}

.adm-avail-cell {
  transition:
    background-color 180ms var(--ease-out-expo),
    border-color 180ms var(--ease-out-expo);
}
.adm-avail-cell .avail-tag {
  display: inline-block;
  transition:
    transform 180ms var(--ease-out-expo),
    filter 180ms var(--ease-out-expo);
}
.adm-avail-cell:hover .avail-tag {
  transform: scale(1.05);
  filter: brightness(1.06);
}
.adm-avail-cell.is-inhouse .avail-tag.gold {
  animation: admInHousePulse 2.4s ease-in-out infinite;
}
@keyframes admInHousePulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.78;
    transform: scale(0.96);
  }
}

.adm-avail-tip {
  position: absolute;
  z-index: 200;
  transform: translate(-50%, -100%);
  padding: 10px 14px;
  background: var(--text-d);
  color: var(--cream);
  border-radius: 10px;
  font-size: 12px;
  font-weight: 500;
  box-shadow: var(--sh-card);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 200ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo);
  min-width: 110px;
}
.adm-avail-tip.show {
  opacity: 1;
  transform: translate(-50%, calc(-100% - 10px));
}
.adm-avail-tip-name {
  font-weight: 700;
  font-size: 13px;
  color: #fff;
}
.adm-avail-tip-src {
  font-size: 11px;
  color: var(--olive-20);
  margin-top: 2px;
  text-transform: capitalize;
}
.adm-avail-tip-arrow {
  position: absolute;
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 10px;
  height: 10px;
  background: var(--text-d);
}

/* Tip box */
.adm-tip {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-top: 20px;
  padding: 16px 18px;
  background: var(--olive-3);
  border-radius: var(--rs);
  font-size: 13px;
  color: var(--text-s);
}
.adm-tip-bulb {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-top: 1px;
}
.adm-tip .adm-tip-bulb {
  animation: admBulbFlicker 200ms ease-out 200ms 1;
}
@keyframes admBulbFlicker {
  0%,
  100% {
    opacity: 1;
  }
  30% {
    opacity: 0.5;
  }
  60% {
    opacity: 1;
  }
  80% {
    opacity: 0.75;
  }
}

/* ── 9.6 — Add Booking ─────────────────────────────────────────── */
.adm-ab-info {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 24px;
  padding: 16px 18px;
  background: var(--olive-3);
  border-radius: var(--rs);
  border: 1px solid var(--olive-10);
}
.adm-ab-pencil {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  margin-top: 1px;
}
.adm-ab-pen-stroke {
  stroke-dasharray: 110;
  stroke-dashoffset: 110;
  animation: admPenWrite 800ms var(--ease-out-expo) 100ms forwards;
}
@keyframes admPenWrite {
  to {
    stroke-dashoffset: 0;
  }
}
.adm-ab-info-text {
  flex: 1;
}

.adm-ab-select {
  transition: border-color 220ms var(--ease-out-expo);
}
.adm-ab-select:focus {
  border-color: var(--olive);
  outline: none;
}
.adm-ab-select option {
  animation: admOptFade 260ms var(--ease-out-expo) both;
}
.adm-ab-select option:nth-child(1) {
  animation-delay: 0ms;
}
.adm-ab-select option:nth-child(2) {
  animation-delay: 20ms;
}
.adm-ab-select option:nth-child(3) {
  animation-delay: 40ms;
}
.adm-ab-select option:nth-child(4) {
  animation-delay: 60ms;
}
.adm-ab-select option:nth-child(5) {
  animation-delay: 80ms;
}
@keyframes admOptFade {
  from {
    opacity: 0;
    transform: translateY(-2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.adm-ab-dates {
  position: relative;
}
.adm-ab-nights {
  position: absolute;
  top: -22px;
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--olive);
  color: #fff;
  padding: 3px 12px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.4px;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 260ms var(--ease-out-expo),
    transform 260ms var(--ease-out-expo);
  white-space: nowrap;
}
.adm-ab-nights::before {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid var(--olive);
}
.adm-ab-nights.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.adm-ab-helper {
  font-size: 11px;
  color: var(--text-m);
  margin-top: 4px;
  transition: color 220ms var(--ease-out-expo);
}
.adm-ab-helper.is-warn {
  color: var(--olive);
  font-weight: 600;
}

.adm-ab-price-field {
  position: relative;
}
.adm-ab-auto {
  position: absolute;
  top: 0;
  right: 0;
  font-size: 9px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--gold);
  color: #463300;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.adm-ab-auto.is-pulse {
  animation: admAutoPulse 800ms var(--ease-out-expo);
}
@keyframes admAutoPulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.12);
  }
  100% {
    transform: scale(1);
  }
}
.adm-ab-price-wrap {
  position: relative;
}
.adm-ab-price-ghost {
  position: absolute;
  inset: 0;
  pointer-events: none;
  display: flex;
  align-items: center;
  padding-left: 16px;
  color: var(--olive);
  font-weight: 600;
  opacity: 0;
}
.adm-ab-price-ghost.is-out {
  animation: admPriceGhost 320ms var(--ease-out-expo);
}
@keyframes admPriceGhost {
  0% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  100% {
    opacity: 0;
    transform: translateY(-6px) scale(0.9);
  }
}

.adm-ab-result-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 18px;
  border-radius: var(--rs);
  font-size: 14px;
  opacity: 0;
  transform: translateY(-8px);
  transition:
    opacity 350ms var(--ease-out-expo),
    transform 350ms var(--ease-out-expo);
}
.adm-ab-result-card.is-in {
  opacity: 1;
  transform: translateY(0);
}
.adm-ab-result-ok {
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  color: #166534;
}
.adm-ab-result-bad {
  background: #fef2f2;
  border: 1px solid #fecaca;
  color: #b91c1c;
}
.adm-ab-result-ic {
  display: inline-flex;
  flex-shrink: 0;
}
.adm-ab-result-ic svg {
  width: 22px;
  height: 22px;
}

.adm-ab-check.is-loading,
.adm-ab-confirm.is-loading {
  pointer-events: none;
}
.adm-ab-confirm.is-success {
  background: #22c55e !important;
}

/* Confetti canvas */
.adm-confetti {
  position: absolute;
  z-index: 240;
  pointer-events: none;
}

/* ── 9.7 — All Bookings ─────────────────────────────────────────── */
.adm-bookings-table .adm-bk-row {
  transition:
    background-color 200ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo);
}
.adm-bookings-table .adm-bk-row:hover:not(.adm-header) {
  transform: translateX(2px);
  background: var(--olive-3);
}
.adm-bk-status {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  text-transform: capitalize;
  position: relative;
}
.adm-bk-status::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
}
.adm-bk-status-checked_in {
  padding-left: 18px;
}
.adm-bk-status-checked_in::before {
  animation: admStatusPulse 2s ease-in-out infinite;
}
@keyframes admStatusPulse {
  0%,
  100% {
    opacity: 0.45;
    transform: translateY(-50%) scale(1);
  }
  50% {
    opacity: 1;
    transform: translateY(-50%) scale(1.3);
  }
}
.adm-bk-status-confirmed::before {
  background: var(--olive);
}
.adm-bk-status-checked_out::before {
  background: var(--text-m);
  opacity: 0.6;
}

/* ── 9.8 — Users tab ─────────────────────────────────────────── */
.adm-uc {
  transition:
    transform 280ms var(--ease-out-expo),
    box-shadow 280ms var(--ease-out-expo),
    border-color 220ms var(--ease-out-expo);
}
.adm-uc:hover {
  transform: translateY(-3px);
  box-shadow: var(--sh-card);
  border-color: var(--olive-20);
}
.adm-uc-av {
  transition: transform 260ms var(--ease-out-back);
}
.adm-uc:hover .adm-uc-av {
  transform: scale(1.06);
}
.adm-uc-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--gold-light);
  color: #92710a;
  font-size: 10px;
  font-weight: 700;
}

/* ── 9.9 — Admin reveals (data-stagger) wired to .vis OR .is-in ── */
.adm-stat.reveal,
.adm-rm-card.reveal,
.adm-user-mini.reveal,
.adm-uc.reveal,
.adm-bk-row.reveal,
.adm-alert-booked.reveal,
.adm-section-title.reveal,
.adm-quick-actions.reveal,
.adm-tip.reveal,
.rm-manage-header.reveal,
.adm-avail-head.reveal,
.adm-ab-info.reveal,
.adm-addbooking .auth-field.reveal,
.adm-addbooking .form-grid-2.reveal,
.adm-addbooking .form-row-flex.reveal,
.adm-room-editor .reveal,
.adm-room-editor .rm-editor-section.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 460ms var(--ease-out-expo),
    transform 460ms var(--ease-out-expo);
}
/* Availability rows: <tr> — opacity-only stagger (transform on <tr> is quirky). */
.adm-avail-row.reveal {
  opacity: 0;
  transition: opacity 360ms var(--ease-out-expo);
}
.adm-avail-row.reveal.vis,
.adm-avail-row.reveal.is-in {
  opacity: 1;
}
.adm-stat.reveal.vis,
.adm-stat.reveal.is-in,
.adm-rm-card.reveal.vis,
.adm-rm-card.reveal.is-in,
.adm-user-mini.reveal.vis,
.adm-user-mini.reveal.is-in,
.adm-uc.reveal.vis,
.adm-uc.reveal.is-in,
.adm-bk-row.reveal.vis,
.adm-bk-row.reveal.is-in,
.adm-alert-booked.reveal.vis,
.adm-alert-booked.reveal.is-in,
.adm-section-title.reveal.vis,
.adm-section-title.reveal.is-in,
.adm-quick-actions.reveal.vis,
.adm-quick-actions.reveal.is-in,
.adm-tip.reveal.vis,
.adm-tip.reveal.is-in,
.rm-manage-header.reveal.vis,
.rm-manage-header.reveal.is-in,
.adm-avail-head.reveal.vis,
.adm-avail-head.reveal.is-in,
.adm-ab-info.reveal.vis,
.adm-ab-info.reveal.is-in,
.adm-addbooking .auth-field.reveal.vis,
.adm-addbooking .auth-field.reveal.is-in,
.adm-addbooking .form-grid-2.reveal.vis,
.adm-addbooking .form-grid-2.reveal.is-in,
.adm-addbooking .form-row-flex.reveal.vis,
.adm-addbooking .form-row-flex.reveal.is-in,
.adm-room-editor .reveal.vis,
.adm-room-editor .reveal.is-in,
.adm-room-editor .rm-editor-section.reveal.vis,
.adm-room-editor .rm-editor-section.reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* Reduced-motion overrides for §9 */
@media (prefers-reduced-motion: reduce) {
  .adm-spinner-arc,
  .adm-spinner-orbit {
    animation: none;
  }
  .adm-stat-accent {
    transform: scaleX(1);
    transition: none;
  }
  .adm-stat.is-empty::before,
  .adm-stat-dot,
  .adm-alert-stripe,
  .adm-cover-pulse,
  .adm-rm-cover,
  .adm-leg-dot.leg-booked,
  .adm-leg-dot.leg-in,
  .adm-avail-cell.is-inhouse .avail-tag.gold,
  .adm-bk-status-checked_in::before {
    animation: none;
  }
  .adm-stat:hover,
  .adm-rm-card:hover,
  .adm-user-mini:hover,
  .adm-uc:hover,
  .adm-bookings-table .adm-bk-row:hover,
  .adm-qa-btn:hover {
    transform: none;
  }
  .adm-rm-card:hover .rm-card-img-inner {
    transform: none;
  }
  .adm-user-mini:hover .adm-user-mini-av {
    transform: none;
  }
  .adm-uc:hover .adm-uc-av {
    transform: none;
  }
  .adm-rm-add:hover .adm-rm-plus {
    transform: none;
  }
  .adm-rm-edit:hover .adm-ic-pencil,
  .adm-rm-del:hover .adm-ic-trash {
    animation: none;
  }
  .adm-qa-btn::before {
    display: none;
  }
  .adm-user-mini::before {
    display: none;
  }
  .adm-um-chev {
    opacity: 1;
    transform: none;
  }
  .adm-tab-bar button.active .adm-tab-ic {
    animation: none;
  }
  .adm-tab-indicator {
    transition: none !important;
  }
  .adm-photos-grid .adm-rm-photo-add::before {
    animation: none;
  }
  .adm-today-bar {
    animation: none;
    transform: translateX(-50%) scaleY(1);
  }
  .adm-ab-pen-stroke {
    animation: none;
    stroke-dashoffset: 0;
  }
  .adm-ab-nights.show {
    transform: translateX(-50%);
  }
  .adm-tip .adm-tip-bulb {
    animation: none;
  }
  .adm-confetti {
    display: none !important;
  }
  .adm-content-anim,
  .adm-content-anim.is-in {
    transform: none;
    transition: opacity 200ms ease;
  }
  .adm-stat.reveal,
  .adm-rm-card.reveal,
  .adm-user-mini.reveal,
  .adm-uc.reveal,
  .adm-bk-row.reveal,
  .adm-alert-booked.reveal,
  .adm-section-title.reveal,
  .adm-quick-actions.reveal,
  .adm-tip.reveal,
  .rm-manage-header.reveal,
  .adm-avail-head.reveal,
  .adm-ab-info.reveal,
  .adm-addbooking .auth-field.reveal,
  .adm-addbooking .form-grid-2.reveal,
  .adm-addbooking .form-row-flex.reveal,
  .adm-room-editor .reveal,
  .adm-room-editor .rm-editor-section.reveal {
    transform: none;
    transition: opacity 180ms ease;
  }
}
/* === END ADMIN (§9) — Phase 8 === */

/* ════════════════════════════════════════════════════════════════════
   CHECKOUT (§10) — Phase 9
   Cinematic polish on top of the existing 4-step modal. Only animates
   transform / opacity / filter (§-1 rule 4). All motion respects
   prefers-reduced-motion via the global safety net + per-rule overrides.
   ════════════════════════════════════════════════════════════════════ */

/* --- Backdrop: deep blurred olive overlay (§10) --- */
.co-modal {
  background: rgba(31, 42, 26, 0.55);
  backdrop-filter: blur(16px) saturate(0.9);
  -webkit-backdrop-filter: blur(16px) saturate(0.9);
  transition: opacity 200ms var(--ease-out-expo);
}

/* --- Modal entrance: backdrop fade 200ms, sheet slide+scale 400ms --- */
.co-modal .co-sheet {
  transform: translateY(40px) scale(0.98);
  opacity: 0;
  transition:
    transform 400ms var(--ease-out-expo),
    opacity 280ms var(--ease-out-expo);
}
.co-modal.show .co-sheet {
  transform: translateY(0) scale(1);
  opacity: 1;
}

/* --- Step transitions: content slides left out / in from right --- */
.co-sheet-body {
  position: relative;
}
.co-step-anim {
  opacity: 0;
  transform: translateX(24px);
  animation: coStepEnter 320ms var(--ease-out-expo) forwards;
}
.co-step-anim.co-step-back {
  transform: translateX(-24px);
  animation-name: coStepEnterBack;
}
@keyframes coStepEnter {
  0% {
    opacity: 0;
    transform: translateX(24px);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}
@keyframes coStepEnterBack {
  0% {
    opacity: 0;
    transform: translateX(-24px);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

/* --- Step indicator polish: olive-fill bar between dots (§10) --- */
.co-progress {
  gap: 0;
  position: relative;
}
.co-prog-step {
  transition: opacity 320ms var(--ease-out-expo);
}
.co-prog-step.active .co-prog-dot,
.co-prog-step.done .co-prog-dot {
  transform: scale(1);
  transition:
    transform 280ms var(--ease-out-back),
    background-color 280ms var(--ease-out-expo);
}
.co-prog-step .co-prog-dot {
  transform: scale(0.94);
}
.co-prog-line {
  position: relative;
  overflow: hidden;
  margin: 0 8px;
  background: var(--brd);
}
.co-prog-line::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--olive), #6b8a3e);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 400ms var(--ease-out-expo);
}
.co-prog-line.co-prog-line-fill::after {
  transform: scaleX(1);
}

/* --- Hold timer ring (§10) --- */
.co-hold {
  position: relative;
  gap: 10px;
}
.co-hold-ring-wrap {
  position: relative;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  display: inline-grid;
  place-items: center;
}
.co-hold-ring {
  position: absolute;
  inset: 0;
  width: 22px;
  height: 22px;
  transform: rotate(-90deg);
  pointer-events: none;
}
.co-hold-ring-bg {
  fill: none;
  stroke: rgba(146, 64, 14, 0.18);
  stroke-width: 2.5;
}
.co-hold-ring-fill {
  fill: none;
  stroke: #92400e;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 56.5;
  stroke-dashoffset: 0;
  transition: stroke 200ms ease;
}
.co-hold.co-hold-expired .co-hold-ring-fill {
  stroke: #991b1b;
}
.co-hold.co-hold-expired .co-hold-ring-bg {
  stroke: rgba(153, 27, 27, 0.18);
}
.co-hold-ic-svg {
  width: 12px;
  height: 12px;
  color: #92400e;
  position: relative;
  z-index: 1;
}
.co-hold.co-hold-expired .co-hold-ic-svg {
  color: #991b1b;
}

/* --- Price breakdown rows (Step 1) reveal stagger --- */
.co-price-row.reveal {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 320ms var(--ease-out-expo),
    transform 320ms var(--ease-out-expo);
}
.co-price-row.reveal.is-in {
  opacity: 1;
  transform: none;
}

/* --- Payment method card (Step 2) selected state polish (§10) --- */
.co-method {
  transition:
    transform 220ms var(--ease-out-expo),
    border-color 220ms ease,
    background-color 220ms ease,
    opacity 220ms ease,
    box-shadow 280ms var(--ease-out-expo);
}
.co-methods.has-selected .co-method:not(.selected) {
  opacity: 0.7;
}
.co-method.selected {
  transform: translateY(-2px);
}
.co-method-check {
  position: absolute;
  top: 10px;
  right: 12px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--olive);
  color: #fff;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: scale(0.6);
  transition:
    opacity 220ms var(--ease-out-expo),
    transform 280ms var(--ease-out-back);
  pointer-events: none;
}
.co-method {
  position: relative;
}
.co-method.selected .co-method-check {
  opacity: 1;
  transform: scale(1);
}
.co-method-check svg {
  width: 12px;
  height: 12px;
}

/* --- Trust strip icons swap from emoji to line-art SVG --- */
.co-trust-item .co-trust-ic {
  width: 14px;
  height: 14px;
  color: var(--olive);
  flex-shrink: 0;
}

/* --- Step 4 SUCCESS — animated checkmark + radial burst + typewriter --- */
.co-success {
  position: relative;
  overflow: hidden;
}
.co-success-burst {
  position: absolute;
  top: 40px;
  left: 50%;
  width: 320px;
  height: 320px;
  transform: translate(-50%, -50%) scale(0.6);
  pointer-events: none;
  background: radial-gradient(
    circle,
    rgba(200, 169, 81, 0.32) 0%,
    rgba(200, 169, 81, 0) 60%
  );
  opacity: 0;
  z-index: 0;
  animation: coBurstIn 600ms var(--ease-out-expo) forwards;
}
@keyframes coBurstIn {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.6);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 0.65;
    transform: translate(-50%, -50%) scale(1);
  }
}
.co-success-ic {
  position: relative;
  z-index: 1;
  background: linear-gradient(135deg, var(--olive), #6b8a3e);
  font-size: 0;
  /* override the old emoji animation */
  animation: coSuccessScale 540ms var(--ease-out-back) both;
  box-shadow:
    0 12px 32px rgba(74, 93, 35, 0.32),
    0 0 0 8px rgba(200, 169, 81, 0.16);
}
@keyframes coSuccessScale {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}
.co-success-ic svg {
  width: 38px;
  height: 38px;
  color: #fff;
}
.co-success-ic-path {
  stroke: currentColor;
  stroke-width: 3.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
  stroke-dasharray: 32;
  stroke-dashoffset: 32;
  animation: coSuccessDraw 420ms var(--ease-out-expo) 320ms forwards;
}
@keyframes coSuccessDraw {
  to {
    stroke-dashoffset: 0;
  }
}

/* Booking reference typewriter (character-by-character, 60ms / char).
   The JS injects spans with .co-ref-char; CSS handles fade-in. */
.co-success-ref {
  position: relative;
  z-index: 1;
}
.co-ref-char {
  display: inline-block;
  opacity: 0;
  transform: translateY(2px);
  transition:
    opacity 180ms var(--ease-out-expo),
    transform 180ms var(--ease-out-expo);
}
.co-ref-char.is-in {
  opacity: 1;
  transform: none;
}

/* Keep the rest of success layers above the burst */
.co-success-title,
.co-success-sub,
.co-success-card,
.co-success-next,
.co-success > .co-next {
  position: relative;
  z-index: 1;
}

/* --- Method icon polish: subtle scale on selection --- */
.co-method-icon {
  transition: transform 280ms var(--ease-out-back);
}
.co-method.selected .co-method-icon {
  transform: scale(1.04);
}

/* --- Reduced-motion overrides for checkout (§10) --- */
@media (prefers-reduced-motion: reduce) {
  .co-modal,
  .co-modal .co-sheet,
  .co-modal.show .co-sheet {
    transition: opacity 150ms ease !important;
  }
  .co-modal .co-sheet {
    transform: none !important;
  }
  .co-step-anim {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .co-prog-line::after {
    transition: none !important;
  }
  .co-success-burst {
    animation: none !important;
    opacity: 0 !important;
  }
  .co-success-ic {
    animation: none !important;
    transform: none !important;
  }
  .co-success-ic-path {
    animation: none !important;
    stroke-dashoffset: 0 !important;
  }
  .co-ref-char {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .co-price-row.reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .co-method,
  .co-method.selected,
  .co-method-icon,
  .co-method.selected .co-method-icon {
    transform: none !important;
    transition: opacity 150ms ease !important;
  }
  .co-method-check {
    transition: opacity 150ms ease !important;
    transform: none !important;
  }
  .co-hold-ring-fill {
    transition: none !important;
  }
}
/* === END CHECKOUT (§10) — Phase 9 === */

/* ═══════════════════════════════════════════════════════════════════
   §11 — MICRO-INTERACTIONS SWEEP (Phase 10)
   ───────────────────────────────────────────────────────────────────
   Site-wide sweep filling gaps in interactive state coverage. Earlier
   phases (4-9) polished specific pages; Phase 10 ensures every button,
   input, toggle, toast, tooltip and modal close has its complete
   base micro-interaction per Brief §11.

   §-1 rules: animate only transform/opacity/filter, palette sacred,
   no setInterval, no permanent will-change, no innerHTML += loops.

   Sections:
     §11.1  Buttons (default / primary / secondary / danger / loading)
     §11.2  Inputs (focus / .is-invalid / .is-valid)
     §11.3  Toggles (.toggle.on + ripple)
     §11.4  Toasts (.toast.is-success/warn/error, dismissible)
     §11.5  Tooltips (.kw-tooltip)
     §11.6  Modals (.kw-modal-close × rotates 90° on hover)
     Reduced-motion overrides
   ═══════════════════════════════════════════════════════════════════ */

/* ─── §11.1 BUTTONS — default press feedback ─────────────────────────
   Common interactive button families get a subtle scale + translateY
   on :active, with a 200ms spring release. Applied via :active so the
   release is automatic — only the press costs a transition. We keep
   each button's existing hover behaviour untouched and merely add
   the press state — no specificity wars. */
.ncta:active:not(:disabled),
.cta-btn:active:not(:disabled),
.bk-go:active:not(:disabled),
.island-cta-btn:active:not(:disabled),
.auth-submit:active:not(:disabled),
.lout:active:not(:disabled),
.rc-btn:active:not(:disabled),
.chat-send-btn:active:not(:disabled),
.btn-primary:active:not(:disabled),
.btn-secondary:active:not(:disabled),
.btn-danger:active:not(:disabled) {
  transform: translateY(1px) scale(0.98);
  transition: transform 80ms var(--ease-out-expo);
}
.ncta,
.cta-btn,
.bk-go,
.island-cta-btn,
.auth-submit,
.lout,
.rc-btn,
.chat-send-btn,
.btn-primary,
.btn-secondary,
.btn-danger {
  /* Spring release after :active is released. Existing per-button
     transitions remain authoritative for background/color; this only
     governs the transform release. */
  transition:
    transform 200ms var(--spring),
    background-color var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    box-shadow var(--t-med) var(--ease-out-expo);
}

/* ─── §11.1 PRIMARY (olive) — gold edge-glow on hover ────────────────
   A pseudo-element draws a soft gold ring just outside the button.
   We only fade its opacity — composite-cheap. Phase 4 already set
   .hero-acts .ncta::after; this generalizes to all primary CTAs that
   don't already define ::after. The :not() selectors keep us from
   clobbering existing ::after usage. */
.ncta:not(.hero-acts .ncta):not(.is-loading),
.cta-btn:not(.is-loading),
.bk-go:not(.is-loading):not(:disabled),
.island-cta-btn:not(.is-loading),
.auth-submit:not(.is-loading):not(:disabled) {
  position: relative;
}
.ncta:not(.hero-acts .ncta):not(.is-loading)::before,
.cta-btn:not(.is-loading)::before,
.bk-go:not(.is-loading):not(:disabled)::before,
.island-cta-btn:not(.is-loading)::before {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: inherit;
  background: transparent;
  box-shadow:
    0 0 0 2px rgba(200, 169, 81, 0.45),
    0 0 18px 2px rgba(200, 169, 81, 0.28);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-med) var(--ease-out-expo);
}
.ncta:not(.hero-acts .ncta):not(.is-loading):hover::before,
.cta-btn:not(.is-loading):hover::before,
.bk-go:not(.is-loading):not(:disabled):hover::before,
.island-cta-btn:not(.is-loading):hover::before {
  opacity: 1;
}
.ncta:not(.hero-acts .ncta):not(.is-loading):active::before,
.cta-btn:not(.is-loading):active::before,
.bk-go:not(.is-loading):not(:disabled):active::before,
.island-cta-btn:not(.is-loading):active::before {
  opacity: 1;
  box-shadow:
    0 0 0 3px rgba(200, 169, 81, 0.6),
    0 0 24px 4px rgba(200, 169, 81, 0.4);
}

/* ─── §11.1 SECONDARY (outlined) — olive-3 hover fill ────────────────
   For outlined buttons. The fade is into the brand pale-olive token
   per §1. Border-color deepens to olive-20 for definition. */
.btn-secondary,
.bk-cancel,
.sb-outline,
button.outline-olive {
  background: transparent;
  border: 1.5px solid var(--olive-20);
  color: var(--olive);
  transition:
    background-color var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    transform 200ms var(--spring);
}
.btn-secondary:hover:not(:disabled),
.bk-cancel:hover:not(:disabled),
.sb-outline:hover:not(:disabled),
button.outline-olive:hover:not(:disabled) {
  background: var(--olive-3);
  border-color: var(--olive);
}

/* ─── §11.1 DANGER (red) — soft red tint + icon shake ────────────────
   .lout already exists. Generalizes to .btn-danger / .danger-btn.
   On hover, the icon (if present via .danger-icon) trembles briefly. */
.btn-danger,
.danger-btn {
  background: transparent;
  border: 1.5px solid #fca5a5;
  color: #dc2626;
  transition:
    background-color var(--t-med) var(--ease-out-expo),
    border-color var(--t-med) var(--ease-out-expo),
    transform 200ms var(--spring);
}
.btn-danger:hover:not(:disabled),
.danger-btn:hover:not(:disabled),
.lout:hover:not(:disabled) {
  background: #fef2f2;
  border-color: #f87171;
}
.lout .danger-icon,
.btn-danger .danger-icon,
.danger-btn .danger-icon {
  display: inline-block;
  transition: transform 200ms var(--ease-out-back);
}
.lout:hover .danger-icon,
.btn-danger:hover .danger-icon,
.danger-btn:hover .danger-icon {
  animation: kwDangerShake 360ms var(--ease-out-expo) 1;
}
@keyframes kwDangerShake {
  0%,
  100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-2px) rotate(-3deg);
  }
  40% {
    transform: translateX(2px) rotate(3deg);
  }
  60% {
    transform: translateX(-2px) rotate(-2deg);
  }
  80% {
    transform: translateX(2px) rotate(2deg);
  }
}

/* ─── §11.1 SHARED LOADING / SUCCESS UTILITY ─────────────────────────
   Reusable .is-loading and .is-success states for any olive CTA.
   .auth-submit (Phase 5) and .bk-go/.ncta (Phase 6) already implement
   their own loaders; this provides a fallback for ALL other buttons
   so callers can simply add `.is-loading` for instant 3-dot pulse,
   then swap to `.is-success` for the check flash. */
button.is-loading.kw-loadable,
.cta-btn.is-loading,
.island-cta-btn.is-loading,
.btn-primary.is-loading,
.btn-secondary.is-loading,
.btn-danger.is-loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}
button.is-loading.kw-loadable::after,
.cta-btn.is-loading::after,
.island-cta-btn.is-loading::after,
.btn-primary.is-loading::after,
.btn-secondary.is-loading::after,
.btn-danger.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56px;
  height: 12px;
  transform: translate(-50%, -50%);
  background-image:
    radial-gradient(circle 4px at center, currentColor 60%, transparent 65%),
    radial-gradient(circle 4px at center, currentColor 60%, transparent 65%),
    radial-gradient(circle 4px at center, currentColor 60%, transparent 65%);
  background-repeat: no-repeat, no-repeat, no-repeat;
  background-size:
    12px 12px,
    12px 12px,
    12px 12px;
  background-position:
    0 0,
    22px 0,
    44px 0;
  color: #fff;
  animation: bkDotsWave 1.2s var(--ease-in-out-quart) infinite;
}
button.is-success.kw-loadable,
.cta-btn.is-success,
.island-cta-btn.is-success,
.btn-primary.is-success,
.btn-secondary.is-success,
.btn-danger.is-success {
  position: relative;
  color: transparent !important;
}
button.is-success.kw-loadable::after,
.cta-btn.is-success::after,
.island-cta-btn.is-success::after,
.btn-primary.is-success::after,
.btn-secondary.is-success::after,
.btn-danger.is-success::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 12px;
  transform: translate(-50%, -50%) rotate(-45deg);
  border-left: 2.5px solid currentColor;
  border-bottom: 2.5px solid currentColor;
  color: #fff;
  opacity: 0;
  animation: kwCheckFlash 600ms var(--ease-out-back) forwards;
}
@keyframes kwCheckFlash {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(-45deg) scale(0.4);
  }
  60% {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(-45deg) scale(1.08);
  }
  100% {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(-45deg) scale(1);
  }
}

/* ─── §11.2 INPUTS — site-wide focus ring (olive + soft halo) ────────
   Generalizes the Phase 5 auth field focus to ALL inputs on the site.
   Per-page overrides (auth, checkout, chat) remain authoritative
   because their selectors are more specific. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not(
    [type="color"]
  ):focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--olive);
  box-shadow: 0 0 0 4px rgba(74, 93, 35, 0.08);
  transition:
    border-color var(--t-med) var(--ease-out-expo),
    box-shadow var(--t-med) var(--ease-out-expo);
}

/* ─── §11.2 INPUTS — .is-invalid (red border + shake + msg slide) ────
   The wrapping form-row exposes a sibling `.kw-input-msg` slot that
   slides down when the field becomes invalid. The shake is 280ms.
   Use kwAddInputValidation(el, false, msg) from JS to apply. */
input.is-invalid,
select.is-invalid,
textarea.is-invalid {
  border-color: #dc2626 !important;
  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.1) !important;
  animation: kwInputShake 280ms var(--ease-out-expo) 1;
}
@keyframes kwInputShake {
  0%,
  100% {
    transform: translateX(0);
  }
  15% {
    transform: translateX(-5px);
  }
  30% {
    transform: translateX(4px);
  }
  45% {
    transform: translateX(-3px);
  }
  60% {
    transform: translateX(2px);
  }
  75% {
    transform: translateX(-1px);
  }
}
.kw-input-msg {
  display: block;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  color: #dc2626;
  font-size: 12px;
  margin-top: 0;
  transform: translateY(-4px);
  transition:
    opacity var(--t-med) var(--ease-out-expo),
    transform var(--t-med) var(--ease-out-expo);
}
.kw-input-msg.is-visible {
  max-height: 60px;
  opacity: 1;
  margin-top: 6px;
  transform: translateY(0);
}

/* ─── §11.2 INPUTS — .is-valid (green check at right edge) ───────────
   Wrap field in `.kw-input-wrap` so the check can be absolutely
   positioned. Falls back gracefully if no wrap is provided. */
.kw-input-wrap {
  position: relative;
  display: block;
}
.kw-input-wrap::after {
  content: "";
  position: absolute;
  right: 14px;
  top: 50%;
  width: 14px;
  height: 9px;
  transform: translateY(-50%) rotate(-45deg) scale(0.5);
  border-left: 2.5px solid #16a34a;
  border-bottom: 2.5px solid #16a34a;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--t-med) var(--ease-out-back),
    transform var(--t-med) var(--ease-out-back);
}
.kw-input-wrap.is-valid::after {
  opacity: 1;
  transform: translateY(-50%) rotate(-45deg) scale(1);
}

/* ─── §11.3 TOGGLE / SWITCH — generic .toggle.on + olive ripple ──────
   Phase 7 added .pref-toggle ripple. Phase 10 adds a generic
   .toggle / .toggle-knob pair so any future toggle works site-wide
   without bespoke CSS. */
.toggle {
  position: relative;
  display: inline-block;
  width: 44px;
  height: 24px;
  border-radius: 999px;
  background: var(--brd);
  border: none;
  cursor: pointer;
  padding: 0;
  transition: background-color 200ms var(--ease-out-expo);
  overflow: visible;
}
.toggle-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
  transform: translateX(0);
  transition: transform 200ms var(--ease-out-back);
  pointer-events: none;
}
.toggle.on {
  background: var(--olive);
}
.toggle.on .toggle-knob {
  transform: translateX(20px);
}
.toggle::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--olive);
  opacity: 0;
  transform: scale(0.6);
  pointer-events: none;
}
.toggle.just-on::after {
  animation: kwToggleRipple 600ms var(--ease-out-expo) 1;
}
@keyframes kwToggleRipple {
  0% {
    opacity: 0.5;
    transform: scale(0.6);
  }
  100% {
    opacity: 0;
    transform: scale(1.4);
  }
}

/* ─── §11.4 TOASTS — type variants + slide-up + dismiss ──────────────
   The existing `.toast` element is used by `flash()`. Phase 10 adds
   .is-success / .is-warn / .is-error variants with type icons and
   a slide-up entry / fade-down exit. Multiple toasts stack via the
   .kw-toast-stack container if present. */
.toast.is-success,
.toast.is-warn,
.toast.is-error {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-left: 44px;
  position: fixed;
}
.toast.is-success::after,
.toast.is-warn::after,
.toast.is-error::after {
  content: "";
  position: absolute;
  left: 14px;
  top: 50%;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: #fff;
  font-size: 13px;
  line-height: 22px;
  text-align: center;
  background-position: center;
  background-repeat: no-repeat;
}
.toast.is-success::after {
  background-color: #16a34a;
  /* white check via inline SVG */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 12' width='12' height='9'><path d='M1 6.2 5.4 10 15 1' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}
.toast.is-warn::after {
  background-color: var(--gold);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 14' width='4' height='14'><path d='M2 1v8M2 12v1' fill='none' stroke='white' stroke-width='2' stroke-linecap='round'/></svg>");
}
.toast.is-error::after {
  background-color: #dc2626;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' width='10' height='10'><path d='M1 1l12 12M13 1L1 13' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round'/></svg>");
}
.toast.is-dismissing {
  animation: kwToastDismiss 260ms var(--ease-out-expo) forwards;
}
@keyframes kwToastDismiss {
  0% {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }
  100% {
    opacity: 0;
    transform: translateX(-50%) translateY(12px);
  }
}
/* Toast stack — bottom-anchored, gap between siblings. Each toast
   uses position:fixed already; the stack offsets translateY in JS
   if needed (or via :nth-last-of-type below for static stacks). */
.kw-toast-stack {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 400;
  pointer-events: none;
}
.kw-toast-stack > .toast {
  position: relative;
  left: auto;
  bottom: auto;
  transform: none;
  pointer-events: auto;
}

/* ─── §11.5 TOOLTIPS — .kw-tooltip with arrow ────────────────────────
   Pure CSS pattern. A `[data-tooltip]` element shows a tooltip on
   hover/focus with text from its data attribute. Triangle arrow via
   ::after. We use translate + opacity for the transition. */
[data-tooltip] {
  position: relative;
}
[data-tooltip]::before,
[data-tooltip]::after {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transition:
    opacity 200ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo);
  z-index: 500;
}
[data-tooltip]::before {
  content: attr(data-tooltip);
  left: 50%;
  bottom: calc(100% + 10px);
  transform: translateX(-50%) translateY(4px);
  background: var(--text-d);
  color: #fff;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: var(--sh-card);
  max-width: 240px;
}
[data-tooltip]::after {
  content: "";
  left: 50%;
  bottom: calc(100% + 4px);
  transform: translateX(-50%) translateY(4px);
  border: 6px solid transparent;
  border-top-color: var(--text-d);
  width: 0;
  height: 0;
}
[data-tooltip]:hover::before,
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::before,
[data-tooltip]:focus-visible::after {
  opacity: 1;
}
[data-tooltip]:hover::before,
[data-tooltip]:focus-visible::before {
  transform: translateX(-50%) translateY(0);
}
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
  transform: translateX(-50%) translateY(0);
}
/* JS-mounted floating tooltip for kwShowTooltip() */
.kw-tooltip {
  position: absolute;
  background: var(--text-d);
  color: #fff;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: var(--sh-card);
  z-index: 500;
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 200ms var(--ease-out-expo),
    transform 200ms var(--ease-out-expo);
  pointer-events: none;
}
.kw-tooltip.is-in {
  opacity: 1;
  transform: translateY(0);
}
.kw-tooltip::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -6px;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--text-d);
  width: 0;
  height: 0;
}

/* ─── §11.6 MODAL CLOSE — × rotates 90° on hover ─────────────────────
   Common modal close button family. We piggyback on existing class
   names (.cin-close, .lb-close are already styled with hover bg).
   The new .kw-modal-close class gives a clean shared pattern. */
.kw-modal-close,
.cin-close,
.lb-close {
  transition:
    transform 240ms var(--ease-out-back),
    background-color 200ms var(--ease-out-expo);
}
.kw-modal-close:hover,
.cin-close:hover,
.lb-close:hover {
  transform: rotate(90deg);
}
.lb-close:hover {
  /* Preserve existing scale(1.1) from the lightbox close. */
  transform: rotate(90deg) scale(1.1);
}

/* ─── §11 — Reduced-motion overrides ─────────────────────────────────
   All sweep additions revert to no-motion / opacity-only transitions
   under prefers-reduced-motion. */
@media (prefers-reduced-motion: reduce) {
  .ncta:active:not(:disabled),
  .cta-btn:active:not(:disabled),
  .bk-go:active:not(:disabled),
  .island-cta-btn:active:not(:disabled),
  .auth-submit:active:not(:disabled),
  .lout:active:not(:disabled),
  .rc-btn:active:not(:disabled),
  .chat-send-btn:active:not(:disabled),
  .btn-primary:active:not(:disabled),
  .btn-secondary:active:not(:disabled),
  .btn-danger:active:not(:disabled) {
    transform: none !important;
    transition: none !important;
  }
  .ncta::before,
  .cta-btn::before,
  .bk-go::before,
  .island-cta-btn::before {
    transition: opacity 150ms ease !important;
  }
  .lout:hover .danger-icon,
  .btn-danger:hover .danger-icon,
  .danger-btn:hover .danger-icon {
    animation: none !important;
  }
  button.is-loading.kw-loadable::after,
  .cta-btn.is-loading::after,
  .island-cta-btn.is-loading::after,
  .btn-primary.is-loading::after,
  .btn-secondary.is-loading::after,
  .btn-danger.is-loading::after {
    animation: none !important;
    opacity: 0.8 !important;
  }
  button.is-success.kw-loadable::after,
  .cta-btn.is-success::after,
  .island-cta-btn.is-success::after,
  .btn-primary.is-success::after,
  .btn-secondary.is-success::after,
  .btn-danger.is-success::after {
    animation: none !important;
    opacity: 1 !important;
    transform: translate(-50%, -50%) rotate(-45deg) !important;
  }
  input.is-invalid,
  select.is-invalid,
  textarea.is-invalid {
    animation: none !important;
  }
  .kw-input-msg {
    transition: opacity 150ms ease !important;
    transform: none !important;
  }
  .kw-input-wrap::after {
    transition: opacity 150ms ease !important;
    transform: translateY(-50%) rotate(-45deg) !important;
  }
  .toggle-knob {
    transition: none !important;
  }
  .toggle.just-on::after {
    animation: none !important;
    opacity: 0 !important;
  }
  .toast.is-dismissing {
    animation: none !important;
    opacity: 0 !important;
  }
  [data-tooltip]::before,
  [data-tooltip]::after {
    transition: opacity 150ms ease !important;
    transform: translateX(-50%) !important;
  }
  .kw-tooltip {
    transition: opacity 150ms ease !important;
    transform: none !important;
  }
  .kw-modal-close,
  .cin-close,
  .lb-close {
    transition: background-color 150ms ease !important;
  }
  .kw-modal-close:hover,
  .cin-close:hover,
  .lb-close:hover {
    transform: none !important;
  }
}
/* === END §11 MICRO-INTERACTIONS SWEEP (Phase 10) === */

/* ═══════════════════════════════════════════════════════════════════
   === GUEST REVIEWS — submit lifecycle (write/update/delete) ===
   Polish layer on top of the existing .write-rev-* + .rev-card-guest
   markup. Adds: optimistic card entrance, "You" pill, edit/delete
   affordances, 3-dot loading pulse, success check draw-in, error shake.
   ═══════════════════════════════════════════════════════════════════ */

@keyframes revCardIn {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes revCardOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
  }
}
.rev-card-in {
  animation: revCardIn 360ms var(--ease-out-back) both;
}
.rev-card-out {
  animation: revCardOut 240ms var(--ease-in-quart) both;
}

.rev-card-mine {
  box-shadow:
    0 0 0 1px rgba(74, 93, 35, 0.18) inset,
    var(--sh-card);
  border-color: rgba(74, 93, 35, 0.18);
  position: relative;
}
.rev-card-mine::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 56px;
  height: 56px;
  background: radial-gradient(
    circle at top right,
    rgba(200, 169, 81, 0.18),
    transparent 70%
  );
  pointer-events: none;
  border-top-right-radius: inherit;
}
.rev-mine-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: 100px;
  background: var(--olive-3);
  color: var(--olive);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  vertical-align: middle;
  border: 1px solid rgba(74, 93, 35, 0.15);
}

.write-rev-login-icon {
  color: var(--gold);
  flex-shrink: 0;
}

.write-rev-card.is-editing::before {
  background: linear-gradient(90deg, var(--gold), var(--olive), var(--gold));
  background-size: 200% 100%;
}

.write-rev-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}
.write-rev-delete {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1.5px solid rgba(220, 38, 38, 0.22);
  color: #b91c1c;
  padding: 10px 16px;
  border-radius: var(--rs);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition:
    background 180ms var(--ease-out-expo),
    color 180ms var(--ease-out-expo),
    border-color 180ms var(--ease-out-expo);
}
.write-rev-delete:hover {
  background: #fef2f2;
  color: #991b1b;
  border-color: rgba(220, 38, 38, 0.45);
}
.write-rev-delete:focus-visible {
  outline: 2px solid #dc2626;
  outline-offset: 2px;
}
.write-rev-delete svg {
  display: block;
}

.write-rev-btn {
  position: relative;
  min-width: 140px;
  overflow: hidden;
}
.write-rev-btn-label {
  display: inline-block;
  transition:
    opacity 160ms var(--ease-out-expo),
    transform 160ms var(--ease-out-expo);
}
.write-rev-btn.is-loading .write-rev-btn-label {
  opacity: 0;
  transform: translateY(4px);
}
.write-rev-btn.is-success .write-rev-btn-label {
  opacity: 0;
}
.write-rev-btn.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  display: block;
  background:
    radial-gradient(circle, #fff 0 3px, transparent 3.5px) 50% 50% / 6px 6px
      no-repeat,
    radial-gradient(circle, #fff 0 3px, transparent 3.5px) calc(50% - 14px)
      50% / 6px 6px no-repeat,
    radial-gradient(circle, #fff 0 3px, transparent 3.5px) calc(50% + 14px)
      50% / 6px 6px no-repeat;
  opacity: 0.95;
  animation: writeRevDots 1.2s ease-in-out infinite;
}
@keyframes writeRevDots {
  0%,
  100% {
    background-position-y: 50%, 50%, 50%;
  }
  20% {
    background-position:
      calc(50% - 14px) 40%,
      50% 60%,
      calc(50% + 14px) 60%;
  }
  40% {
    background-position:
      calc(50% - 14px) 60%,
      50% 40%,
      calc(50% + 14px) 60%;
  }
  60% {
    background-position:
      calc(50% - 14px) 60%,
      50% 60%,
      calc(50% + 14px) 40%;
  }
}
.write-rev-btn.is-success {
  background: var(--olive);
  animation: writeRevGoldPulse 700ms var(--ease-out-expo) both;
}
.write-rev-btn.is-success::after {
  content: "";
  position: absolute;
  inset: 0;
  background: no-repeat center / 18px 18px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 12 10 17 19 7'/></svg>");
  animation: writeRevCheckIn 360ms var(--ease-out-back) both;
}
@keyframes writeRevCheckIn {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes writeRevGoldPulse {
  0% {
    box-shadow:
      0 0 0 0 rgba(200, 169, 81, 0),
      0 8px 24px -6px rgba(74, 93, 35, 0.35);
  }
  40% {
    box-shadow:
      0 0 0 14px rgba(200, 169, 81, 0.35),
      0 8px 24px -6px rgba(74, 93, 35, 0.45);
  }
  100% {
    box-shadow:
      0 0 0 22px rgba(200, 169, 81, 0),
      0 8px 24px -6px rgba(74, 93, 35, 0.45);
  }
}
.write-rev-btn.is-error {
  animation: writeRevErrorFlash 600ms var(--ease-out-expo) both;
}
@keyframes writeRevErrorFlash {
  0%,
  100% {
    background: var(--olive);
  }
  20%,
  60% {
    background: #b91c1c;
  }
}

@keyframes writeRevShake {
  0%,
  100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-4px);
  }
  40% {
    transform: translateX(4px);
  }
  60% {
    transform: translateX(-3px);
  }
  80% {
    transform: translateX(3px);
  }
}
.write-rev-shake {
  animation: writeRevShake 320ms var(--ease-out-expo) both;
}

.write-rev-success-check {
  display: flex;
  justify-content: center;
  margin-bottom: 10px;
}
.write-rev-success-ring {
  stroke-dasharray: 151;
  stroke-dashoffset: 151;
  animation: writeRevRingDraw 520ms var(--ease-out-expo) 120ms forwards;
}
.write-rev-success-tick {
  stroke-dasharray: 48;
  stroke-dashoffset: 48;
  animation: writeRevTickDraw 320ms var(--ease-out-expo) 480ms forwards;
}
@keyframes writeRevRingDraw {
  to {
    stroke-dashoffset: 0;
  }
}
@keyframes writeRevTickDraw {
  to {
    stroke-dashoffset: 0;
  }
}
.write-rev-success-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 18px;
  flex-wrap: wrap;
}
.write-rev-success-edit,
.write-rev-success-delete {
  padding: 9px 18px;
  border-radius: var(--rs);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition:
    background 180ms var(--ease-out-expo),
    color 180ms var(--ease-out-expo),
    border-color 180ms var(--ease-out-expo),
    transform 180ms var(--ease-out-expo);
}
.write-rev-success-edit {
  background: var(--olive-3);
  color: var(--olive);
  border: 1.5px solid rgba(74, 93, 35, 0.18);
}
.write-rev-success-edit:hover {
  background: rgba(74, 93, 35, 0.12);
  transform: translateY(-1px);
}
.write-rev-success-delete {
  background: none;
  color: #b91c1c;
  border: 1.5px solid rgba(220, 38, 38, 0.22);
}
.write-rev-success-delete:hover {
  background: #fef2f2;
  border-color: rgba(220, 38, 38, 0.4);
}
.write-rev-success-edit:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
}
.write-rev-success-delete:focus-visible {
  outline: 2px solid #dc2626;
  outline-offset: 2px;
}

.wr-star:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 4px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .rev-card-in,
  .rev-card-out,
  .write-rev-shake,
  .write-rev-btn.is-success,
  .write-rev-btn.is-error,
  .write-rev-btn.is-loading::after,
  .write-rev-btn.is-success::after {
    animation: none !important;
  }
  .write-rev-btn.is-loading::after {
    display: none;
  }
  .write-rev-success-ring,
  .write-rev-success-tick {
    animation: none !important;
    stroke-dashoffset: 0;
  }
}
/* === END GUEST REVIEWS — submit lifecycle === */

/* ═══════════════════════════════════════════════════════════════════
   === SVG PALMS — Replaces canvas palms (§4 rev2) ===
   See _kwPalmSvg() in script.js. The legacy .magic__palms canvas rules
   above this block are harmless dead code (the canvases are no longer
   rendered). Removing them is a future cleanup; not done here to keep
   the diff focused on the visible change.
   ═══════════════════════════════════════════════════════════════════ */

.kw-palm-wrap {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 300px;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}
.kw-palm-wrap--left {
  left: -30px;
}
.kw-palm-wrap--right {
  right: -30px;
}
.kw-palm-wrap--right > .kw-palm {
  transform: scaleX(-1);
  transform-origin: 50% 100%;
}

.kw-palm {
  position: absolute;
  bottom: -12px;
  width: auto;
  /* Anchored by individual nth-child rules below */
}
.kw-palm-wrap > .kw-palm:nth-child(1) {
  left: -6%;
  height: 95%;
  filter: drop-shadow(0 6px 12px rgba(15, 26, 10, 0.1));
}
.kw-palm-wrap > .kw-palm:nth-child(2) {
  left: 38%;
  height: 72%;
  opacity: 0.55;
  filter: drop-shadow(0 4px 8px rgba(15, 26, 10, 0.06));
}

/* The SVG's own internal fills/strokes (set in the markup) provide the
   tree's color. Below we just style classes that need to apply uniformly
   across all palms. */
.kw-palm-rings line {
  stroke: #0a120a;
  stroke-width: 1;
  opacity: 0.32;
  stroke-linecap: round;
}
.kw-palm-frond-spine {
  stroke: #1f2a1a;
  stroke-width: 2.4;
  fill: none;
  stroke-linecap: round;
}
.kw-palm-frond-leaflets line {
  stroke: #1f2a1a;
  stroke-width: 1.4;
  stroke-linecap: round;
}
.kw-palm-coconuts circle {
  fill: #0a120a;
}

/* Ambient sway. Crown rocks gently; each frond layers a smaller per-frond
   oscillation on top with desynced duration + negative animation-delay
   (set inline per-frond by _kwPalmSvg) so no two fronds match phase. */
.kw-palm-crown {
  animation: kwPalmCrownSway 5.5s ease-in-out infinite;
}
.kw-palm-frond {
  animation: kwPalmFrondSway 4s ease-in-out infinite;
}
@keyframes kwPalmCrownSway {
  0%,
  100% {
    transform: rotate(-1.4deg);
  }
  50% {
    transform: rotate(1.4deg);
  }
}
@keyframes kwPalmFrondSway {
  0%,
  100% {
    transform: rotate(-1.6deg);
  }
  50% {
    transform: rotate(1.6deg);
  }
}

/* Mobile: smaller wrap, single palm per side, sway slightly toned down. */
@media (max-width: 768px) {
  .kw-palm-wrap {
    width: 190px;
  }
  .kw-palm-wrap--left {
    left: -20px;
  }
  .kw-palm-wrap--right {
    right: -20px;
  }
  .kw-palm-wrap > .kw-palm:nth-child(1) {
    left: -8%;
    height: 80%;
  }
  .kw-palm-wrap > .kw-palm:nth-child(2) {
    display: none;
  }
}

/* Reduced motion: hold the resting pose, no sway. */
@media (prefers-reduced-motion: reduce) {
  .kw-palm-crown,
  .kw-palm-frond {
    animation: none;
  }
}
/* === END SVG PALMS === */

/* ═══════════════════════════════════════════════════════════════════
   INSTALL PROMPT — bottom sheet + persistent bubble
   See: docs/superpowers/specs/2026-05-18-install-prompt-and-whatsapp-slide-design.md
   ═══════════════════════════════════════════════════════════════════ */
.kw-install-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(42, 47, 36, 0.32);
  z-index: 9998;
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.kw-install-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

.kw-install-sheet {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: #faf9f6;
  border-radius: 24px 24px 0 0;
  border-top: 1px solid rgba(74, 93, 35, 0.08);
  padding: 22px 18px calc(18px + env(safe-area-inset-bottom));
  box-shadow: 0 -16px 40px rgba(0, 0, 0, 0.18);
  z-index: 9999;
  transform: translateY(110%);
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
  max-width: 480px;
  margin: 0 auto;
}
.kw-install-sheet.is-open {
  transform: translateY(0);
}

.kw-install-drag {
  width: 38px;
  height: 4px;
  background: #d4cfc3;
  border-radius: 2px;
  margin: 0 auto 14px;
}
.kw-install-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: #e8eddc;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
  color: #4a5d23;
}
.kw-install-title {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 19px;
  font-weight: 600;
  color: #2a2f24;
  margin: 0 0 4px;
  line-height: 1.2;
}
.kw-install-body {
  font-size: 13px;
  color: #6a7160;
  margin: 0 0 14px;
  line-height: 1.5;
  font-family: "Outfit", sans-serif;
}
.kw-install-steps {
  font-size: 12px;
  color: #2a2f24;
  margin: 0 0 14px;
  padding-left: 18px;
  line-height: 1.6;
  font-family: "Outfit", sans-serif;
}
.kw-install-steps li {
  margin-bottom: 3px;
}
.kw-install-share-svg {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  background: rgba(0, 122, 255, 0.12);
  border-radius: 4px;
  color: #007aff;
  vertical-align: -4px;
  margin: 0 2px;
}
.kw-install-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kw-install-btn-primary {
  background: #4a5d23;
  color: white;
  border: none;
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: "Outfit", sans-serif;
}
.kw-install-btn-secondary {
  background: transparent;
  color: #6a7160;
  border: none;
  padding: 10px 16px;
  font-size: 13px;
  cursor: pointer;
  font-family: "Outfit", sans-serif;
}

.kw-install-bubble {
  position: fixed;
  bottom: calc(16px + env(safe-area-inset-bottom));
  left: 16px;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: #4a5d23;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow:
    0 6px 20px rgba(74, 93, 35, 0.32),
    0 2px 6px rgba(0, 0, 0, 0.18);
  z-index: 9997;
  cursor: pointer;
  opacity: 0;
  transform: scale(0.6);
  transition:
    opacity 0.3s ease,
    transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.kw-install-bubble.is-open {
  opacity: 1;
  transform: scale(1);
}
.kw-install-bubble::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid #4a5d23;
  opacity: 0.4;
  animation: kwBubblePulse 2.6s ease-in-out infinite;
  pointer-events: none;
}
@keyframes kwBubblePulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.4;
  }
  50% {
    transform: scale(1.18);
    opacity: 0;
  }
}
.kw-install-bubble-x {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 18px;
  height: 18px;
  background: #6a7160;
  color: white;
  font-size: 11px;
  line-height: 1;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #faf9f6;
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  .kw-install-sheet,
  .kw-install-backdrop,
  .kw-install-bubble {
    transition: none;
  }
  .kw-install-bubble::after {
    animation: none;
  }
}

/* ─── INSTALL PROMPT — Guide mode (iOS "Got it, show me") ─────────── */
.kw-install-sheet.kw-install-guide {
  bottom: auto;
  top: 0;
  border-radius: 0 0 24px 24px;
  border-top: none;
  border-bottom: 1px solid rgba(74, 93, 35, 0.08);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18);
  padding: calc(env(safe-area-inset-top) + 14px) 16px 14px;
  transform: translateY(-110%);
}
.kw-install-sheet.kw-install-guide.is-open {
  transform: translateY(0);
}

.kw-install-guide-row {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 460px;
  margin: 0 auto;
}
.kw-install-icon-sm {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  margin-bottom: 0;
  background: #e8eddc;
}
.kw-install-icon-sm svg {
  width: 18px;
  height: 18px;
}
.kw-install-guide-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.kw-install-guide-text strong {
  font-family: "Outfit", sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #2a2f24;
  line-height: 1.2;
}
.kw-install-guide-text span {
  font-family: "Outfit", sans-serif;
  font-size: 11px;
  color: #6a7160;
  line-height: 1.3;
}
.kw-install-guide-done {
  flex-shrink: 0;
  padding: 8px 14px !important;
  font-size: 12px !important;
  background: rgba(74, 93, 35, 0.08) !important;
  color: #4a5d23 !important;
  border-radius: 10px !important;
}

.kw-install-guide-arrow {
  position: fixed;
  left: 50%;
  bottom: calc(56px + env(safe-area-inset-bottom));
  transform: translate(-50%, 8px);
  z-index: 9998;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  opacity: 0;
  transition:
    opacity 0.35s ease,
    transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.kw-install-guide-arrow.is-open {
  opacity: 1;
  transform: translate(-50%, 0);
}
.kw-install-guide-arrow-pill {
  background: rgba(74, 93, 35, 0.96);
  color: white;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  font-family: "Outfit", sans-serif;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
  white-space: nowrap;
  letter-spacing: 0.2px;
}
.kw-install-guide-arrow svg {
  width: 44px;
  height: 44px;
  color: #4a5d23;
  filter: drop-shadow(0 6px 14px rgba(74, 93, 35, 0.45));
  animation: kwGuideArrowBounce 1.4s ease-in-out infinite;
}
@keyframes kwGuideArrowBounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(10px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .kw-install-guide-arrow svg {
    animation: none;
  }
  .kw-install-sheet.kw-install-guide {
    transition: none;
  }
}

/* ═══════════════════════════════════════════════════════════════
   Plan 1 — Foundation: ticks, presence, typing label, RR toggle
   ═══════════════════════════════════════════════════════════════ */

/* ── 3-state ticks ─────────────────────────────────────────── */
.msg-tick-sending {
  display: inline-block;
  font-size: 11px;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.7);
  opacity: 0.9;
  animation: kwTickSendingPulse 1.2s ease-in-out infinite;
}
@keyframes kwTickSendingPulse {
  0%,
  100% {
    opacity: 0.45;
  }
  50% {
    opacity: 0.9;
  }
}
.msg-tick-sent {
  width: 12px;
  height: 8px;
  color: rgba(255, 255, 255, 0.7);
}
.msg-tick-sent svg {
  width: 100%;
  height: 100%;
}
.msg-tick-delivered {
  width: 16px;
  height: 8px;
  color: rgba(255, 255, 255, 0.85);
}
.msg-tick-delivered svg {
  width: 100%;
  height: 100%;
}
.msg-tick-read {
  width: 16px;
  height: 8px;
  color: #4fc3f7;
}
.msg-tick-read svg {
  width: 100%;
  height: 100%;
}

.chat-msg-pro.me .msg-time .msg-tick {
  margin-left: 4px;
  vertical-align: middle;
}

/* ── Header presence pill (Spec B2) ─────────────────────────── */
.chat-header-presence {
  font-size: 12px;
  color: var(--text-m);
  display: flex;
  align-items: center;
  gap: 6px;
  line-height: 1.2;
  margin: 2px 0 0;
}
.chat-header-presence.is-online::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #34c759;
  box-shadow: 0 0 0 2px rgba(52, 199, 89, 0.18);
}
.chat-header-presence:not(.is-online)::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--cream-2, #d8d3c5);
}

/* ── Typing label visibility (B3) ───────────────────────────── */
.typing-row-pro .typing-label,
.typing-row .typing-label {
  font-size: 12px;
  color: var(--text-m);
  font-style: italic;
  margin-left: 4px;
  display: inline-block;
}

/* ── Admin chat-list per-row "X is typing…" line (B3) ───────── */
.chat-typing-line {
  font-size: 11px;
  color: var(--olive, #4a5d23);
  font-style: italic;
  margin-top: 2px;
  display: none;
  animation: kwTypingLineIn 0.2s ease-out both;
}
.chat-typing-line.show {
  display: block;
}
@keyframes kwTypingLineIn {
  from {
    opacity: 0;
    transform: translateX(-3px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

/* ── Per-chat read-receipt privacy toggle button ────────────── */
.chat-rr-toggle {
  margin-left: 6px;
}
.chat-rr-toggle .cmm-glyph {
  font-size: 16px;
}

/* ── Reduced motion ─────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .msg-tick-sending {
    animation: none;
    opacity: 0.7;
  }
  .chat-typing-line {
    animation: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   §C2.A — MESSAGE INTERACTIONS (Plan 2)
   Action menu overlay, reaction strip, reply quote, pin banner, etc.
   ═══════════════════════════════════════════════════════════════════ */

/* Bubble — long-press lift effect (mobile) */
.chat-msg.is-lifted {
  transform: scale(1.04);
  box-shadow: 0 18px 50px rgba(27, 33, 18, 0.18);
  transition:
    transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1),
    box-shadow 180ms ease;
  z-index: 5;
  position: relative;
}
@media (prefers-reduced-motion: reduce) {
  .chat-msg.is-lifted {
    transform: none;
    transition: none;
  }
}

/* Bubble — reply-by-swipe transform (mobile only) */
.chat-msg.is-swiping {
  transition: none;
  will-change: transform;
}
.chat-msg.is-swipe-bounce {
  transform: translateX(0) !important;
  transition: transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.chat-msg .msg-swipe-hint {
  position: absolute;
  top: 50%;
  left: -32px;
  transform: translateY(-50%) scale(0.6);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(74, 93, 35, 0.18);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 120ms ease,
    transform 120ms ease;
}
.chat-msg.is-swiping .msg-swipe-hint {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}
.chat-msg.is-swiping .msg-swipe-hint svg {
  width: 14px;
  height: 14px;
  color: var(--olive);
}

/* Floating action toolbar (desktop, hover) */
.chat-msg .msg-hover-toolbar {
  position: absolute;
  top: -36px;
  right: 8px;
  /* Phase I — switched from display:none/inline-flex to opacity +
     pointer-events. Pure :hover triggers were sticky on touch-capable
     devices (laptops with touchscreen, iPad+mouse, etc.) — once a
     touch synthesised a hover the toolbar stayed visible AND
     interactive, which is what produced the "ghost touch" symptom
     when the bubbles re-rendered under a stuck hover state. */
  display: inline-flex;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition:
    opacity 0.12s ease,
    visibility 0s linear 0.12s;
  background: #fff;
  border: 1px solid var(--brd);
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(27, 33, 18, 0.12);
  padding: 4px 6px;
  gap: 2px;
  z-index: 4;
}
.chat-msg.me .msg-hover-toolbar {
  right: auto;
  left: 8px;
}
/* Show only when a real mouse hovers (not synthesised by a touch).
   bindMsgInteractions adds .is-mouse-hover on pointerenter where
   pointerType==='mouse', removes on pointerleave; pure :hover is
   kept as a fallback for older browsers that don't fire pointer
   events but is wrapped in @media (hover: hover) and (pointer: fine)
   so it only matches real-hover devices. */
.chat-msg.is-mouse-hover .msg-hover-toolbar {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition:
    opacity 0.12s ease,
    visibility 0s linear 0s;
}
@media (hover: hover) and (pointer: fine) {
  .chat-msg:hover .msg-hover-toolbar {
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transition:
      opacity 0.12s ease,
      visibility 0s linear 0s;
  }
}
/* Phase C/5 — flip the hover toolbar BELOW the first visible message in
   the chat so it isn't clipped by .chat-messages overflow at the top. */
.chat-msg:first-child .msg-hover-toolbar {
  top: auto;
  bottom: -36px;
}
.msg-hover-toolbar button {
  background: transparent;
  border: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 14px;
  cursor: pointer;
  color: var(--text-s);
  display: flex;
  align-items: center;
  justify-content: center;
}
.msg-hover-toolbar button:hover {
  background: var(--olive-10);
  color: var(--olive);
}
@media (max-width: 768px) {
  .chat-msg .msg-hover-toolbar {
    display: none !important;
  }
}

/* Full-screen action overlay (mobile long-press) */
.msg-action-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: rgba(15, 20, 12, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  opacity: 0;
  transition: opacity 220ms ease;
}
.msg-action-overlay.is-open {
  opacity: 1;
}
.msg-action-overlay-inner {
  background: #fff;
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  padding: 16px 14px calc(20px + env(safe-area-inset-bottom));
  transform: translateY(40px);
  transition: transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1);
  max-height: 80vh;
  overflow-y: auto;
}
.msg-action-overlay.is-open .msg-action-overlay-inner {
  transform: translateY(0);
}
/* Phase L — Explicit close X for the action menu. Without it,
   users had no visible way to dismiss the sheet other than
   tapping the dark backdrop (mobile) or pressing Esc (desktop).
   Both work post-fix, but the X is the clearest affordance. */
.msg-action-close {
  position: absolute;
  top: 8px;
  right: 12px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(15, 20, 12, 0.06);
  color: var(--text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  transition: background 0.15s ease;
}
.msg-action-close:hover {
  background: rgba(15, 20, 12, 0.12);
}
.msg-action-close:active {
  background: rgba(15, 20, 12, 0.18);
}
.msg-action-overlay-inner {
  position: relative;
}
@media (min-width: 1024px) {
  /* On desktop the popover is small; tuck the close button a hair
     further into the corner so it doesn't crowd the reaction strip. */
  .msg-action-close {
    top: 6px;
    right: 8px;
    width: 28px;
    height: 28px;
    font-size: 18px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .msg-action-overlay,
  .msg-action-overlay-inner {
    transition: none;
  }
  .msg-action-overlay-inner {
    transform: none;
  }
}

/* Phase B/5 — Desktop: the full-screen mobile sheet looks oversized
   when triggered from a right-click on a roomy laptop. Switch to a
   contextual popover anchored next to the clicked bubble. JS sets
   inline top/left coords based on the bubble's bounding rect. */
@media (min-width: 1024px) {
  .msg-action-overlay {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    pointer-events: none;
    align-items: flex-start;
    justify-content: flex-start;
  }
  .msg-action-overlay-inner {
    pointer-events: auto;
    position: absolute;
    max-width: 320px;
    max-height: 70vh;
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
    transform: none;
    padding: 12px 10px;
  }
  .msg-action-overlay.is-open .msg-action-overlay-inner {
    transform: none;
  }
}

.msg-action-reactions {
  display: flex;
  justify-content: space-around;
  align-items: center;
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 4px 18px rgba(27, 33, 18, 0.12);
  padding: 8px 10px;
  margin: 0 8px 14px;
  gap: 4px;
}
.msg-action-reactions button {
  background: transparent;
  border: 0;
  font-size: 26px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  cursor: pointer;
  transition:
    transform 120ms ease,
    background 120ms ease;
}
.msg-action-reactions button:hover,
.msg-action-reactions button:active {
  transform: scale(1.18);
  background: var(--olive-10);
}
.msg-action-reactions .react-plus {
  font-size: 20px;
  color: var(--olive);
}

.msg-action-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.msg-action-list li {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 10px;
  font-size: 15px;
  font-family: "Outfit", sans-serif;
  color: var(--text-s);
  cursor: pointer;
  border-radius: 12px;
  transition: background 120ms ease;
}
.msg-action-list li:hover,
.msg-action-list li:active {
  background: var(--olive-10);
}
.msg-action-list li[data-action="delete"] {
  color: #b33a2d;
}
.msg-action-list li[data-action="delete"]:hover {
  background: rgba(179, 58, 45, 0.08);
}
.msg-action-list li .mal-ic {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}
.msg-action-list li.is-hidden {
  display: none;
}

/* Reaction chips below bubble */
.msg-reaction-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.msg-reaction-chip {
  background: #fff;
  border: 1px solid var(--brd);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 12px;
  line-height: 1.4;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  transition:
    transform 160ms cubic-bezier(0.34, 1.56, 0.64, 1),
    background 120ms ease;
}
.msg-reaction-chip.is-mine {
  background: var(--olive-10);
  border-color: var(--olive-20);
}
.msg-reaction-chip:hover {
  transform: scale(1.06);
}
.msg-reaction-chip.is-bump {
  animation: msgChipBump 360ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes msgChipBump {
  0% {
    transform: scale(0.6);
  }
  60% {
    transform: scale(1.18);
  }
  100% {
    transform: scale(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .msg-reaction-chip.is-bump {
    animation: none;
  }
}

/* Who-reacted bottom sheet */
.msg-who-sheet {
  position: fixed;
  inset: 0;
  z-index: 9100;
  background: rgba(15, 20, 12, 0.5);
  display: flex;
  justify-content: center;
  align-items: flex-end;
  opacity: 0;
  transition: opacity 200ms ease;
}
.msg-who-sheet.is-open {
  opacity: 1;
}
.msg-who-sheet-inner {
  background: #fff;
  width: 100%;
  max-width: 480px;
  border-top-left-radius: 20px;
  border-top-right-radius: 20px;
  padding: 16px 16px calc(20px + env(safe-area-inset-bottom));
  transform: translateY(40px);
  transition: transform 240ms cubic-bezier(0.34, 1.56, 0.64, 1);
  max-height: 70vh;
  overflow-y: auto;
}
.msg-who-sheet.is-open .msg-who-sheet-inner {
  transform: translateY(0);
}
.msg-who-sheet h4 {
  font-family: "Playfair Display", serif;
  margin: 0 0 12px;
  font-size: 18px;
  color: var(--text-d);
}
.msg-who-sheet-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--brd-l);
  font-size: 14px;
}
.msg-who-sheet-row .mwr-emoji {
  font-size: 22px;
}
.msg-who-sheet-row:last-child {
  border-bottom: 0;
}

/* Reply quote — composer preview chip */
.chat-reply-preview {
  display: none;
  align-items: stretch;
  background: var(--olive-3);
  border-left: 3px solid var(--olive);
  padding: 8px 10px;
  margin: 0 12px 6px;
  border-radius: 8px;
  font-size: 12px;
  color: var(--text-s);
  gap: 8px;
}
.chat-reply-preview.is-active {
  display: flex;
}
.chat-reply-preview .crp-body {
  flex: 1;
  min-width: 0;
}
.chat-reply-preview .crp-label {
  font-weight: 700;
  color: var(--olive);
  display: block;
  margin-bottom: 2px;
  font-size: 11px;
}
.chat-reply-preview .crp-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}
.chat-reply-preview .crp-cancel {
  background: transparent;
  border: 0;
  font-size: 18px;
  line-height: 1;
  color: var(--text-m);
  cursor: pointer;
  align-self: flex-start;
  padding: 0 4px;
}

/* Mini-bubble (quoted message rendered above the reply) */
.msg-mini-quote {
  background: rgba(74, 93, 35, 0.06);
  border-left: 3px solid var(--olive);
  padding: 6px 8px;
  margin: 0 0 6px;
  border-radius: 8px;
  font-size: 12px;
  color: var(--text-s);
  cursor: pointer;
  max-width: 100%;
  overflow: hidden;
  display: block;
}
.msg-mini-quote .mmq-name {
  font-weight: 700;
  color: var(--olive);
  font-size: 11px;
  display: block;
  margin-bottom: 2px;
}
.msg-mini-quote .mmq-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}
.msg-mini-quote.is-deleted {
  font-style: italic;
  color: var(--text-m);
}

/* Scroll-target highlight pulse */
.chat-msg.is-scroll-target {
  animation: msgScrollPulse 1400ms ease-out;
}
@keyframes msgScrollPulse {
  0% {
    background-color: rgba(200, 169, 81, 0.4);
  }
  100% {
    background-color: transparent;
  }
}
@media (prefers-reduced-motion: reduce) {
  .chat-msg.is-scroll-target {
    animation: none;
  }
}

/* "(edited)" label */
.msg-edited-label {
  font-size: 10px;
  color: var(--text-m);
  margin-left: 6px;
  font-style: italic;
}

/* Tombstone (deleted) */
.chat-msg.is-deleted {
  font-style: italic;
  color: var(--text-m);
  background: rgba(0, 0, 0, 0.04) !important;
  border: 1px dashed var(--brd) !important;
}
.chat-msg.is-deleted .msg-tombstone {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.chat-msg.is-deleted .msg-reaction-chips,
.chat-msg.is-deleted .msg-hover-toolbar {
  display: none !important;
}

/* Pinned banner */
.chat-pin-banner {
  display: none;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, var(--gold-light), #fff);
  border-bottom: 1px solid var(--brd);
  padding: 8px 12px;
  font-size: 12px;
  color: var(--text-s);
  cursor: pointer;
  position: relative;
}
.chat-pin-banner.is-active {
  display: flex;
}
.chat-pin-banner .cpb-icon {
  font-size: 14px;
}
.chat-pin-banner .cpb-label {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-pin-banner .cpb-label strong {
  color: var(--olive);
  margin-right: 6px;
}
.chat-pin-banner .cpb-unpin {
  background: transparent;
  border: 0;
  color: var(--text-m);
  font-size: 16px;
  cursor: pointer;
  padding: 2px 6px;
  line-height: 1;
}

/* Forwarded label */
.msg-forwarded-label {
  font-size: 10px;
  color: var(--text-m);
  display: flex;
  align-items: center;
  gap: 3px;
  margin-bottom: 2px;
}
.msg-forwarded-label::before {
  content: "↪";
  font-size: 11px;
}

/* Forward picker */
.fwd-picker {
  position: fixed;
  inset: 0;
  z-index: 9200;
  background: rgba(15, 20, 12, 0.55);
  display: flex;
  justify-content: center;
  align-items: flex-end;
  opacity: 0;
  transition: opacity 200ms ease;
}
.fwd-picker.is-open {
  opacity: 1;
}
.fwd-picker-inner {
  background: #fff;
  width: 100%;
  max-width: 540px;
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  transform: translateY(40px);
  transition: transform 240ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.fwd-picker.is-open .fwd-picker-inner {
  transform: translateY(0);
}
.fwd-picker h4 {
  font-family: "Playfair Display", serif;
  margin: 0 0 8px;
  font-size: 18px;
  color: var(--text-d);
}
.fwd-picker .fwd-list {
  flex: 1;
  overflow-y: auto;
  margin: 6px 0 12px;
  border-top: 1px solid var(--brd-l);
}
.fwd-picker .fwd-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 4px;
  border-bottom: 1px solid var(--brd-l);
  cursor: pointer;
  font-size: 14px;
}
.fwd-picker .fwd-row input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--olive);
}
.fwd-picker .fwd-name {
  font-weight: 600;
  color: var(--text-d);
}
.fwd-picker .fwd-preview {
  font-size: 12px;
  color: var(--text-m);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60vw;
}
.fwd-picker-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.fwd-picker-actions button {
  font-family: "Outfit", sans-serif;
  border: 0;
  border-radius: 12px;
  padding: 10px 18px;
  font-size: 14px;
  cursor: pointer;
}
.fwd-picker-actions .fwd-cancel {
  background: var(--brd-l);
  color: var(--text-s);
}
.fwd-picker-actions .fwd-send {
  background: var(--olive);
  color: #fff;
}
.fwd-picker-actions .fwd-send[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ─── Plan 3 / C4 — Booking-context header card (admin) ───────── */
.chat-bk-card {
  display: flex;
  flex-direction: column;
  border-bottom: 1px solid var(--brd-l);
  background: linear-gradient(
    180deg,
    rgba(74, 93, 35, 0.04),
    rgba(74, 93, 35, 0)
  );
  font-family: var(--sans);
}
.chat-bk-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 18px;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  font-size: 13px;
  color: var(--text);
}
.chat-bk-icon {
  font-size: 16px;
  line-height: 1;
}
.chat-bk-summary {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat-bk-chev {
  color: var(--text-m);
  font-size: 12px;
}
.chat-bk-detail {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 4px 12px;
  padding: 4px 18px 12px;
  font-size: 12.5px;
  color: var(--text);
  max-height: 240px;
  overflow: hidden;
  transition:
    max-height 0.25s ease,
    padding 0.25s ease,
    opacity 0.25s ease;
}
.chat-bk-card.is-collapsed .chat-bk-detail {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  opacity: 0;
  pointer-events: none;
}
.chat-bk-k {
  color: var(--text-m);
  font-weight: 500;
}
.chat-bk-v {
  color: var(--text);
}
.chat-bk-row {
  display: contents;
}
.chat-bk-link {
  grid-column: 1 / -1;
  margin-top: 8px;
  color: var(--olive);
  font-weight: 600;
  text-decoration: none;
  font-size: 12.5px;
}
.chat-bk-link:hover {
  text-decoration: underline;
}
.chat-bk-empty {
  padding: 10px 18px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
  color: var(--text-m);
}
.chat-bk-empty .chat-bk-title {
  font-weight: 600;
  color: var(--text);
}

/* ─── Plan 3 / C2 — Composer slash-picker + note/snippet buttons ── */
.chat-snip-picker {
  position: relative;
  display: none;
  max-height: 260px;
  overflow-y: auto;
  border-top: 1px solid var(--brd-l);
  background: var(--wh);
}
.chat-snip-picker.show {
  display: block;
}
.chat-snip-row {
  padding: 10px 18px;
  border-bottom: 1px solid var(--brd-l);
  cursor: pointer;
  font-family: var(--sans);
  font-size: 13px;
  transition: background 0.15s ease;
}
.chat-snip-row:last-child {
  border-bottom: none;
}
.chat-snip-row:hover,
.chat-snip-row.is-active {
  background: rgba(74, 93, 35, 0.08);
}
.chat-snip-empty {
  color: var(--text-m);
  font-style: italic;
}
.chat-snip-top {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.chat-snip-shortcut {
  font-family: monospace;
  font-weight: 700;
  color: var(--olive);
  font-size: 12.5px;
}
.chat-snip-title {
  font-weight: 600;
  color: var(--text);
}
.chat-snip-preview {
  color: var(--text-m);
  font-size: 12px;
  margin-top: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-snip-btn,
.chat-note-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1.5px solid var(--brd);
  background: var(--wh);
  color: var(--text);
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  transition:
    background 0.15s ease,
    transform 0.1s ease;
}
.chat-snip-btn:hover,
.chat-note-btn:hover {
  background: var(--cream);
  transform: scale(1.05);
}
.chat-note-btn.is-active {
  background: #fff7c2;
  border-color: #d4b800;
}
.chat-input-bar.is-note-mode {
  background: #fffbe0;
}
.chat-input-bar.is-note-mode input {
  background: #fffceb;
  border-color: #d4b800;
}

/* ─── Plan 3 / C3 — Internal-note bubble (admin view only) ─────── */
.chat-msg.is-note {
  background: #fff7c2 !important;
  border-left: 3px solid #d4b800;
  color: #5b4f00;
}
.chat-msg.is-note .msg-sender {
  color: #7a6a00;
}
.chat-msg.is-note .msg-note-badge {
  margin-left: 6px;
  padding: 1px 6px;
  background: #d4b800;
  color: #3a2f00;
  font-size: 11px;
  border-radius: 4px;
  font-weight: 700;
  letter-spacing: 0.3px;
}

/* ─── Plan 3 / C2 — Snippets management UI ───────────────────── */
.adm-quicklink {
  padding: 8px 14px;
  border: 1px solid var(--brd);
  border-radius: 999px;
  background: var(--wh);
  font-family: var(--sans);
  font-size: 13px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 0.15s ease;
}
.adm-quicklink:hover {
  background: var(--cream);
}
.snip-toolbar {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 18px;
}
.snip-new-btn {
  padding: 10px 18px;
  border-radius: 100px;
  background: var(--olive);
  color: #fff;
  border: none;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.snip-new-btn:hover {
  background: var(--olive-60);
}
.snip-count {
  color: var(--text-m);
  font-size: 12px;
}
.snip-list {
  display: grid;
  gap: 14px;
}
.snip-row {
  background: var(--wh);
  border: 1px solid var(--brd-l);
  border-radius: 14px;
  padding: 14px 18px;
  font-family: var(--sans);
}
.snip-row-top {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.snip-row-shortcut {
  font-family: monospace;
  font-weight: 700;
  color: var(--olive);
  background: rgba(74, 93, 35, 0.08);
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 13px;
}
.snip-row-title {
  font-weight: 600;
  color: var(--text);
}
.snip-row-uses {
  margin-left: auto;
  color: var(--text-m);
  font-size: 12px;
}
.snip-row-body {
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}
.snip-row-ph {
  font-size: 11.5px;
  color: var(--text-m);
  margin-top: 6px;
}
.snip-row-ph code {
  font-family: monospace;
  background: var(--cream);
  padding: 1px 4px;
  border-radius: 3px;
}
.snip-row-acts {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.snip-btn {
  padding: 6px 14px;
  border-radius: 8px;
  border: 1px solid var(--brd);
  background: var(--wh);
  font-family: var(--sans);
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s ease;
}
.snip-btn:hover {
  background: var(--cream);
}
.snip-btn-edit {
  color: var(--olive);
}
.snip-btn-del {
  color: #c92a2a;
  border-color: #f4b9b9;
}
.snip-empty {
  color: var(--text-m);
  text-align: center;
  padding: 36px;
  border: 1px dashed var(--brd);
  border-radius: 14px;
}
.snip-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}
.snip-modal[hidden] {
  display: none;
}
.snip-modal-card {
  background: var(--wh);
  border-radius: 16px;
  padding: 24px;
  width: 100%;
  max-width: 480px;
  font-family: var(--sans);
}
.snip-modal-card h3 {
  margin: 0 0 16px 0;
  font-size: 18px;
  color: var(--text);
}
.snip-field {
  display: block;
  margin-bottom: 14px;
}
.snip-field > span {
  display: block;
  font-size: 12px;
  color: var(--text-m);
  margin-bottom: 4px;
  font-weight: 600;
}
.snip-field input,
.snip-field textarea,
.snip-field select {
  width: 100%;
  padding: 10px 14px;
  border: 1.5px solid var(--brd);
  border-radius: 10px;
  font-family: var(--sans);
  font-size: 13px;
  background: var(--wh);
  color: var(--text);
  outline: none;
  resize: vertical;
}
.snip-field input:focus,
.snip-field textarea:focus,
.snip-field select:focus {
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.snip-modal-acts {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 12px;
}
.snip-btn-cancel {
  background: var(--wh);
}
.snip-btn-save {
  background: var(--olive);
  color: #fff;
  border-color: var(--olive);
  padding: 8px 18px;
  font-weight: 600;
}
.snip-btn-save:hover {
  background: var(--olive-60);
}

/* ─── Chat Auto-Replies admin (Tier 1 deterministic auto-responder) ─── */
.cauto-warn,
.cauto-live {
  font-size: 13px;
  line-height: 1.5;
  border-radius: 12px;
  padding: 12px 16px;
  margin-bottom: 18px;
}
.cauto-warn {
  background: rgba(202, 168, 74, 0.12);
  border: 1px solid rgba(202, 168, 74, 0.4);
  color: var(--text);
}
.cauto-live {
  background: rgba(74, 93, 35, 0.1);
  border: 1px solid rgba(74, 93, 35, 0.35);
  color: var(--text);
}
.cauto-card {
  background: var(--wh);
  border: 1px solid var(--brd-l);
  border-radius: 16px;
  padding: 18px;
  margin-bottom: 26px;
  display: grid;
  gap: 16px;
  font-family: var(--sans);
}
.cauto-switch {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
  color: var(--text);
  cursor: pointer;
  min-height: 44px; /* comfortable touch target */
}
.cauto-switch .cauto-cb {
  /* Visually hidden but still accessible — the styled track below is the
     visible control. We don't rely on the native checkbox because a
     global reset strips its appearance (that's why the toggle rendered
     blank). The whole label is clickable, so the hidden input still
     toggles. */
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}
.cauto-track {
  flex: 0 0 auto;
  width: 46px;
  height: 28px;
  border-radius: 999px;
  background: var(--brd);
  position: relative;
  transition: background 0.18s ease;
}
.cauto-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: transform 0.18s ease;
}
.cauto-switch .cauto-cb:checked + .cauto-track {
  background: var(--olive);
}
.cauto-switch .cauto-cb:checked + .cauto-track .cauto-thumb {
  transform: translateX(18px);
}
.cauto-switch .cauto-cb:focus-visible + .cauto-track {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .cauto-track,
  .cauto-thumb {
    transition: none;
  }
}
.cauto-lbl {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-m);
  margin-bottom: 6px;
}
.cauto-hours-row {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}
.cauto-h {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  color: var(--text-m);
}
.cauto-h input {
  width: 90px;
  padding: 10px 12px;
  border: 1.5px solid var(--brd);
  border-radius: 10px;
  font-family: var(--sans);
  font-size: 16px; /* ≥16px: no iOS focus-zoom */
  background: var(--wh);
  color: var(--text);
  outline: none;
}
.cauto-h input:focus {
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.cauto-hint {
  display: block;
  font-size: 11.5px;
  color: var(--text-m);
  margin-top: 6px;
}
.cauto-field {
  display: block;
}
.cauto-field textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1.5px solid var(--brd);
  border-radius: 10px;
  font-family: var(--sans);
  font-size: 16px; /* ≥16px */
  line-height: 1.5;
  background: var(--wh);
  color: var(--text);
  outline: none;
  resize: vertical;
}
.cauto-field textarea:focus {
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.cauto-save {
  justify-self: start;
  min-height: 44px;
}
.cauto-rules-hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.cauto-rules-title {
  margin: 0;
  font-size: 16px;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.cauto-rules {
  display: grid;
  gap: 12px;
}
.cauto-rule {
  background: var(--wh);
  border: 1px solid var(--brd-l);
  border-radius: 14px;
  padding: 14px 16px;
}
.cauto-rule-kw {
  font-family: monospace;
  font-size: 12.5px;
  color: var(--olive);
  background: rgba(74, 93, 35, 0.08);
  padding: 4px 8px;
  border-radius: 6px;
  display: inline-block;
  margin-bottom: 8px;
  word-break: break-word;
}
.cauto-rule-ans {
  font-size: 13.5px;
  color: var(--text);
  line-height: 1.5;
}
.cauto-rule-acts {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}
.cauto-rule-acts .snip-btn {
  min-height: 40px;
  padding: 8px 16px;
}
/* FAQ rule modal reuses .snip-field; bump its inputs to ≥16px so iOS
   Safari doesn't auto-zoom on focus (the shared .snip-field rule is
   13px). Scoped to this modal only — the snippets modal is untouched. */
#faqRuleModal .snip-field input,
#faqRuleModal .snip-field textarea {
  font-size: 16px;
}

/* ─── Plan 3 / C5 — Saved Messages notepad ───────────────────── */
.chat-item-notepad {
  background: linear-gradient(
    180deg,
    rgba(202, 168, 74, 0.06),
    rgba(202, 168, 74, 0)
  );
}
.chat-pin-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  background: #caa84a;
  color: #fff;
  font-size: 9.5px;
  border-radius: 4px;
  font-weight: 700;
  letter-spacing: 0.3px;
  vertical-align: middle;
}
.notepad-actions {
  display: none;
  align-items: center;
  gap: 12px;
  padding: 10px 18px;
  background: rgba(202, 168, 74, 0.12);
  border-top: 1px solid var(--brd-l);
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text);
}
.notepad-actions.show {
  display: flex;
}
.notepad-fwd-btn {
  margin-left: auto;
  padding: 8px 16px;
  border-radius: 100px;
  background: var(--olive);
  color: #fff;
  border: none;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 12.5px;
  cursor: pointer;
}
.notepad-cancel-btn {
  padding: 8px 14px;
  background: transparent;
  border: 1px solid var(--brd);
  border-radius: 100px;
  font-family: var(--sans);
  font-size: 12.5px;
  cursor: pointer;
}
.notepad-msg.is-selected {
  outline: 3px solid #caa84a;
  outline-offset: 2px;
}
.notepad-check {
  margin-right: 8px;
  vertical-align: middle;
}
.notepad-del {
  background: none;
  border: none;
  color: var(--text-m);
  font-size: 16px;
  cursor: pointer;
  margin-left: 6px;
  line-height: 1;
}
.notepad-del:hover {
  color: #c92a2a;
}
.notepad-forward {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}
.notepad-forward[hidden] {
  display: none;
}
.notepad-fwd-card {
  background: var(--wh);
  border-radius: 16px;
  width: 100%;
  max-width: 420px;
  max-height: 80vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
}
.notepad-fwd-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--brd-l);
}
.notepad-fwd-header h3 {
  margin: 0;
  font-size: 15px;
}
.notepad-fwd-close {
  background: none;
  border: none;
  font-size: 22px;
  cursor: pointer;
  color: var(--text-m);
  line-height: 1;
}
.notepad-fwd-list {
  overflow-y: auto;
  padding: 8px 0;
}
.notepad-fwd-row {
  display: block;
  width: 100%;
  padding: 12px 20px;
  border: none;
  background: transparent;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  border-bottom: 1px solid var(--brd-l);
}
.notepad-fwd-row:last-child {
  border-bottom: none;
}
.notepad-fwd-row:hover {
  background: var(--cream);
}

/* ─── Plan 3 / C1 — In-chat search + global admin search ───────── */
.chat-search-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 15px;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.chat-search-btn:hover {
  background: var(--cream);
}
.chat-search-bar {
  display: none;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--brd-l);
  background: var(--cream);
  font-family: var(--sans);
}
.chat-search-bar.show {
  display: flex;
}
.chat-search-bar input {
  flex: 1;
  /* Phase E — match the composer input fix; allow shrinking below
     content min-width so the prev/next/close buttons stay visible
     on narrow viewports. */
  min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--brd);
  border-radius: 8px;
  font-size: 13px;
  background: var(--wh);
  outline: none;
}
.chat-search-bar input:focus {
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.chat-search-counter {
  font-size: 11.5px;
  color: var(--text-m);
  min-width: 50px;
  text-align: center;
}
.chat-search-bar button {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  border: 1px solid var(--brd);
  background: var(--wh);
  font-size: 11px;
  cursor: pointer;
  color: var(--text);
}
.chat-search-bar button:hover {
  background: var(--cream);
}
.chat-hl {
  background: #ffe66d;
  color: var(--text);
  padding: 0 1px;
  border-radius: 2px;
}
.chat-msg.is-search-active {
  outline: 2px solid #ffb800;
  outline-offset: 2px;
  background-color: rgba(255, 230, 109, 0.18) !important;
  transition: background-color 0.3s ease;
}
.chat-global-search {
  margin-bottom: 14px;
}
.chat-global-search input {
  width: 100%;
  padding: 10px 14px;
  border: 1.5px solid var(--brd);
  border-radius: 100px;
  font-size: 13px;
  font-family: var(--sans);
  background: var(--wh);
  outline: none;
}
.chat-global-search input:focus {
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.1);
}
.chat-gres-wrap {
  margin-bottom: 20px;
}
.chat-gres-load,
.chat-gres-empty {
  padding: 14px;
  color: var(--text-m);
  text-align: center;
  font-size: 12.5px;
}
.chat-gres-chat {
  background: var(--wh);
  border: 1px solid var(--brd-l);
  border-radius: 12px;
  padding: 12px 16px;
  margin-bottom: 10px;
  font-family: var(--sans);
}
.chat-gres-head {
  font-size: 13px;
  margin-bottom: 8px;
  color: var(--text);
}
.chat-gres-hit {
  font-size: 12px;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s ease;
}
.chat-gres-hit:hover {
  background: var(--cream);
}
.chat-gres-hit-snippet {
  color: var(--text);
  line-height: 1.4;
}
.chat-gres-hit-meta {
  color: var(--text-m);
  font-size: 10.5px;
  margin-top: 2px;
}

/* ──────────────────────────────────────────────────────────────────
   Phase B/4 — Sticky-hover suppression on touch devices.

   On touch screens, `:hover` styles latch after a tap and stay "on"
   until another element is tapped. For COLOR/SHADOW changes that's
   harmless and provides a useful tap-feedback. But for `transform`
   changes (translateY/scale/translateX) the visual SHIFT survives
   after the user releases — a room card stays lifted, the heart
   button stays scaled, the chat-item stays slid 3px to the right.

   Wrapping every existing rule in (hover: hover) would be ~50 edits
   spread across 12k lines and risks regressions. Instead, this single
   override fires only on (hover: none) — fine-pointer desktops are
   untouched — and neutralizes the transform on the known sticky-
   hover surfaces. Color/box-shadow hover effects on these same
   elements are intentionally left alone (they self-clear on tap-out).
   ────────────────────────────────────────────────────────────────── */
@media (hover: none) and (pointer: coarse) {
  .ncta:hover,
  .btt:hover,
  .rc:hover,
  .rc-fav:hover,
  .attr-card:hover,
  .svc-card:hover,
  .rev-card:hover,
  .cta-btn:hover,
  .island-feat:hover,
  .island-cta-btn:hover,
  .ft-social:hover,
  .chat-item:hover,
  .chat-input-bar button:hover,
  .chat-notif-btn:hover,
  .chat-item-featured:hover,
  .pmi:hover,
  .sticky-book-btn:hover,
  .lb-close:hover,
  .lb-nav:hover,
  .lb-nav.prev:hover,
  .lb-nav.next:hover,
  .map-btn:hover {
    transform: none;
  }
}

/* ──────────────────────────────────────────────────────────────────
   Phase B/4 — Mobile minimum touch targets (WCAG 2.5.5 — 44x44 CSS
   pixels). The audit flagged several interactive surfaces below the
   threshold which makes them frustrating to tap on small screens.
   Scoped to (max-width: 768px) so the desktop pixel layout is
   unchanged.
   ────────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .bk-ctr button,
  .chat-input-bar button,
  .chat-snip-btn,
  .chat-note-btn,
  .rc-fav,
  .mtog,
  .xb,
  .chat-header .ch-back {
    min-width: 44px;
    min-height: 44px;
  }
}

/* ──────────────────────────────────────────────────────────────────
   Phase B/6 — Global :focus-visible ring for keyboard a11y. Pre-fix,
   users tabbing through the UI had no visible indicator of which
   element had focus, failing WCAG 2.4.7. Using :focus-visible (not
   :focus) so mouse clicks don't draw a ring on every button.
   ────────────────────────────────────────────────────────────────── */
*:focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 2px;
  border-radius: 6px;
}
/* Don't double-ring elements that already define a custom indicator. */
.nl:focus-visible {
  outline: none;
}

/* Phase C/2 - Skip to main content link (a11y) */
.kw-skip-link {
  position: fixed;
  top: -100px;
  left: 8px;
  background: var(--olive);
  color: #fff;
  padding: 10px 14px;
  border-radius: 8px;
  text-decoration: none;
  font-weight: 600;
  z-index: 99999;
  transition: top 0.15s;
}
.kw-skip-link:focus-visible {
  top: 8px;
}

/* ════════════════════════════════════════════════════════════════════
   MOTION SYSTEM v3 — Progressive enhancement + auth-state-safe.
   (CLAUDE_CODE_ANIMATION_FIX_AND_UPLIFT.md fix.)

   THE BUG (pre-fix):
   - .reveal { opacity: 0 } at styles.css:1715 made content invisible by
     default. The .reveal.vis rule revealed it, but the JS observers ran
     only once at module load. On auth-state-driven re-renders (sign in /
     sign out), new .reveal nodes were created with opacity:0 and only the
     async MutationObserver+IntersectionObserver chain could un-hide them.
     Race conditions left content stuck invisible.

   THE FIX (this block):
   - .reveal is VISIBLE by default. Pure-CSS load = content visible.
   - The body.kw-motion-ready class (set by initMotion in script.js)
     gates the "hide first then animate in" behavior. If JS never runs,
     content stays visible.
   - body.kw-reduce-motion class (set by initMotion when the OS prefers
     reduced motion) overrides everything to instant visibility.
   - Selectors use :not(.is-in):not(.vis) so they automatically yield to
     the existing reveal-state rules (.reveal.is-in at line 80 and
     .reveal.vis at line 1722) — fully backward compatible.

   Source-order placement at EOF ensures this block has cascade priority
   over the legacy .reveal rules without removing them (live-site safety).
   ════════════════════════════════════════════════════════════════════ */

/* PE default: .reveal is VISIBLE — no JS required. */
.reveal {
  opacity: 1;
  transform: none;
  transition:
    opacity 520ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 520ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* JS has marked the page motion-ready. Hide un-revealed reveals. */
body.kw-motion-ready .reveal:not(.is-in):not(.vis) {
  opacity: 0;
  transform: translateY(24px);
}
body.kw-motion-ready .reveal.reveal-left:not(.is-in):not(.vis) {
  transform: translateX(-24px);
}
body.kw-motion-ready .reveal.reveal-right:not(.is-in):not(.vis) {
  transform: translateX(24px);
}
body.kw-motion-ready .reveal.reveal-scale:not(.is-in):not(.vis) {
  transform: scale(0.96);
}

/* Reduced motion: hard-override every motion path to instant. */
body.kw-reduce-motion .reveal,
body.kw-reduce-motion .reveal.is-in,
body.kw-reduce-motion .reveal.vis,
body.kw-reduce-motion .hero-fx,
body.kw-reduce-motion .hero-fx.is-visible,
body.kw-reduce-motion .hero-fx-h1 .hero-line,
body.kw-reduce-motion .hero-fx-h1 .hero-line.is-visible,
body.kw-reduce-motion [data-hero-art],
body.kw-reduce-motion [data-hero-art].is-visible {
  opacity: 1 !important;
  transform: none !important;
  clip-path: none !important;
  transition: none !important;
  animation: none !important;
}

/* ── Hero "island escape" accent ────────────────────────────────────
   ONE tasteful, one-time gold underline draw-in. Not a loop. Fires
   after the headline line settles, then stays settled. Reduced-motion
   gets the final state instantly. */
.kw-hero-accent {
  position: relative;
  white-space: nowrap;
  /* Inherit italic + olive from the existing <em> styles — don't fight them. */
}
.kw-hero-accent::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.06em;
  height: 0.1em;
  background: linear-gradient(
    90deg,
    var(--gold, #c8a951) 0%,
    rgba(200, 169, 81, 0.45) 100%
  );
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1) 1.4s;
  pointer-events: none;
}
/* The headline line carries .hero-line.is-visible once the hero anim
   fires. Trigger the underline off that signal so it always lands
   AFTER the line settles. */
body.kw-motion-ready .hero-fx-h1 .hero-line.is-visible .kw-hero-accent::after {
  transform: scaleX(1);
}
body.kw-reduce-motion .kw-hero-accent::after {
  transform: scaleX(1);
  transition: none;
}

/* ── View Transitions API — auth-state crossfade ───────────────────
   Feature-detected in JS (kwSwapView). When supported, gives a
   tasteful 420ms crossfade for sign-in / sign-out instead of a hard
   DOM swap. When unsupported, JS falls back to instant. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.42s;
  animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}
::view-transition-old(root) {
  animation-name: kwViewFadeOut;
}
::view-transition-new(root) {
  animation-name: kwViewFadeIn;
}
@keyframes kwViewFadeOut {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-6px);
  }
}
@keyframes kwViewFadeIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none !important;
  }
}

/* ── Premium CTA micro-interaction — subtle lift, never bouncy. ────
   Targets the brand CTAs (Browse Rooms, Sign In, Confirm Booking).
   Reduced-motion-safe via media query. */
@media (prefers-reduced-motion: no-preference) {
  .ncta,
  .auth-submit {
    transition:
      transform 180ms cubic-bezier(0.22, 1, 0.36, 1),
      box-shadow 180ms cubic-bezier(0.22, 1, 0.36, 1),
      background 180ms ease;
  }
  .ncta:hover,
  .auth-submit:hover:not([disabled]) {
    transform: translateY(-2px);
    box-shadow: 0 10px 24px -10px rgba(74, 93, 35, 0.4);
  }
  .ncta:active,
  .auth-submit:active:not([disabled]) {
    transform: translateY(0);
    transition-duration: 100ms;
  }
  /* Outline CTA — same lift, no shadow. */
  .det-back:not(.adm-back):not([disabled]):hover {
    transform: translateY(-1px);
    transition: transform 160ms cubic-bezier(0.22, 1, 0.36, 1);
  }
}

/* ════════════════════════════════════════════════════════════════════
   HERO REVEAL v3 — visible-by-default, motion is pure enhancement.
   (HERO_REDESIGN_PROMPT.md §7c — the reliability-safe reveal pattern.)

   The old v2 system hid `.hero [data-reveal]` at parse time under
   `html.js` and bet that JS would reveal it (with a 1500ms failsafe
   keyframe bolted on because that bet kept losing). v3 inverts this:

   - `[data-reveal]` elements are ALWAYS visible in CSS (opacity:1).
     There is no hidden-by-default state and therefore no way to strand
     content invisible — no JS, no failsafe keyframe, nothing to fail into.
   - The staggered entrance is driven entirely by the Web Animations API
     in initHeroMotion() (script.js). element.animate() with
     `fill: "backwards"` paints the hidden start-state ONLY while its own
     animation is pending/running, then releases the element back to this
     visible CSS base. If JS throws mid-run, every element still resolves
     to visible. If JS never runs, the CSS base is already visible.
   - Reduced-motion: initHeroMotion() skips animating; the static visible
     base below is the result. (The hero block above also hard-disables
     ambient motion under the reduced-motion media query.)
   ════════════════════════════════════════════════════════════════════ */
.hero [data-reveal] {
  opacity: 1;
  transform: none;
}

/* Belt-and-suspenders: even under reduced motion, force the visible base
   (initHeroMotion already no-ops, but this guarantees it in CSS too). */
@media (prefers-reduced-motion: reduce) {
  .hero [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ════════════════════════════════════════════════════════════════════
   MOBILE MENU v2 — Premium, on-brand, with CTA + items + divider.
   (P1 fix companion CSS.)
   ════════════════════════════════════════════════════════════════════ */
.mnav {
  display: flex;
  flex-direction: column;
}
.mnav-inner {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 64px 24px 32px;
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
}
.mnav-cta {
  width: 100%;
  padding: 14px 24px;
  background: var(--olive, #4a5d23);
  color: #fff;
  border: 0;
  border-radius: 12px;
  font-family: var(--sans, "Outfit", sans-serif);
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  letter-spacing: 0.2px;
  box-shadow: 0 10px 24px -8px rgba(74, 93, 35, 0.35);
  transition:
    transform 180ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 180ms cubic-bezier(0.22, 1, 0.36, 1);
}
.mnav-cta:active {
  transform: scale(0.98);
}
.mnav-div {
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(74, 93, 35, 0.18) 50%,
    transparent 100%
  );
  margin: 4px 0;
}
.mnav-items {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mnav-item {
  width: 100%;
  padding: 14px 18px;
  background: transparent;
  color: var(--text-d, #1f2a1a);
  border: 0;
  border-radius: 10px;
  font-family: var(--sans, "Outfit", sans-serif);
  font-size: 16px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  transition: background 160ms ease;
}
.mnav-item:hover {
  background: rgba(74, 93, 35, 0.06);
}
.mnav-item:focus-visible {
  background: rgba(74, 93, 35, 0.06);
  outline: 2px solid var(--olive, #4a5d23);
  outline-offset: -2px;
}
.mnav-item.act {
  background: rgba(74, 93, 35, 0.1);
  color: var(--olive, #4a5d23);
  font-weight: 600;
}
.mnav-item .nbadge {
  background: var(--olive, #4a5d23);
  color: #fff;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 100px;
  font-weight: 700;
  line-height: 1.4;
}
.mnav-item .nbadge-unread {
  background: var(--gold, #c8a951);
  color: #3a2f00;
}

/* Staggered entry — mnav-items children fade up in sequence. */
@media (prefers-reduced-motion: no-preference) {
  .mnav .mnav-cta {
    animation: mnavSlideUp 360ms cubic-bezier(0.22, 1, 0.36, 1) both;
  }
  .mnav .mnav-item {
    opacity: 0;
    transform: translateY(8px);
    animation: mnavSlideUp 360ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
  }
  .mnav .mnav-item:nth-child(1) {
    animation-delay: 80ms;
  }
  .mnav .mnav-item:nth-child(2) {
    animation-delay: 130ms;
  }
  .mnav .mnav-item:nth-child(3) {
    animation-delay: 180ms;
  }
  .mnav .mnav-item:nth-child(4) {
    animation-delay: 230ms;
  }
  .mnav .mnav-item:nth-child(5) {
    animation-delay: 280ms;
  }
  .mnav .mnav-item:nth-child(6) {
    animation-delay: 330ms;
  }
}
@keyframes mnavSlideUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* === fix-pass 2026-05-27 — cancel-trip + forgot-password === */
:root {
  --danger: #b91c1c;
  --danger-soft: #fee2e2;
  --danger-border: #fca5a5;
}
.tkt-cancel-btn {
  background: none;
  border: 1px solid var(--danger-border);
  color: var(--danger);
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  line-height: 1.2;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.tkt-cancel-btn:hover,
.tkt-cancel-btn:focus-visible {
  background: var(--danger-soft);
  border-color: var(--danger);
  outline: none;
}
.tkt-cancel-btn:focus-visible {
  box-shadow: 0 0 0 3px rgba(185, 28, 28, 0.22);
}
.auth-forgot {
  margin-top: 10px;
  text-align: right;
}
.kw-auth-link {
  background: none;
  border: 0;
  padding: 4px 2px;
  font: inherit;
  color: var(--olive, #4a5d23);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  border-radius: 4px;
}
.kw-auth-link:hover,
.kw-auth-link:focus-visible {
  color: #2e3c14;
  outline: none;
}
.kw-auth-link:focus-visible {
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.25);
}

/* === avatar fallback 2026-05-28 === */
.p-av,
.ep-avatar,
.adm-user-avatar {
  position: relative;
}
.kw-av-img-wrap {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
  z-index: 1;
}
.kw-av-img-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.p-av-letter {
  position: relative;
  z-index: 0;
}
.p-av-badge,
.ep-avatar .ep-badge,
.adm-user-avatar .adm-badge {
  z-index: 2;
}

/* === chat-av fallback 2026-05-28 === */
.chat-av-initial { position: relative; }

/* ════════════════════════════════════════════════════════════════════
   GOLDEN HOUR — WAVE 1B · Aurora wash   (spec §4 Wave 1B, 2026-06-01)

   WHAT: a slow, low-opacity "aurora" of golden-hour light behind TWO
   sections only — Guest Reviews (#reviews) and the Island CTA card
   (.island-cta). Sand / seafoam / dusk-gold radial blobs that breathe and
   drift over ~22-26s. Decorative atmosphere, not a feature.

   WHY pure CSS (no JS): Wave 1A's sun is scroll-DRIVEN (a value per frame)
   so it lives in the rAF loop. This wash is AMBIENT — it loops on its own
   clock — so a CSS @keyframes runs 100% on the compositor with zero
   main-thread cost. Cheapest possible always-on motion.

   GPU-only (spec: "transform/opacity, compositor-only"): the radial
   gradients are painted ONCE into the layer; the animation moves only
   `transform` + `opacity` (both compositor properties). No layout, no
   per-frame repaint.

   AA BY CONSTRUCTION (spec: "never drops text below AA on the booking
   band"): each wash is a separate layer pinned BELOW content (aurora
   z-index 0 vs content z-index 1/2). Text never composites through the
   glow — the section's own background decides contrast. Verified
   empirically at the BRIGHTEST animation frame, not at rest.

   CTA = GATED WHISPER (4-voice council, 2026-06-01): the Island CTA is
   already a 5-layer motion stack (glow + shimmer + 2 waves + 2 trees), so
   its wash is deliberately faint, CORNER-BIASED away from the bottom-centre
   .island-cta-note line, and runs slower + reversed (26s) so it never syncs
   with the existing 4s glow — depth, not a second strobe. (The note's own
   rgba(255,255,255,.45) contrast is a PRE-EXISTING condition, out of Wave-1B
   scope; this layer is positioned not to lift luminance under it.)

   REDUCED MOTION: animation off, pinned to a gentle static rest frame
   (mirrors the hero-block convention), will-change released.
   ════════════════════════════════════════════════════════════════════ */

:root {
  /* Aurora palette as RGB triplets so each gradient sets its own alpha.
     Derived from locked brand + Palette-B tokens — NOT new accents:
       sand      ≈ Palette-B CTA stop #f0dcb6
       dusk-gold = --gold #c8a951 (the page's existing gold accent)
       seafoam   = a desaturated tropical green kept at low alpha so it
                   reads as coastal atmosphere, never a competing accent
                   (Color-Consistency-Lock safe). */
  --gh-sand: 240, 220, 182;
  --gh-dusk-gold: 200, 169, 81;
  --gh-seafoam: 150, 188, 166;
}

/* Two keyframes (one per surface) with HARD-CODED opacity. This was one shared
   @keyframes reading per-element var(--gh-o1/--gh-o2) — but custom properties
   inside @keyframes silently fall back on Safari < 15.4 (still a slice of PH
   iOS), which would animate the CTA whisper at the brighter fallback. Two
   keyframes remove that dependency. Transform animates translate + a tiny scale
   only — NO rotate (rotate forces a CPU re-raster of the gradient on layer
   promotion → first-scroll jank on cheap Android). Seamless loop (0%/100%
   identical); gentle opacity breath. The CTA drifts the OPPOSITE direction +
   slower so it never syncs with the card's existing 4s glow. */
@keyframes ghAuroraReviews {
  0%, 100% { transform: translate3d(-1.5%, -1%, 0) scale(1); opacity: 0.55; }
  50%      { transform: translate3d(2%, 1.5%, 0) scale(1.05); opacity: 0.78; }
}
@keyframes ghAuroraCta {
  0%, 100% { transform: translate3d(1.5%, 1%, 0) scale(1); opacity: 0.22; }
  50%      { transform: translate3d(-2%, -1.5%, 0) scale(1.05); opacity: 0.36; }
}

/* ── Reviews: light pale-olive section (#eef3e5) → warm sand rising from
   below, with a dusk-gold + seafoam whisper up top. The showcase surface. */
#reviews {
  position: relative;   /* containing block for the aurora layer */
  overflow: hidden;     /* crops the drifting layer. The carousel arrows
                           (.rev-nav) are display:none on mobile and sit inside
                           the section on desktop (ctn 48px pad), so this never
                           clips them. isolation:isolate removed — position +
                           the child z-index below already order the layer, and
                           isolate would trap any future fixed descendant. */
}
#reviews > .ctn {
  position: relative;
  z-index: 1;           /* all heading + carousel content above the wash */
}
#reviews::before {
  content: "";
  position: absolute;
  inset: -12%;          /* oversized so drift never reveals an edge; trimmed
                           from -20% to shrink the promoted GPU layer. Margin
                           (12%) > translate (2%) + scale growth (2.5%). */
  z-index: 0;           /* below content; above the section background */
  pointer-events: none;
  background:
    radial-gradient(38% 48% at 20% 28%, rgba(var(--gh-dusk-gold), 0.22), transparent 70%),
    radial-gradient(42% 52% at 82% 22%, rgba(var(--gh-seafoam), 0.16), transparent 72%),
    radial-gradient(52% 50% at 50% 92%, rgba(var(--gh-sand), 0.5), transparent 72%);
  /* symmetric bezier (not ease-in-out) avoids a loop-boundary frame drop on
     some budget Android Chromium builds. No will-change: the browser already
     promotes an actively-animating transform/opacity layer, so an eager
     always-on hint just wastes GPU memory before the section scrolls in. */
  animation: ghAuroraReviews 22s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

/* ── Island CTA: dark olive card, ALREADY richly decorated. The wash here is a
   faint whisper, CORNER-BIASED (top-left, top-right, bottom-left) so the
   bottom-centre note line is never lit from behind. z-index 0 keeps it below
   the shimmer (::after z1) and content (z2) → white text stays crisp (the
   ::before may paint above or below the existing .island-cta-bg glow depending
   on tree order — that's fine, both are faint and below all text). Seafoam is
   dialled to a near-zero whisper here: the page accent is olive+gold, and on
   this busy dark card the warm gold alone carries the golden-hour read
   (Color-Consistency-Lock). */
.island-cta::before {
  content: "";
  position: absolute;
  inset: -10%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(32% 40% at 16% 20%, rgba(var(--gh-dusk-gold), 0.34), transparent 68%),
    radial-gradient(34% 42% at 86% 16%, rgba(var(--gh-seafoam), 0.1), transparent 70%),
    radial-gradient(26% 30% at 12% 80%, rgba(var(--gh-sand), 0.26), transparent 70%);
  animation: ghAuroraCta 26s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

/* Reduced motion: no drift. Pin each wash to its own 0%-keyframe position (so a
   mid-session toggle doesn't snap) at the CALMEST opacity — at or below each
   animation's rest value, because reduced-motion should read quieter, not
   brighter. (The global catch-all at the top of this file also kills the
   animation; this is the explicit, intentional rest state.) */
@media (prefers-reduced-motion: reduce) {
  #reviews::before,
  .island-cta::before { animation: none !important; }
  #reviews::before { transform: translate3d(-1.5%, -1%, 0); opacity: 0.5; }
  .island-cta::before { transform: translate3d(1.5%, 1%, 0); opacity: 0.2; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Booking Confirmation generator (OWNER-ONLY) — editorial form + live
   canvas preview. Mobile-first: the form stacks ABOVE the preview on phones
   and sits side-by-side from 1024px. Inputs are >=16px (no iOS zoom on focus)
   and >=44px tall (touch targets); the Download bar is sticky + safe-area
   padded; all motion respects prefers-reduced-motion.
   ═══════════════════════════════════════════════════════════════════════ */
.cg-wrap { max-width: 1120px; margin: 0 auto; padding-bottom: 132px; }
.cg-lead {
  color: var(--text-m);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  max-width: 60ch;
  margin: 4px 0 22px;
}
.cg-stage { display: flex; flex-direction: column; gap: 26px; }

/* ── Form ── */
.cg-form { display: grid; grid-template-columns: 1fr; gap: 16px; align-content: start; }
.cg-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.cg-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
  border: 0;
  margin: 0;
  padding: 0;
}
.cg-field-pax { max-width: 130px; }
.cg-label {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-m);
  padding: 0;
}
.cg-input {
  font-family: var(--sans);
  font-size: 16px; /* >=16px: never trips iOS focus-zoom */
  line-height: 1.4;
  color: var(--text-d);
  background: #fff;
  border: 1px solid rgba(74, 93, 35, 0.22);
  border-radius: 12px;
  padding: 12px 14px;
  min-height: 48px; /* >=44px touch target */
  width: 100%;
  box-sizing: border-box;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.cg-input::placeholder { color: rgba(93, 99, 88, 0.6); }
.cg-input:focus-visible {
  outline: none;
  border-color: var(--olive);
  box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.16);
}
.cg-textarea { resize: vertical; min-height: 66px; line-height: 1.5; }
select.cg-input {
  padding-right: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%234a5d23' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
.cg-paystate { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 10px 12px; }
.cg-paystate .cg-label { width: 100%; }
.cg-radio {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--text-d);
  min-height: 44px;
  padding: 9px 18px;
  border: 1px solid rgba(74, 93, 35, 0.28);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  transition: background-color 180ms cubic-bezier(0.23, 1, 0.32, 1),
              color 180ms cubic-bezier(0.23, 1, 0.32, 1),
              border-color 180ms cubic-bezier(0.23, 1, 0.32, 1),
              box-shadow 180ms cubic-bezier(0.23, 1, 0.32, 1),
              transform 140ms cubic-bezier(0.23, 1, 0.32, 1);
}
@media (hover: hover) and (pointer: fine) {
  .cg-radio:hover { border-color: var(--olive); background: rgba(74, 93, 35, 0.06); }
}
.cg-radio:active { transform: scale(0.97); }
.cg-radio:has(input:checked) {
  background: var(--olive);
  border-color: var(--olive);
  color: var(--cream);
  font-weight: 600;
  box-shadow: 0 2px 10px -3px rgba(74, 93, 35, 0.5);
}
.cg-radio:has(input:focus-visible) { box-shadow: 0 0 0 3px rgba(74, 93, 35, 0.22); }
.cg-radio input { width: 20px; height: 20px; accent-color: var(--olive); }
@media (prefers-reduced-motion: reduce) {
  .cg-radio {
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
  }
  .cg-radio:active { transform: none; }
}

/* ── Live preview ── */
.cg-preview { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.cg-canvas-frame {
  width: 100%;
  max-width: 520px;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 18px 50px -22px rgba(31, 42, 26, 0.45), 0 2px 8px rgba(31, 42, 26, 0.08);
}
.cg-canvas { display: block; width: 100%; height: auto; background: var(--cream); }
.cg-preview-note {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-m);
  margin: 0;
}

/* ── Sticky download bar (safe-area aware; no full-bleed → no h-overflow) ── */
.cg-actionbar {
  position: sticky;
  bottom: 0;
  z-index: 20;
  display: flex;
  justify-content: center;
  margin-top: 22px;
  padding: 14px 0 calc(14px + env(safe-area-inset-bottom));
  background: linear-gradient(to top, var(--cream) 64%, rgba(250, 249, 246, 0));
}
.cg-download {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--cream);
  background: var(--olive);
  border: 0;
  border-radius: 999px;
  padding: 15px 40px;
  min-height: 52px;
  width: 100%;
  max-width: 420px;
  cursor: pointer;
  box-shadow: 0 10px 26px -10px rgba(74, 93, 35, 0.6);
  transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), background-color 160ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .cg-download:hover { background: #3c4d1c; }
}
.cg-download:active { transform: scale(0.97); }
.cg-download:focus-visible { outline: 3px solid var(--olive); outline-offset: 3px; }

/* ── Load-existing-booking: select + explicit Load button (a bare onchange
   select changes context on arrow-key traversal — WCAG 3.2.2). ── */
.cg-loadrow { display: flex; gap: 10px; align-items: stretch; }
.cg-loadrow .cg-input { flex: 1 1 auto; min-width: 0; }
.cg-load-btn {
  flex: 0 0 auto;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--olive);
  background: rgba(74, 93, 35, 0.08);
  border: 1px solid rgba(74, 93, 35, 0.3);
  border-radius: 12px;
  padding: 0 20px;
  min-height: 48px;
  cursor: pointer;
  transition: background-color 160ms ease, transform 160ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .cg-load-btn:hover { background: rgba(74, 93, 35, 0.14); }
}
.cg-load-btn:active { transform: scale(0.97); }
.cg-load-btn:focus-visible { outline: 3px solid var(--olive); outline-offset: 2px; }

/* ── Visually-hidden live region for the payment-state announcement ── */
.cg-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── Desktop: form + sticky preview side-by-side ── */
@media (min-width: 1024px) {
  .cg-stage { flex-direction: row; align-items: flex-start; gap: 40px; }
  .cg-form { flex: 1 1 0; max-width: 460px; }
  .cg-preview { flex: 1 1 0; position: sticky; top: 92px; }
  .cg-actionbar {
    position: static;
    justify-content: flex-start;
    margin-top: 24px;
    padding: 0;
    background: none;
  }
  .cg-download { width: auto; }
  .cg-wrap { padding-bottom: 60px; }
}

/* ── Small phones: collapse paired rows so date/number fields breathe ── */
@media (max-width: 380px) {
  .cg-row { grid-template-columns: 1fr; }
  .cg-field-pax { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cg-input, .cg-download, .cg-load-btn { transition: none; }
  .cg-download:active, .cg-load-btn:active { transform: none; }
}

