/* ╔══════════════════════════════════════════════════════════════════════════╗
   ║  JAS Cleaning — ANIMATION + INTERACTION LAYER                           ║
   ║                                                                          ║
   ║  Purely additive on top of styles.css + site.css. No color or           ║
   ║  component identity changes. Adds motion, glass surfaces, scroll        ║
   ║  reveals, bilingual i18n CSS, and shared interactive components         ║
   ║  injected by animations.js.                                              ║
   ║                                                                          ║
   ║  LOADED BY: every HTML page                                              ║
   ║  PAIRS WITH: animations.js (which actually runs the motion)             ║
   ║                                                                          ║
   ║  Honors:                                                                 ║
   ║    • Design System §9 — 160ms baseline, cubic-bezier(0.2, 0, 0, 1)     ║
   ║    • prefers-reduced-motion — kills animations + scroll progress       ║
   ║                                                                          ║
   ║  ══════════════════════════════════════════════════════════════════════ ║
   ║   §1.  Easing + timing tokens   — --ease-out, --t-fast, --t-base       ║
   ║   §2.  Lenis smooth-scroll      — html.lenis resets                    ║
   ║   §3.  Sticky-nav scrolled      — frosted-blur state                   ║
   ║   §4.  Button + card hover      — micro-lift on .btn, .svc, .review    ║
   ║   §5.  Field focus              — leaf glow                            ║
   ║   §6.  Booking-wizard hover     — tile/addon/cleaner gentle scale      ║
   ║   §7.  FAQ details              — summary marker rotation              ║
   ║   §8.  Float CTA bob            — gentle attention animation           ║
   ║   §9.  Modal + toast            — backdrop-blur + slide-in             ║
   ║  §10. Anchor offset             — :target scroll-margin-top            ║
   ║  §11. Glassmorphism             — targeted glass surfaces (nav,        ║
   ║       float CTA, modals, slider handle, toast, booking summary,        ║
   ║       hero proof card + quote card)                                     ║
   ║  §12. Motion helpers            — .mask-line, .mask-inner (split text  ║
   ║       reveals), .scroll-progress, .magnetic CTAs, .eb-tracking         ║
   ║  §13. JESKO #1: clip-path reveals — photos wipe in                     ║
   ║  §14. JESKO #2: trust marquee   — dark ticker before footer            ║
   ║  §15. JESKO #3: eyebrow dot     — leaf dot scales in                   ║
   ║  §16. JESKO #4: pinned steps    — (currently unused; kept for revival) ║
   ║  §17. i18n dual-element         — <select>, <textarea> sibling swap    ║
   ║  §18. i18n .lang-block          — dual-language headlines under split  ║
   ║       (mask reveals need block-level lang containers)                  ║
   ║  §19. Cookie consent            — bottom-fixed glass-dark banner       ║
   ║  §20. Print media               — CleanCheck Report PDF layout         ║
   ║  §21. Reduced-motion overrides  — disable transforms + animations      ║
   ╚══════════════════════════════════════════════════════════════════════════╝ */

/* JAS Cleaning — Animation support layer
   Purely additive. No color or component changes.
   Honors the design system: 160ms baseline, cubic-bezier(0.2, 0, 0, 1). */

:root {
  --ease-out: cubic-bezier(0.2, 0, 0, 1);
  --ease-in: cubic-bezier(0.6, 0, 0.85, 0.5);
  --t-fast: 160ms;
  --t-base: 240ms;
  --t-slow: 420ms;
}

/* Lenis smooth-scroll resets (needed when Lenis is active) */
html.lenis,
html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-scrolling iframe { pointer-events: none; }

/* ────────────────────────────────────────────────────────────
   ACCESSIBILITY — keyboard focus + screen reader helpers.
   The design system removes default outlines on .btn (for clean
   visuals); we restore a high-contrast leaf ring on :focus-visible
   so keyboard users get a clear focus indicator.
   ──────────────────────────────────────────────────────────── */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--leaf);
  outline-offset: 3px;
  border-radius: 4px;
}
.btn:focus-visible,
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--leaf);
  outline-offset: 3px;
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.field:focus-within {
  outline: 2px solid var(--leaf);
  outline-offset: 1px;
}

/* Visually hide but keep available for screen readers */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip-to-content link (mounted by JS at top of each page) */
.skip-link {
  position: absolute;
  top: -100px;
  left: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 12px 18px;
  font-size: 13px;
  font-family: var(--mono);
  letter-spacing: 0.08em;
  text-decoration: none;
  z-index: 9999;
  transition: top 160ms cubic-bezier(0.2,0,0,1);
}
.skip-link:focus {
  top: 0;
  outline: 2px solid var(--leaf);
  outline-offset: -4px;
}

/* Native <details> open state — show pointer + improved hover */
details summary { user-select: none; }
details summary:focus-visible { outline-offset: 4px; }

/* Sticky-nav scrolled state — adds shadow when page has scrolled past 20px */
nav.bar {
  transition: box-shadow var(--t-base) var(--ease-out),
              border-color var(--t-base) var(--ease-out),
              backdrop-filter var(--t-base) var(--ease-out);
  will-change: box-shadow;
}
nav.bar.scrolled {
  box-shadow: 0 1px 0 var(--line), 0 12px 28px -20px rgba(26, 30, 27, 0.18);
  border-bottom-color: var(--line);
  backdrop-filter: saturate(140%) blur(6px);
  background: rgba(244, 239, 230, 0.92);
}

/* Buttons: subtle lift on hover (design system says 160ms) */
.btn {
  transition: transform var(--t-fast) var(--ease-out),
              background-color var(--t-fast) ease,
              border-color var(--t-fast) ease,
              color var(--t-fast) ease,
              box-shadow var(--t-base) var(--ease-out);
  will-change: transform;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn-leaf:hover { box-shadow: 0 8px 20px -10px rgba(46, 107, 58, 0.55); }
.btn-primary:hover { box-shadow: 0 8px 20px -10px rgba(26, 30, 27, 0.45); }

/* Service / package cards — gentle lift, design system says no shadow normally */
.svc {
  transition: border-color var(--t-fast) ease,
              transform var(--t-base) var(--ease-out),
              box-shadow var(--t-base) var(--ease-out);
}
.svc:hover {
  transform: translateY(-3px);
  box-shadow: 0 18px 36px -22px rgba(26, 30, 27, 0.20);
}

/* Review cards */
.review {
  transition: border-color var(--t-fast) ease,
              transform var(--t-base) var(--ease-out);
}
.review:hover { transform: translateY(-2px); border-color: var(--line-2); }

/* Pill hover (subtle) */
.pill {
  transition: transform var(--t-fast) var(--ease-out),
              background-color var(--t-fast) ease;
}

/* Fields — focus glow */
.field,
input.field,
select.field,
textarea.field,
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="number"],
select,
textarea {
  transition: border-color var(--t-fast) ease,
              box-shadow var(--t-fast) var(--ease-out),
              background-color var(--t-fast) ease;
}
.field:focus-within,
input.field:focus,
select.field:focus,
textarea.field:focus,
input[type="text"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus,
input[type="number"]:focus,
select:focus,
textarea:focus {
  box-shadow: 0 0 0 4px rgba(46, 107, 58, 0.12);
}

/* Booking-flow tiles, addons, cleaners — gentle scale on hover */
.tile,
.addon,
.cleaner,
.slot,
.cal-day,
.tip-row button {
  transition: transform var(--t-fast) var(--ease-out),
              border-color var(--t-fast) ease,
              background-color var(--t-fast) ease,
              box-shadow var(--t-fast) ease;
}
.tile:hover,
.addon:hover,
.cleaner:hover,
.slot:hover { transform: translateY(-1px); }

/* FAQ details — smoother summary marker */
details summary { transition: color var(--t-fast) ease; }
details summary::-webkit-details-marker { display: none; }
details[open] summary { color: var(--leaf); }

/* Float CTA gentle attention bob — paused on hover */
@keyframes jas-float-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}
.float-cta {
  animation: jas-float-bob 3.2s ease-in-out infinite;
  will-change: transform;
}
.float-cta:hover { animation-play-state: paused; }

/* CleanCheck slider handle pulse */
@keyframes jas-handle-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(244, 239, 230, 0.0), var(--sh-2); }
  50% { box-shadow: 0 0 0 8px rgba(244, 239, 230, 0.0), var(--sh-2); }
}

/* Toast — already styled in clean-checklist; keep transition */
.toast { transition: opacity var(--t-base) ease, transform var(--t-base) var(--ease-out); }

/* Modal — already styled, just smoother in */
.modal-bg {
  transition: opacity var(--t-base) ease;
  opacity: 0;
}
.modal-bg.show { opacity: 1; }
.modal {
  transform: translateY(8px);
  transition: transform var(--t-base) var(--ease-out);
}
.modal-bg.show .modal { transform: translateY(0); }

/* In-page anchor offset so the sticky nav doesn't cover headings */
:target { scroll-margin-top: 96px; }

/* ────────────────────────────────────────────────────────────
   I18N — dual-span pattern (no JS dictionary, just CSS)
   <span lang="en">…</span><span lang="es">…</span>
   Default (no body class) shows EN, hides ES.
   body.lang-es flips it.
   ──────────────────────────────────────────────────────────── */
span[lang="en"], em[lang="en"], b[lang="en"] { display: inline; }
span[lang="es"], em[lang="es"], b[lang="es"] { display: none; }
body.lang-es span[lang="en"],
body.lang-es em[lang="en"],
body.lang-es b[lang="en"] { display: none; }
body.lang-es span[lang="es"],
body.lang-es em[lang="es"],
body.lang-es b[lang="es"] { display: inline; }

/* Block-level dual-element pattern (for <select>, <textarea>, etc.
   where dual-spans inside don't work — render as siblings instead). */
select[lang="es"], textarea[lang="es"] { display: none; }
body.lang-es select[lang="en"], body.lang-es textarea[lang="en"] { display: none; }
body.lang-es select[lang="es"] { display: flex; }
body.lang-es textarea[lang="es"] { display: block; }

/* ────────────────────────────────────────────────────────────
   Cookie consent banner — injected by animations.js if no
   prior choice in localStorage. Bottom-fixed, dismissible.
   ──────────────────────────────────────────────────────────── */
.jas-cookie {
  position: fixed;
  bottom: 20px;
  left: 20px;
  right: 20px;
  z-index: 800;
  max-width: 640px;
  margin: 0 auto;
  background: rgba(26, 30, 27, 0.92);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  color: var(--paper);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--r-lg);
  padding: 18px 22px;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 18px;
  align-items: center;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.4);
  transform: translateY(20px);
  opacity: 0;
  transition: transform var(--t-slow) var(--ease-out), opacity var(--t-slow) var(--ease-out);
}
.jas-cookie.in {
  transform: translateY(0);
  opacity: 1;
}
.jas-cookie .copy {
  font-size: 13px;
  line-height: 1.55;
}
.jas-cookie .copy b { color: var(--paper); }
.jas-cookie .copy a {
  color: var(--leaf-soft);
  text-decoration: none;
  border-bottom: 1px dashed rgba(217, 229, 199, 0.4);
  padding-bottom: 1px;
}
.jas-cookie .actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}
.jas-cookie .btn-sm {
  height: 36px;
  font-size: 13px;
  padding: 0 14px;
}
.jas-cookie .essential-only {
  background: transparent;
  color: var(--paper);
  border: 1px solid rgba(244, 239, 230, 0.3);
}
.jas-cookie .essential-only:hover { background: rgba(244, 239, 230, 0.08); }
@media (max-width: 640px) {
  .jas-cookie {
    grid-template-columns: 1fr;
    bottom: 12px;
    left: 12px;
    right: 12px;
    padding: 16px 18px;
  }
  .jas-cookie .actions { justify-content: flex-end; }
}

/* .lang-block — used by splitLines() when a headline contains dual-language
   siblings (e.g. <h1><span lang="en">…</span><span lang="es">…</span></h1>).
   Mask reveals need each line as a block element, so the lang container
   must also be block, not inline. Higher specificity than the generic
   span[lang] rules so these win. */
.lang-block { display: block; }
.lang-block[lang="es"] { display: none; }
body.lang-es .lang-block[lang="en"] { display: none; }
body.lang-es .lang-block[lang="es"] { display: block; }

/* The toggle in the top utility bar — interactive now */
.ub .lang b, .ub .lang span { cursor: pointer; transition: opacity var(--t-fast) ease, border-color var(--t-fast) ease; }
.ub .lang b:hover, .ub .lang span:hover { opacity: 1; }

/* ────────────────────────────────────────────────────────────
   GLASSMORPHISM — targeted surfaces only (the design system
   keeps the cream/paper editorial floor; glass is reserved for
   surfaces that *float over* content, where blur actually does
   something visible).
   ──────────────────────────────────────────────────────────── */

/* Nav bar — when scrolled past the top, become a frosted bar.
   Overrides the simple solid bg from the page's inline <style>. */
nav.bar.scrolled {
  background: rgba(244, 239, 230, 0.72) !important;
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid rgba(219, 210, 189, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 8px 24px -16px rgba(26, 30, 27, 0.14);
}

/* Float CTA — glass-leaf */
.float-cta {
  background: rgba(46, 107, 58, 0.82);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.32),
    inset 0 0 0 1px rgba(46, 107, 58, 0.18),
    0 14px 40px -10px rgba(46, 107, 58, 0.45),
    0 4px 14px -4px rgba(26, 30, 27, 0.18);
}
.float-cta:hover {
  background: rgba(46, 107, 58, 0.92);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.40),
    inset 0 0 0 1px rgba(46, 107, 58, 0.22),
    0 18px 50px -10px rgba(46, 107, 58, 0.55),
    0 6px 18px -4px rgba(26, 30, 27, 0.22);
}

/* CleanCheck modal — glass panel + blurred backdrop */
.modal-bg {
  background: rgba(26, 30, 27, 0.42);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.modal {
  background: rgba(250, 247, 241, 0.86);
  backdrop-filter: saturate(180%) blur(22px);
  -webkit-backdrop-filter: saturate(180%) blur(22px);
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 24px 60px -20px rgba(26, 30, 27, 0.30),
    0 0 0 1px rgba(255, 255, 255, 0.20);
}

/* CleanCheck slider handle — glass pill */
.slider-handle::after {
  background: rgba(250, 247, 241, 0.78) !important;
  backdrop-filter: saturate(180%) blur(8px);
  -webkit-backdrop-filter: saturate(180%) blur(8px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    inset 0 0 0 1px rgba(255, 255, 255, 0.25),
    0 4px 12px -2px rgba(26, 30, 27, 0.25) !important;
}

/* Toast — glass dark */
.toast {
  background: rgba(26, 30, 27, 0.78) !important;
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    0 12px 30px -8px rgba(0, 0, 0, 0.40);
}

/* Booking summary card — subtle premium paper.
   The bookings page has solid bone behind, so this leans
   "premium card stock" rather than full frosted glass. */
[data-page="bookings"] .summary {
  background: rgba(250, 247, 241, 0.82);
  backdrop-filter: saturate(150%) blur(10px);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 24px 60px -30px rgba(26, 30, 27, 0.16);
}

/* Home hero floating cards — premium paper treatment */
[data-page="home"] .proof-card,
[data-page="home"] .quote-card {
  background: rgba(250, 247, 241, 0.92);
  backdrop-filter: saturate(140%) blur(8px);
  -webkit-backdrop-filter: saturate(140%) blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 24px 60px -30px rgba(26, 30, 27, 0.16);
}

/* ────────────────────────────────────────────────────────────
   MOTION — line-mask reveals, eyebrow tracking, scroll bar,
   magnetic CTAs
   ──────────────────────────────────────────────────────────── */

/* Per-line mask wrapper (JS wraps each <br>-delimited line) */
.mask-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.08em; /* breathing room for descenders */
}
.mask-inner {
  display: inline-block;
  transform: translateY(110%);
  will-change: transform;
}

/* Eyebrow expansion: text starts compressed, expands its tracking */
.eb.eb-tracking,
.eb-tracking {
  letter-spacing: 0;
  opacity: 0;
  will-change: letter-spacing, opacity;
}

/* Scroll progress bar — thin leaf line at the very top */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg,
    rgba(46, 107, 58, 0.0) 0%,
    rgba(46, 107, 58, 0.95) 18%,
    rgba(79, 140, 91, 1.0) 100%);
  transform: scaleX(0);
  transform-origin: left center;
  z-index: 1000;
  pointer-events: none;
}

/* Magnetic targets — JS handles transform; we ensure smooth return */
.magnetic {
  will-change: transform;
  display: inline-flex; /* preserves inline-flow for inline anchors */
}

/* Anchor-styled buttons must never have underlines */
a.btn, .btn, a.float-cta, a.pkg-card, a.svc { text-decoration: none; }

/* Leaf-CTA premium glow on hover */
.btn-leaf {
  transition: transform var(--t-fast) var(--ease-out),
              background-color var(--t-fast) ease,
              box-shadow 320ms var(--ease-out);
}
.btn-leaf:hover {
  box-shadow:
    0 0 0 6px rgba(46, 107, 58, 0.08),
    0 14px 30px -10px rgba(46, 107, 58, 0.45);
}

/* Cursor pointer on big interactive areas — already there, just consistent */
.magnetic, .magnetic * { cursor: pointer; }

/* Make sure backdrop-filtered elements stay isolated so blur doesn't
   spill into siblings on browsers that don't fully support it */
nav.bar, .float-cta, .modal, .modal-bg, .toast,
[data-page="bookings"] .summary,
[data-page="home"] .proof-card,
[data-page="home"] .quote-card { isolation: isolate; }

/* ────────────────────────────────────────────────────────────
   JESKO #1 — CLIP-PATH REVEALS
   Photos wipe into view rather than fading.
   ──────────────────────────────────────────────────────────── */
.clip-reveal {
  clip-path: inset(0 100% 0 0);
  -webkit-clip-path: inset(0 100% 0 0);
  will-change: clip-path;
}

/* ────────────────────────────────────────────────────────────
   JESKO #2 — TRUST MARQUEE
   Slow horizontal scroll of trust receipts, dark band, sits
   between Final CTA and footer (or directly above footer on
   pages without a Final CTA).
   ──────────────────────────────────────────────────────────── */
.trust-marquee {
  background: var(--ink);
  color: var(--paper);
  padding: 20px 0;
  overflow: hidden;
  border-top: 1px solid rgba(244, 239, 230, 0.06);
  border-bottom: 1px solid rgba(244, 239, 230, 0.06);
}
.trust-marquee-track {
  display: flex;
  white-space: nowrap;
  will-change: transform;
}
.trust-marquee-track span {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding-right: 0;
  flex-shrink: 0;
  color: rgba(244, 239, 230, 0.78);
}
.trust-marquee-track span em {
  color: var(--leaf-soft);
  font-style: normal;
  margin: 0 14px;
}

/* ────────────────────────────────────────────────────────────
   JESKO #3 — EYEBROW LEADING DOT
   A small leaf dot scales in before section-leading eyebrows.
   ──────────────────────────────────────────────────────────── */
.eb-dotted {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.eb-dotted::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--leaf);
  margin-right: 10px;
  transform: scale(var(--dot-s, 0));
  transform-origin: center;
  will-change: transform;
}

/* ────────────────────────────────────────────────────────────
   JESKO #4 — PINNED STEP STORY (home "How it works")
   Each step dims when not active; active step has full ink.
   ──────────────────────────────────────────────────────────── */
.steps .step {
  transition: opacity 360ms cubic-bezier(0.2, 0, 0, 1),
              transform 360ms cubic-bezier(0.2, 0, 0, 1);
}
.steps .step.step-dim { opacity: 0.32; }
.steps .step.step-on  { opacity: 1; }
.steps .step.step-on .n { color: var(--moss); font-weight: 700; }
.steps .step.step-on .h { color: var(--ink); }
.steps .step .n {
  transition: color 360ms ease, font-weight 360ms ease;
}

/* Reduced motion overrides for the new pieces */
@media (prefers-reduced-motion: reduce) {
  .mask-inner { transform: none !important; }
  .scroll-progress { display: none !important; }
  .magnetic { transition: none !important; }
  .eb.eb-tracking, .eb-tracking { opacity: 1 !important; letter-spacing: 0.14em !important; }
  .clip-reveal { clip-path: none !important; -webkit-clip-path: none !important; }
  .trust-marquee-track { animation: none !important; }
  .eb-dotted::before { transform: scale(1) !important; }
  .steps .step.step-dim { opacity: 1 !important; }
}

/* ────────────────────────────────────────────────────────────
   MOBILE NAV — burger + drawer, injected by animations.js
   (initMobileNav) on every page with the standard nav.bar.
   HIDDEN + INERT at desktop widths: desktop keeps the full
   inline .menu exactly as-is; both pieces only come alive
   inside the ≤900px media block below. Open/close is a pure
   class toggle (.nav-drawer.open) — no GSAP in the path.
   ──────────────────────────────────────────────────────────── */
.nav-burger { display: none; }
.nav-drawer { display: none; }

/* Slim brand-strip pieces on the focused flows (the bookings
   checkout header + the CleanCheck report header): the phone
   link + the right-side group it sits in. Class-scoped (not
   [data-page]) so the first static paint is styled before
   PageRuntime tags <body> on the Next pages. */
.hdr-right { display: inline-flex; align-items: center; gap: 16px; }
a.hdr-phone {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-decoration: none;
  white-space: nowrap;
}
a.hdr-phone:hover { color: var(--leaf); }

/* ────────────────────────────────────────────────────────────
   MOBILE — shared responsive layer for all pages.
   Pages that need page-specific tweaks (home, services) also
   have their own inline @media rules, but this is the floor.
   ──────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  /* Page-level chrome — utility bar: phone + EN/ES only. "Sign in" and the
     "|" divider move into the nav drawer. The phone display string (number
     + "· text or call, 7am–9pm" suffix) is ONE admin-fed text node
     (data-content-key="phone.display.*"), so there is no markup hook to
     drop just the suffix — let it truncate with an ellipsis instead. */
  .ub { padding: 8px 16px; font-size: 11px; flex-wrap: wrap; gap: 6px; }
  .ub .pin { display: none; }
  .ub .right { width: 100%; gap: 10px; flex-wrap: nowrap; justify-content: space-between; min-width: 0; }
  .ub .right > a, .ub .right > span[style*="opacity"] { display: none; }
  .ub .right > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Nav bar — ONE row: logo left, quote pill + burger right. The inline
     .menu links and the "Talk to us" ghost CTA live in the drawer now. */
  nav.bar { padding: 12px 16px; flex-wrap: nowrap; gap: 10px; }
  html.has-mobile-nav nav.bar .menu { display: none; } /* JS-injected burger present; without it the plain menu stays usable */
  nav.bar .ctas { margin-left: auto; gap: 6px; align-items: center; }
  nav.bar .ctas .btn { padding: 0 12px; height: 36px; font-size: 13px; }
  nav.bar .ctas .btn-ghost { display: none; }

  /* Burger — minimal 2-line glyph, 44px tap target, crosses to an X */
  .nav-burger {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    margin: -4px -12px -4px 0;
    padding: 0;
    background: transparent;
    border: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .nav-burger-line {
    width: 20px;
    height: 2px;
    border-radius: 2px;
    background: var(--ink);
    transition: transform var(--t-base) var(--ease-out);
  }
  .nav-burger[aria-expanded="true"] .nav-burger-line:first-child { transform: translateY(3.5px) rotate(45deg); }
  .nav-burger[aria-expanded="true"] .nav-burger-line:last-child { transform: translateY(-3.5px) rotate(-45deg); }

  /* Drawer — full-width panel under the sticky bar (the bar is its
     positioning context). Closed state is invisible AND inert. */
  .nav-drawer {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--bone);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 24px 48px -28px rgba(26, 30, 27, 0.28);
    padding: 6px 16px 18px;
    opacity: 0;
    transform: translateY(-8px);
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--t-base) var(--ease-out),
                transform var(--t-base) var(--ease-out),
                visibility 0s linear var(--t-base);
  }
  .nav-drawer.open {
    opacity: 1;
    transform: none;
    visibility: visible;
    pointer-events: auto;
    transition: opacity var(--t-base) var(--ease-out),
                transform var(--t-base) var(--ease-out);
  }
  .nav-drawer-links { display: flex; flex-direction: column; }
  .nav-drawer-link {
    display: flex;
    align-items: center;
    min-height: 52px;
    font-family: var(--display);
    font-size: 26px;
    letter-spacing: -0.01em;
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid var(--line-soft);
  }
  .nav-drawer-link.on { color: var(--leaf); }
  .nav-drawer-extras { display: flex; align-items: center; flex-wrap: wrap; gap: 18px; padding-top: 16px; }
  .nav-drawer-extras .btn { height: 44px; padding: 0 18px; font-size: 14px; }
  .nav-drawer-signin {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-size: 14px;
    color: var(--ink-2);
    text-decoration: none;
  }
  .nav-drawer-signin > span { border-bottom: 1px solid var(--line-2); padding-bottom: 1px; }
  .nav-drawer .lang {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.08em;
  }
  .nav-drawer .lang b,
  .nav-drawer .lang span {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 8px;
    cursor: pointer;
    color: var(--ink-3);
    font-weight: 400;
  }
  .nav-drawer .lang b.on,
  .nav-drawer .lang span.on { color: var(--leaf); text-decoration: underline; text-underline-offset: 4px; }

  /* Optional scroll lock while the drawer is open (toggled by initMobileNav) */
  body.nav-drawer-open { overflow: hidden; }

  /* Page header on .page-h pages */
  .page-h { padding: 40px 24px 24px; }
  .page-h h1 { font-size: 44px !important; line-height: 1.06 !important; margin: 8px 0 20px !important; }
  .page-h .lead { font-size: 16px; max-width: none; }

  /* Section padding */
  section.pg { padding: 40px 24px; }
  .pg .sec-head h2 { font-size: 32px !important; }

  /* Footer */
  footer.site { grid-template-columns: 1fr 1fr !important; padding: 32px 24px 20px !important; gap: 28px !important; }
  footer.site .legal { flex-direction: column; gap: 8px; }

  /* About — 4-col stats grid → 2-col, 2-col principles+founder → 1-col.
     Each selector ships two spellings of the style match: the legacy generator
     serializes inline styles with a space after the colon ("…: repeat(4…"),
     React's serializer without one ("…:repeat(4…") — both must collapse. */
  [data-page="about"] section.pg > div[style*="grid-template-columns: repeat(4"],
  [data-page="about"] section.pg > div[style*="grid-template-columns:repeat(4"] { grid-template-columns: 1fr 1fr !important; gap: 20px !important; }
  [data-page="about"] section.pg > div[style*="grid-template-columns: 1fr 1fr"],
  [data-page="about"] section.pg > div[style*="grid-template-columns:1fr 1fr"] { grid-template-columns: 1fr !important; gap: 28px !important; }
  [data-page="about"] .about-stat > div:first-child { font-size: 44px !important; }

  /* Reviews — summary block + 3-col review grid → stack */
  [data-page="reviews"] section.pg > div:first-of-type { flex-direction: column; gap: 20px !important; }
  [data-page="reviews"] section.pg > div:nth-of-type(2) > div[style*="grid-template-columns: repeat(3"] { grid-template-columns: 1fr !important; }
  [data-page="reviews"] section.pg > div[style*="grid-template-columns: repeat(5"] { grid-template-columns: 1fr 1fr !important; gap: 14px !important; }

  /* Contact — 1.2fr 1fr → single column; inside the message card the name/phone
     pair stacks too, and the fields drop their intrinsic size-20 width (width
     100% + min-width 0) so the card can never push the page wider than the
     viewport on small screens. */
  [data-page="contact"] section.pg > div[style*="grid-template-columns"] { grid-template-columns: 1fr !important; gap: 24px !important; }
  [data-page="contact"] .contact-form { padding: 24px !important; }
  [data-page="contact"] .contact-form form > div[style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
  [data-page="contact"] .contact-form .field { width: 100%; min-width: 0; }

  /* FAQ — already single column, just tighten */
  [data-page="faq"] details summary { font-size: 18px !important; }
  [data-page="faq"] details p { font-size: 14px !important; }

  /* Legal — already simple, just tighten card padding */
  [data-page="legal"] .legal-card { padding: 24px !important; }
  [data-page="legal"] .legal-card h2 { font-size: 26px !important; }

  /* CleanCheck — rooms 2-col → 1, photos 2-col → 1, supplies 3-col → 1.
     Header becomes the slim brand strip: logo (the home link) + phone.
     The back link folds into the logo and the report pill into the hero. */
  [data-page="clean-checklist"] header { padding: 10px 16px !important; flex-wrap: nowrap; gap: 10px; }
  [data-page="clean-checklist"] header .back { display: none; }
  [data-page="clean-checklist"] header .report-id { display: none; }
  [data-page="clean-checklist"] .wrap { padding: 24px 16px 60px !important; }
  [data-page="clean-checklist"] .hero-card { padding: 28px 24px !important; }
  [data-page="clean-checklist"] h1.t { font-size: 44px !important; }
  [data-page="clean-checklist"] .hero-meta { gap: 16px !important; flex-direction: column; }
  [data-page="clean-checklist"] .actions { flex-direction: column; align-items: stretch; }
  [data-page="clean-checklist"] .actions .btn { width: 100%; }
  [data-page="clean-checklist"] section { padding: 24px 20px !important; }
  [data-page="clean-checklist"] section h3 { font-size: 24px !important; }
  [data-page="clean-checklist"] .rooms,
  [data-page="clean-checklist"] .photos { grid-template-columns: 1fr !important; }
  [data-page="clean-checklist"] .supplies { grid-template-columns: 1fr 1fr !important; }
  [data-page="clean-checklist"] .actions-row { grid-template-columns: 1fr !important; gap: 14px !important; }
  [data-page="clean-checklist"] .share-card { flex-direction: column; align-items: stretch; gap: 12px; text-align: center; }

  /* Bookings — single column layout + smaller progress strip.
     Header becomes the slim brand strip: logo (the home link) + phone.
     The back link folds into the logo; "· need help?" trims to the number. */
  [data-page="bookings"] header { padding: 10px 16px !important; flex-wrap: nowrap; gap: 10px; }
  [data-page="bookings"] header .back { display: none; }
  [data-page="bookings"] header .help-suffix { display: none; }
  [data-page="bookings"] .progress { padding: 16px 20px !important; }
  [data-page="bookings"] .progress-steps { font-size: 9px !important; gap: 8px; flex-wrap: wrap; }
  [data-page="bookings"] .layout { grid-template-columns: 1fr !important; gap: 24px !important; padding: 24px 16px 60px !important; }
  [data-page="bookings"] .panel { padding: 24px !important; min-height: 0 !important; }
  [data-page="bookings"] .step-title { font-size: 32px !important; }
  [data-page="bookings"] .tile-row { grid-template-columns: 1fr 1fr !important; gap: 8px !important; }
  [data-page="bookings"] .grid-2 { grid-template-columns: 1fr !important; }
  [data-page="bookings"] .cleaners { grid-template-columns: 1fr !important; }
  [data-page="bookings"] .summary { position: static !important; padding: 20px !important; }
  [data-page="bookings"] .summary .total .val { font-size: 28px !important; }

  /* Trust-marquee — smaller text */
  .trust-marquee-track span { font-size: 11px !important; padding-right: 0 !important; }
}

/* ────────────────────────────────────────────────────────────
   PRINT — CleanCheck Report as a designed PDF document.
   Triggered by window.print() or server-side Puppeteer rendering
   with `?print=1` URL parameter.
   Letter-size (8.5 × 11 in / 216 × 279mm) with 0.5in margins.
   ──────────────────────────────────────────────────────────── */
@page {
  size: letter;
  margin: 0.5in;
}

@media print {
  /* Reset everything to clean, predictable rendering */
  html, body {
    background: #fff !important;
    color: #1A1E1B !important;
    font-size: 11pt;
    line-height: 1.4;
  }

  /* Force backgrounds to print (Chrome/Safari) */
  *, *::before, *::after {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    color-adjust: exact !important;
    transform: none !important;
    animation: none !important;
    transition: none !important;
  }

  /* Hide everything that's not part of the report */
  .ub, nav.bar, footer, .float-cta, .toast,
  .modal-bg, .scroll-progress, .trust-marquee,
  .skip-link, .note-lang,
  [data-page="clean-checklist"] header,
  [data-page="clean-checklist"] .actions,
  [data-page="clean-checklist"] .reclean-card,
  [data-page="clean-checklist"] .tip-card,
  [data-page="clean-checklist"] .actions-row,
  [data-page="clean-checklist"] .share-card,
  [data-page="clean-checklist"] .dispute {
    display: none !important;
  }

  /* CleanCheck-only print styles */
  [data-page="clean-checklist"] .wrap {
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  /* Hide entire Spanish content when printing in English mode (and vice versa) */
  body:not(.lang-es) [lang="es"] { display: none !important; }
  body.lang-es [lang="en"] { display: none !important; }

  /* ── Cover page (the hero) ── */
  [data-page="clean-checklist"] .hero-card {
    background: #fff !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    box-shadow: none !important;
    page-break-after: always;
    min-height: 9.5in; /* fills the first page */
    display: flex;
    flex-direction: column;
  }
  [data-page="clean-checklist"] .hero-card::before {
    content: "JAS CLEANING · CLEANCHECK REPORT";
    display: block;
    font-family: var(--mono);
    font-size: 9pt;
    letter-spacing: 0.18em;
    color: #2E6B3A;
    padding-bottom: 16pt;
    border-bottom: 2px solid #2E6B3A;
    margin-bottom: 32pt;
  }
  [data-page="clean-checklist"] .hero-eyebrow {
    font-family: var(--mono);
    font-size: 9pt;
    letter-spacing: 0.14em;
    color: #2E6B3A;
    text-transform: uppercase;
  }
  [data-page="clean-checklist"] .hero-eyebrow .dot { display: none; }
  [data-page="clean-checklist"] .hero-eyebrow .hero-seal {
    margin-left: 8pt;
    padding: 3pt 8pt;
    background: #E9EFD9;
    border: 1px solid #B8CFA1;
    border-radius: 999pt;
    font-size: 8pt;
    color: #143E1F;
  }
  [data-page="clean-checklist"] h1.t {
    font-family: var(--display);
    font-size: 42pt !important;
    line-height: 1.05 !important;
    color: #1A1E1B !important;
    margin: 12pt 0 !important;
    letter-spacing: -0.02em;
  }
  [data-page="clean-checklist"] h1.t em { color: #2E6B3A !important; font-style: italic; }
  [data-page="clean-checklist"] .hero-card > p {
    font-size: 11pt !important;
    color: #44463E !important;
    line-height: 1.5;
    max-width: 5.5in;
    margin-bottom: 32pt;
  }
  [data-page="clean-checklist"] .hero-meta {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 14pt 32pt !important;
    margin-top: 24pt;
    padding-top: 24pt;
    border-top: 1px solid #DBD2BD;
  }
  [data-page="clean-checklist"] .hero-meta > div {
    font-size: 11pt;
    color: #1A1E1B;
  }
  [data-page="clean-checklist"] .hero-meta b {
    display: block;
    font-family: var(--mono);
    font-size: 8pt !important;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #6F6F65 !important;
    font-weight: 500;
    margin-bottom: 4pt;
  }
  /* Bottom-of-cover footer with report ID + signature line */
  [data-page="clean-checklist"] .hero-card::after {
    content: "REPORT #JAS-2057 · jascleaning.com/r/JAS-2057-x9k · Verified by JAS";
    display: block;
    margin-top: auto;
    padding-top: 24pt;
    border-top: 1px solid #DBD2BD;
    font-family: var(--mono);
    font-size: 8pt;
    letter-spacing: 0.14em;
    color: #6F6F65;
    text-align: center;
  }

  /* ── Section style (note / checklist / photos / supplies) ── */
  [data-page="clean-checklist"] section {
    background: #fff !important;
    border: 1px solid #DBD2BD !important;
    border-radius: 4pt !important;
    padding: 18pt 20pt !important;
    margin: 12pt 0 !important;
    box-shadow: none !important;
    page-break-inside: avoid;
  }
  [data-page="clean-checklist"] section h3 {
    font-family: var(--display);
    font-size: 18pt !important;
    color: #1A1E1B !important;
    margin: 0 0 12pt;
    letter-spacing: -0.01em;
  }
  [data-page="clean-checklist"] section .h {
    border-bottom: 1px solid #EAE2CE;
    padding-bottom: 10pt;
    margin-bottom: 14pt;
  }

  /* ── Cleaner note (yellow card) ── */
  [data-page="clean-checklist"] .note {
    background: #FAF4E2 !important;
    border: 1px solid #EBDDB8;
    padding: 16pt 20pt !important;
    border-radius: 4pt;
  }
  [data-page="clean-checklist"] .note::before {
    font-size: 36pt !important;
    color: #A77E3A;
  }
  [data-page="clean-checklist"] .note p {
    font-family: var(--display);
    font-size: 14pt !important;
    line-height: 1.4 !important;
    color: #5A3F0F !important;
    padding-left: 28pt !important;
  }
  [data-page="clean-checklist"] .note .by {
    padding-left: 28pt !important;
    font-size: 10pt !important;
    color: #6E521D !important;
  }

  /* ── Checklist ── */
  [data-page="clean-checklist"] .check-progress {
    margin-bottom: 16pt;
    gap: 12pt;
  }
  [data-page="clean-checklist"] .check-bar {
    height: 6pt !important;
    background: #ECE5D5 !important;
  }
  [data-page="clean-checklist"] .check-bar > div {
    background: #2E6B3A !important;
  }
  [data-page="clean-checklist"] .rooms {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 8pt !important;
  }
  [data-page="clean-checklist"] .room {
    background: #FAF7F1 !important;
    border: 1px solid #EAE2CE !important;
    padding: 10pt 12pt !important;
    border-radius: 3pt;
    page-break-inside: avoid;
  }
  [data-page="clean-checklist"] .room h4 {
    font-size: 11pt !important;
    color: #1A1E1B;
  }
  [data-page="clean-checklist"] .room ul {
    font-size: 9pt !important;
    color: #44463E;
  }
  [data-page="clean-checklist"] .room li::before { color: #2E6B3A; }

  /* ── Photos: 2-up grid ── */
  [data-page="clean-checklist"] .photos {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 12pt !important;
    page-break-inside: avoid;
  }
  [data-page="clean-checklist"] .photo-pair {
    page-break-inside: avoid;
    border: 1px solid #DBD2BD !important;
    border-radius: 3pt;
  }
  [data-page="clean-checklist"] .slider-wrap {
    height: 2in !important;
  }
  [data-page="clean-checklist"] .slider-handle { display: none !important; }
  /* In print, show "after" side fully (assume the clean is done) */
  [data-page="clean-checklist"] .slider-img.after {
    clip-path: none !important;
    -webkit-clip-path: none !important;
  }
  [data-page="clean-checklist"] .slider-img.before {
    opacity: 0; /* hide before; we only show after on PDFs */
  }
  [data-page="clean-checklist"] .photo-pair .label {
    background: #FAF7F1 !important;
    padding: 6pt 10pt !important;
    font-size: 9pt !important;
    border-bottom: 1px solid #DBD2BD;
  }

  /* ── Supplies: 2-col ── */
  [data-page="clean-checklist"] .supplies {
    grid-template-columns: 1fr 1fr !important;
    gap: 6pt !important;
  }
  [data-page="clean-checklist"] .supply {
    background: #FAF7F1 !important;
    border: 1px solid #EAE2CE !important;
    padding: 8pt 10pt !important;
    font-size: 9pt !important;
  }
  [data-page="clean-checklist"] .supply .ic {
    width: 18pt; height: 18pt;
    font-size: 9pt !important;
  }
  [data-page="clean-checklist"] .supply.low {
    background: #FBEBE0 !important;
    border-color: #E1B7A6 !important;
  }

  /* ── End-of-doc footer (legal + signature) ── */
  [data-page="clean-checklist"] .wrap::after {
    content: "This Report is a tamper-proof record of work performed by JAS Cleaning. Photos remain on file for 90 days. For disputes or insurance claims, email legal@jascleaning.com referencing Report #JAS-2057. JAS Cleaning · Miami-Dade FL · $2M general liability · jascleaning.com";
    display: block;
    margin-top: 24pt;
    padding-top: 16pt;
    border-top: 1px solid #DBD2BD;
    font-family: var(--mono);
    font-size: 7.5pt;
    line-height: 1.5;
    color: #6F6F65;
    text-align: center;
  }

  /* Make link URLs visible in PDF (where useful) */
  [data-page="clean-checklist"] a[href]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    color: #6F6F65;
  }
  /* …except for internal jumps and tel/mailto/sms */
  [data-page="clean-checklist"] a[href^="tel:"]::after,
  [data-page="clean-checklist"] a[href^="mailto:"]::after,
  [data-page="clean-checklist"] a[href^="sms:"]::after,
  [data-page="clean-checklist"] a[href^="#"]::after { content: ""; }

  /* Page-break controls */
  [data-page="clean-checklist"] section { page-break-inside: avoid; }
  [data-page="clean-checklist"] section + section { page-break-before: auto; }
}

/* Very narrow viewports (320–500) */
@media (max-width: 500px) {
  .ub .right > span:first-child { font-size: 10px; }
  nav.bar .logo { font-size: 18px; }
  nav.bar .logo .logo-mark { width: 24px; height: 24px; font-size: 13px; }
  .nav-drawer-link { font-size: 24px; }
  /* Focused-flow brand strips shrink their lockup the same way */
  .bk-header .logo,
  [data-page="bookings"] header .logo,
  [data-page="clean-checklist"] header .logo { font-size: 18px; }
  .page-h h1 { font-size: 36px !important; }
  [data-page="clean-checklist"] .supplies { grid-template-columns: 1fr !important; }
  [data-page="bookings"] .tile-row { grid-template-columns: 1fr 1fr !important; }
  footer.site { grid-template-columns: 1fr !important; }
}

/* Reduced-motion: kill nontrivial animations, keep tiny fades */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 80ms !important;
    scroll-behavior: auto !important;
  }
  .float-cta { animation: none !important; }
  html { scroll-behavior: auto !important; }
  /* Mobile nav drawer opens/closes instantly — no slide, no cross-fade */
  .nav-drawer, .nav-burger-line { transition: none !important; }
}
