/* ==========================================================================
   BABY ANGELS — HOME HERO: circular photo + floating bubbles + drifting clouds
   --------------------------------------------------------------------------
   Ported from the Coming Soon landing page so the main site matches it.

   HOW TO USE
     1. Add this file AFTER styles.css:
          <link rel="stylesheet" href="hero-bubbles.css?v=1">
     2. Add the class `hero--bubbles` to the home hero section:
          <section class="hero hero--bubbles">
     3. Replace the contents of .hero-visual with the markup shown at the
        bottom of this file.

   Everything here is scoped under `.hero--bubbles`, so no other page and no
   other section is affected. Remove the class and the old square hero
   returns exactly as it was.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. RESET THE OLD SQUARE FRAME
   styles.css gives .hero-visual a clipped box, a drop shadow and a dark
   gradient overlay. All three fight a round photo, so they're undone here.
   -------------------------------------------------------------------------- */
.hero--bubbles .hero-visual {
  overflow: visible;          /* let bubbles + clouds drift past the edge */
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(380px, 42vw, 560px);
}
.hero--bubbles .hero-visual::after { display: none; }   /* kill dark overlay */
.hero--bubbles .hero-halo         { display: none; }    /* old gold rings */
.hero--bubbles .hero-caption      { display: none; }    /* old photo caption */


/* --------------------------------------------------------------------------
   2. THE ORB — the circular photo and everything orbiting it
   aspect-ratio keeps it a perfect circle at every screen width.
   -------------------------------------------------------------------------- */
.hero-orb {
  position: relative;
  width: clamp(300px, 38vw, 520px);
  aspect-ratio: 1 / 1;
  z-index: 2;
  /* Slow breath, so the ball feels suspended rather than pinned.
     NOTE: no `will-change: transform` here. It promotes .hero-orb to its own
     compositing layer, and Chromium then rasterises that layer at the orb's
     own size — which clips the photo's large soft shadow to a rectangle. That
     clipped rectangle was the mystery grey box behind the picture. */
  animation: orbFloat 15s ease-in-out infinite;
}

/* Glass shell OVER the photo. Deliberately minimal: a small specular gloss
   at upper-left and nothing else. The rose rim vignette that used to live
   here is gone — it was drawing a pink circle around the picture instead of
   reading as roundness. Depth now comes from the shadows, not from tinting
   the image. */
.hero-orb::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: 50%;
  pointer-events: none;
  background:
    radial-gradient(ellipse 24% 18% at 31% 19%,
      rgba(255, 255, 255, 0.46) 0%,
      rgba(255, 255, 255, 0.12) 44%,
      rgba(255, 255, 255, 0)    100%),
    radial-gradient(circle at 27% 23%,
      rgba(255, 255, 255, 0.10) 0%,
      rgba(255, 255, 255, 0)    44%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.42);
}

@keyframes orbFloat {
  0%, 100% { transform: translateY(0)     scale(1);     }
  50%      { transform: translateY(-10px) scale(1.006); }
}

.hero--bubbles .hero-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  position: relative;
  z-index: 2;
  border-radius: 50%;
  /* Soft rose glow beneath + a white inner ring, so the photo reads as a
     drop of glass rather than a cut-out circle. */
  /* Depth comes from drop-shadow, NOT box-shadow. drop-shadow traces the
     element's actual alpha — a circle — so it can never render as a box, and
     it is not clipped the way a box-shadow on a composited layer is. Two
     passes: a wide ambient one for the float, a tighter one under the ball so
     it doesn't look adrift. Neutral ink, no pink. */
  box-shadow: inset 0 0 0 4px rgba(255, 255, 255, 0.42);
  filter:
    drop-shadow(0 26px 34px rgba(42, 36, 56, 0.20))
    drop-shadow(0 8px 14px rgba(42, 36, 56, 0.12));
}


/* --------------------------------------------------------------------------
   3. BUBBLES — base soap-bubble shell
   Three stacked layers make the glass read convincingly:
     a) white highlight top-left  (the light source)
     b) faint bounce-light bottom-right
     c) a pink→mauve→blue tint across the body
   backdrop-filter lets whatever sits behind show through, slightly blurred.
   -------------------------------------------------------------------------- */
.hero--bubbles .bubble {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  /* BEHIND the photo (which is z-index 2). At z-index 3 they painted over
     the nursery and covered the chairs and ceiling; from behind they peek
     out around the rim and read as floating around the ball. */
  z-index: 1;
  background:
    radial-gradient(circle at 30% 26%,
      rgba(255, 255, 255, 0.75) 0%,
      rgba(255, 255, 255, 0.12) 22%,
      rgba(255, 255, 255, 0)    46%),
    radial-gradient(circle at 68% 74%,
      rgba(255, 255, 255, 0.28) 0%,
      rgba(255, 255, 255, 0)    40%),
    linear-gradient(135deg,
      rgba(240, 180, 200, 0.35)  0%,
      rgba(199, 158, 195, 0.30) 45%,
      rgba(169, 169, 206, 0.28) 65%,
      rgba(143, 163, 201, 0.32) 100%);
  -webkit-backdrop-filter: blur(3px) saturate(1.05);
          backdrop-filter: blur(3px) saturate(1.05);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.45),
    inset -8px -8px 18px rgba(180, 155, 200, 0.18),
    inset 6px 6px 14px rgba(255, 255, 255, 0.28),
    0 12px 30px -14px rgba(180, 155, 200, 0.35);
  animation: bubbleFloat 16s ease-in-out infinite;
  will-change: transform;
}

/* ---- Tinted bubbles (1–7): hug the photo, carry colour ---- */
.hero--bubbles .bubble-1 {
  width: clamp(76px, 9vw, 132px); height: clamp(76px, 9vw, 132px);
  /* Offsets kept shallow on purpose: at full drift (bubbleFloat peaks at
     -20px) the bubble must still sit below the top of the hero. */
  /* the orb itself floats 10px, and these ride inside it, so the clearance
     below is measured from both animations at once, not from this one alone */
  top: calc(clamp(-30px, -2.2vw, -14px) + 27px); left: clamp(-56px, -4vw, -28px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.75) 0%, rgba(255,255,255,0.10) 24%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, rgba(240,176,195,0.42) 0%, rgba(224,158,188,0.32) 55%, rgba(199,158,195,0.28) 100%);
  animation: bubbleFloat 18s ease-in-out infinite; animation-delay: 0s;
}
.hero--bubbles .bubble-2 {
  width: clamp(60px, 7.4vw, 112px); height: clamp(60px, 7.4vw, 112px);
  bottom: clamp(-18px, -1.4vw, -6px); left: clamp(16px, 2.6vw, 52px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.75) 0%, rgba(255,255,255,0.12) 24%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, rgba(180,205,240,0.48) 0%, rgba(150,178,224,0.38) 55%, rgba(130,158,210,0.34) 100%);
  animation: bubbleFloatAlt 15s ease-in-out infinite; animation-delay: 1.2s;
}
.hero--bubbles .bubble-3 {
  width: clamp(34px, 4.3vw, 62px); height: clamp(34px, 4.3vw, 62px);
  top: 45%; left: clamp(-26px, -1.9vw, -12px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.78) 0%, rgba(255,255,255,0.12) 24%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, rgba(220,190,220,0.42) 0%, rgba(199,176,210,0.30) 100%);
  animation: bubbleFloat 13s ease-in-out infinite; animation-delay: 2.6s;
}
.hero--bubbles .bubble-4 {
  width: clamp(20px, 2.6vw, 36px); height: clamp(20px, 2.6vw, 36px);
  top: calc(clamp(-26px, -1.9vw, -12px) + 12px); left: clamp(60px, 7.8vw, 112px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.85) 0%, rgba(255,255,255,0.15) 26%, rgba(255,255,255,0) 50%),
    linear-gradient(135deg, rgba(244,194,214,0.50) 0%, rgba(224,168,195,0.32) 100%);
  animation: bubbleFloatAlt 11s ease-in-out infinite; animation-delay: 0.6s;
}
.hero--bubbles .bubble-5 {
  width: clamp(32px, 3.9vw, 58px); height: clamp(32px, 3.9vw, 58px);
  top: clamp(-8px, -0.6vw, -2px); right: clamp(-26px, -1.9vw, -10px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.80) 0%, rgba(255,255,255,0.12) 24%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, rgba(180,205,240,0.50) 0%, rgba(150,178,224,0.34) 100%);
  animation: bubbleFloat 14s ease-in-out infinite; animation-delay: 3.4s;
}
.hero--bubbles .bubble-6 {
  width: clamp(48px, 6vw, 86px); height: clamp(48px, 6vw, 86px);
  bottom: clamp(-26px, -2vw, -12px); right: clamp(-14px, -0.9vw, -4px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.76) 0%, rgba(255,255,255,0.12) 24%, rgba(255,255,255,0) 46%),
    linear-gradient(135deg, rgba(200,212,240,0.46) 0%, rgba(170,190,226,0.36) 60%, rgba(150,178,220,0.32) 100%);
  animation: bubbleFloatAlt 17s ease-in-out infinite; animation-delay: 1.8s;
}
.hero--bubbles .bubble-7 {
  width: clamp(15px, 1.9vw, 26px); height: clamp(15px, 1.9vw, 26px);
  bottom: clamp(26px, 4.3vw, 78px); left: clamp(-34px, -2.6vw, -14px);
  background:
    radial-gradient(circle at 30% 26%, rgba(255,255,255,0.88) 0%, rgba(255,255,255,0.18) 28%, rgba(255,255,255,0) 50%),
    linear-gradient(135deg, rgba(244,194,214,0.50) 0%, rgba(224,168,195,0.30) 100%);
  animation: bubbleFloat 12s ease-in-out infinite; animation-delay: 4.2s;
}

/* ---- Clear glass bubbles (8–15) ----
   Almost no tint — just sheen and a rim — so they stay readable drifting
   over plain ivory in the gap between the wording and the photo. -------- */
.hero--bubbles .bubble-glass {
  background:
    radial-gradient(circle at 28% 24%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.32) 22%,
      rgba(255, 255, 255, 0)    50%),
    radial-gradient(circle at 72% 78%,
      rgba(255, 255, 255, 0.42) 0%,
      rgba(255, 255, 255, 0)    46%),
    linear-gradient(135deg,
      rgba(240, 220, 232, 0.18) 0%,
      rgba(210, 218, 236, 0.20) 100%);
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, 0.70),
    inset -4px -4px 12px rgba(180, 170, 210, 0.14),
    inset 6px 6px 14px rgba(255, 255, 255, 0.42),
    0 10px 28px -12px rgba(180, 170, 210, 0.35);
}
.hero--bubbles .bubble-8  { width: clamp(44px,5.2vw,78px); height: clamp(44px,5.2vw,78px); top: calc(clamp(-26px,-1.7vw,-8px) + 19px);  left: clamp(-88px,-7vw,-44px);  animation: bubbleFloat    19s ease-in-out infinite; animation-delay: 0.4s; }
/* bubble-9 hung far enough left to sit on the "y" of Luxury at every desktop
   width from 1100 to 1600 — up to 35px of overlap, and its drift carries it a
   further 16px left at the far end of the cycle. Pulled in so the glass clears
   the headline with room to spare. (24 Aug 2026, Winnie) */
.hero--bubbles .bubble-9  { width: clamp(24px,3vw,45px);   height: clamp(24px,3vw,45px);   top: 28%;                        left: clamp(-44px,-3.3vw,-16px); animation: bubbleFloatAlt 14s ease-in-out infinite; animation-delay: 1.6s; }
.hero--bubbles .bubble-10 { width: clamp(36px,4.3vw,66px); height: clamp(36px,4.3vw,66px); bottom: clamp(16px,3.4vw,52px);  left: clamp(-96px,-7.4vw,-48px);  animation: bubbleFloat    21s ease-in-out infinite; animation-delay: 2.8s; }
.hero--bubbles .bubble-11 { width: clamp(14px,1.7vw,24px); height: clamp(14px,1.7vw,24px); top: 60%;                        left: clamp(-70px,-5.2vw,-26px);  animation: bubbleFloatAlt 12s ease-in-out infinite; animation-delay: 4.0s; }
.hero--bubbles .bubble-12 { width: clamp(20px,2.6vw,38px); height: clamp(20px,2.6vw,38px); top: calc(clamp(-34px,-2.6vw,-17px) + 25px);  left: clamp(-52px,-3.9vw,-19px);  animation: bubbleFloat    16s ease-in-out infinite; animation-delay: 3.2s; }
.hero--bubbles .bubble-13 { width: clamp(30px,3.5vw,52px); height: clamp(30px,3.5vw,52px); bottom: clamp(-34px,-2.6vw,-15px); left: clamp(-44px,-3vw,-15px);  animation: bubbleFloatAlt 18s ease-in-out infinite; animation-delay: 5.4s; }
.hero--bubbles .bubble-14 { width: clamp(24px,3vw,43px);   height: clamp(24px,3vw,43px);   top: 38%;                        right: clamp(-60px,-4.3vw,-22px); animation: bubbleFloat    15s ease-in-out infinite; animation-delay: 1.4s; }
.hero--bubbles .bubble-15 { width: clamp(17px,2.1vw,31px); height: clamp(17px,2.1vw,31px); top: calc(clamp(-52px,-3.5vw,-24px) + 37px);  right: clamp(34px,4.3vw,78px);    animation: bubbleFloatAlt 13s ease-in-out infinite; animation-delay: 3.8s; }

/* ---- The drift itself ----
   Two opposing paths so neighbouring bubbles weave past each other instead
   of marching in step. Long durations (11–21s) give the slow, dreamy feel.
   Only `transform` animates, which the GPU handles cheaply — no scroll jank. */
@keyframes bubbleFloat {
  0%, 100% { transform: translate(  0px,   0px) scale(1)    rotate( 0deg); }
  15%      { transform: translate( -6px, -14px) scale(1.04) rotate( 6deg); }
  30%      { transform: translate(  4px, -20px) scale(1.06) rotate(-4deg); }
  45%      { transform: translate( 14px, -12px) scale(1.03) rotate( 3deg); }
  60%      { transform: translate( 18px,   2px) scale(1.05) rotate(-6deg); }
  75%      { transform: translate(  8px,  12px) scale(1.03) rotate( 4deg); }
  90%      { transform: translate( -4px,   6px) scale(1.02) rotate(-2deg); }
}
@keyframes bubbleFloatAlt {
  0%, 100% { transform: translate(  0px,   0px) scale(1)    rotate( 0deg); }
  15%      { transform: translate(  6px,  10px) scale(1.03) rotate(-5deg); }
  30%      { transform: translate( -8px,  14px) scale(1.05) rotate( 4deg); }
  45%      { transform: translate(-16px,   4px) scale(1.04) rotate(-3deg); }
  60%      { transform: translate(-14px, -10px) scale(1.06) rotate( 5deg); }
  75%      { transform: translate( -4px, -16px) scale(1.03) rotate(-2deg); }
  90%      { transform: translate(  6px,  -6px) scale(1.02) rotate( 3deg); }
}


/* --------------------------------------------------------------------------
   4. CLOUDS
   Each cloud is the same "Dreamy cloud" photo cut to a cloud silhouette by
   an inline SVG mask, so it keeps the real pastel sky colours instead of
   looking like a flat shape. Sits at low opacity behind everything.
   -------------------------------------------------------------------------- */
.hero--bubbles {
  position: relative;
  /* NOT `overflow: hidden`. The hero is only as tall as its content, so any
     bubble or shadow crossing the top or bottom edge gets sliced off dead
     straight — and a straight cut across a round bubble reads as a ruled line
     drawn across the page. The clouds are clipped by their own .hero-clouds
     container (which is masked soft on every edge), so nothing here needs to
     clip. overflow-x: clip alone guards against sideways page scroll without
     touching the vertical. */
  overflow-x: clip;
  overflow-y: visible;
}

/* NOTE ON THE SELECTOR BELOW
   styles.css line ~5074 contains:
       .hero > *:not(.baby) { position: relative; z-index: 1; }
   That is two classes of specificity, so a plain `.hero-clouds` rule loses
   and the layer collapses to 0x0. Matching it with `.hero--bubbles >` and
   loading this file after styles.css wins on source order. Keep the child
   combinator — without it this breaks again. */
.hero--bubbles > .hero-clouds {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
  /* A cloud crossing the section edge gets sliced off dead straight by the
     overflow clip, and that slice reads as a ruled line across the page.
     Fading all four edges is what keeps the page continuous. */
  -webkit-mask-image:
    linear-gradient(180deg, transparent 0%, #000 14%, #000 86%, transparent 100%),
    linear-gradient(90deg,  transparent 0%, #000 7%,  #000 93%, transparent 100%);
          mask-image:
    linear-gradient(180deg, transparent 0%, #000 14%, #000 86%, transparent 100%),
    linear-gradient(90deg,  transparent 0%, #000 7%,  #000 93%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
.hero--bubbles .hero-cloud {
  position: absolute;
  object-fit: cover;
  opacity: 0.55;
  --cloud-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100' preserveAspectRatio='none'><path d='M 30 70 C 12 70 6 52 22 45 C 8 30 30 15 50 25 C 60 5 90 5 100 25 C 115 8 145 15 148 35 C 168 32 180 50 170 62 C 182 68 178 82 165 82 C 158 92 130 92 122 82 C 108 92 82 92 72 82 C 62 92 40 90 32 82 C 20 84 12 78 30 70 Z' fill='white'/></svg>");
  -webkit-mask-image: var(--cloud-mask);
          mask-image: var(--cloud-mask);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: cloudDrift 22s ease-in-out infinite;
  will-change: transform;
}

/* Minimal: four clouds, nothing stacked, nothing behind the orb's bubbles.
   Overlapping copies compound into grey — that is what read as dirty. Low
   opacity keeps them as atmosphere rather than scenery. */
.hero--bubbles .hero-cloud--1 { bottom: -2%; left:  -5%; width: 260px; height: 130px; opacity: 0.17; animation-delay: 0s; }
.hero--bubbles .hero-cloud--3 { bottom: -4%; left:  33%; width: 180px; height:  90px; opacity: 0.12; animation-delay: 6s; animation-duration: 28s; }
.hero--bubbles .hero-cloud--5 { bottom: -3%; right: -4%; width: 240px; height: 120px; opacity: 0.16; animation-delay: 8s; }
.hero--bubbles .hero-cloud--7 { top:    12%; left:  -6%; width: 130px; height:  65px; opacity: 0.09; animation-delay: 3s; animation-duration: 30s; }

@keyframes cloudDrift {
  0%, 100% { transform: translate(0, 0)      scale(1);     }
  25%      { transform: translate(14px, -6px) scale(1.02); }
  50%      { transform: translate(26px,  0)   scale(1.03); }
  75%      { transform: translate(12px,  6px) scale(1.01); }
}


/* --------------------------------------------------------------------------
   5. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 980px) {
  /* Stacked layout: shrink the orb, drop the far-left gap bubbles (they'd
     collide with the wording) and thin out the cloud bank. */
  .hero-orb { width: min(78vw, 420px); }
  .hero--bubbles .bubble-8,
  .hero--bubbles .bubble-9,
  .hero--bubbles .bubble-10,
  .hero--bubbles .bubble-11 { display: none; }
  .hero-cloud--2,
  .hero-cloud--6,
  .hero--bubbles .hero-cloud--7 { display: none; }
}

@media (max-width: 620px) {
  .hero-orb { width: min(84vw, 340px); }
  .hero--bubbles .bubble-12,
  .hero--bubbles .bubble-13 { display: none; }
  .hero--bubbles .hero-cloud { opacity: 0.10; }
}

/* Phones: backdrop-filter is the main cause of scroll stutter on mobile GPUs,
   so the frosted blur is dropped. Bubbles stay tinted and keep floating —
   transform animations are cheap and don't affect scrolling. */
@media (max-width: 820px) {
  .hero--bubbles .bubble {
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
  }
}

/* Motion-sensitive visitors get the same scene, held still. */
@media (prefers-reduced-motion: reduce) {
  .hero--bubbles .bubble,
  .hero-orb,
  .hero--bubbles .hero-cloud { animation: none; }
}


/* ==========================================================================
   MARKUP — paste this in place of the current .hero-visual contents
   ==========================================================================

<section class="hero hero--bubbles">
  <div class="hero-clouds" aria-hidden="true">
    <img class="hero-cloud hero-cloud--1" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
    <img class="hero-cloud hero-cloud--2" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
    <img class="hero-cloud hero-cloud--3" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
    <img class="hero-cloud hero-cloud--4" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
    <img class="hero-cloud hero-cloud--5" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
    <img class="hero-cloud hero-cloud--6" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
    <img class="hero-cloud hero-cloud--7" src="Image/dreamy-cloud-web.jpg" alt="" onerror="this.style.display='none'">
  </div>

  <div class="hero-grid">
    <div class="hero-content"> … unchanged … </div>

    <div class="hero-visual">
      <div class="hero-orb">
        <span class="bubble bubble-1"></span>
        <span class="bubble bubble-2"></span>
        <span class="bubble bubble-3"></span>
        <span class="bubble bubble-4"></span>
        <span class="bubble bubble-5"></span>
        <span class="bubble bubble-6"></span>
        <span class="bubble bubble-7"></span>
        <span class="bubble bubble-glass bubble-8"></span>
        <span class="bubble bubble-glass bubble-9"></span>
        <span class="bubble bubble-glass bubble-10"></span>
        <span class="bubble bubble-glass bubble-11"></span>
        <span class="bubble bubble-glass bubble-12"></span>
        <span class="bubble bubble-glass bubble-13"></span>
        <span class="bubble bubble-glass bubble-14"></span>
        <span class="bubble bubble-glass bubble-15"></span>
        <img class="hero-photo parallax-img" src="Image/Image4.jpeg"
             alt="Baby Angels nursery interior" loading="eager"
             onerror="this.style.display='none'">
      </div>
    </div>
  </div>
</section>

========================================================================== */


/* ==========================================================================
   6. TRUST RIBBON — icons inside floating glass bubbles, on a cloud bank
   --------------------------------------------------------------------------
   Same opt-in pattern: add `trust--bubbles` to <section class="trust"> and
   drop a .trust-clouds layer inside. Remove the class, old strip returns.
   ========================================================================== */

.trust--bubbles {
  position: relative;
  overflow: hidden;
  background: transparent;                 /* let the cloud bank show through */
  /* styles.css puts a 1px pink rule on both edges of .trust. Against the
     cloud band it reads as the page being chopped in two. */
  border-top: none;
  border-bottom: none;
  padding: clamp(52px, 6vw, 88px) var(--gutter) clamp(44px, 5vw, 72px);
}

/* --- Cloud bank ---------------------------------------------------------
   Sized to cover the full strip and bleed a little past every edge, so the
   band reads as continuous sky rather than a pasted-in rectangle. Same
   `.trust > *:not(.baby)` specificity trap as the hero — hence the child
   combinator. See the note in section 4. */
.trust--bubbles > .trust-clouds {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
  /* Two masks multiplied together: one runs the band off both sides of the
     page, one feathers the top edge. The top feather matters — a cloud that
     crosses the section boundary would otherwise be sliced off in a dead
     straight line by the overflow clip, which is very visible against the
     hero's cloud bank directly above. */
  -webkit-mask-image:
    linear-gradient(90deg,  transparent 0%, #000 9%, #000 91%, transparent 100%),
    linear-gradient(180deg, transparent 0%, #000 11%, #000 100%);
          mask-image:
    linear-gradient(90deg,  transparent 0%, #000 9%, #000 91%, transparent 100%),
    linear-gradient(180deg, transparent 0%, #000 11%, #000 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
/* Whisper of ivory under the wording only — the cloud band sits above it,
   around the bubbles, so the captions stay on clean paper. */
.trust--bubbles::before {
  content: '';
  position: absolute;
  inset: 46% 0 0 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(251, 247, 242, 0) 0%,
    rgba(251, 247, 242, 0.72) 34%,
    rgba(251, 247, 242, 0.88) 100%);
}
.trust--bubbles .trust-cloud {
  position: absolute;
  object-fit: cover;
  opacity: 0.55;
  --cloud-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100' preserveAspectRatio='none'><path d='M 30 70 C 12 70 6 52 22 45 C 8 30 30 15 50 25 C 60 5 90 5 100 25 C 115 8 145 15 148 35 C 168 32 180 50 170 62 C 182 68 178 82 165 82 C 158 92 130 92 122 82 C 108 92 82 92 72 82 C 62 92 40 90 32 82 C 20 84 12 78 30 70 Z' fill='white'/></svg>");
  -webkit-mask-image: var(--cloud-mask);
          mask-image: var(--cloud-mask);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  /* Blur dissolves the individual silhouettes into one soft mass — without
     it you can count the six cloud shapes. */
  /* No blur and no recolour — pixel-for-pixel the same treatment as the hero
     clouds above, so the photo's cloud texture survives and the two bands
     look like one sky. Sizes are in px (not %) for the same reason: blown up
     to half the section width the photo turns into a flat pink shape. */
  animation: cloudDrift 24s ease-in-out infinite;
  will-change: transform;
}
/* Minimal: three clouds sitting in the GAPS between the four bubbles
   (bubbles land at roughly 18%, 39%, 61% and 82% across), so every piece of
   glass reads against clean paper. */
.trust--bubbles .trust-cloud--1 { top: 12%; left:  -7%; width: 250px; height: 125px; opacity: 0.16; animation-delay: 0s; }
.trust--bubbles .trust-cloud--3 { top:  2%; left:  87%; width: 150px; height:  75px; opacity: 0.12; animation-delay: 6s; animation-duration: 27s; }
.trust--bubbles .trust-cloud--5 { top: 28%; right: -7%; width: 230px; height: 115px; opacity: 0.15; animation-delay: 8s; }

/* --- Layout: centred column per item ------------------------------------
   styles.css line ~4638 forces `display:flex !important` and
   `align-items:flex-start !important` on .trust-item, and
   `align-self:flex-start !important` + `margin-top:2px !important` on
   .trust-icon. Those must be beaten with !important of our own. */
.trust--bubbles .trust-grid {
  gap: 0;
  align-items: stretch !important;
}
.trust--bubbles .trust-item {
  display: flex !important;
  flex-direction: column;
  align-items: center !important;
  text-align: center;
  padding: 0 clamp(14px, 2.4vw, 34px);
  position: relative;
  z-index: 1;
}
/* Hairline between items, starting below the bubbles so it only divides
   the wording — matches the reference layout. */
.trust--bubbles .trust-item + .trust-item::before {
  content: '';
  position: absolute;
  left: 0;
  top: 52%;
  bottom: 4%;
  width: 1px;
  background: linear-gradient(180deg,
    transparent,
    rgba(122, 115, 136, 0.22) 22%,
    rgba(122, 115, 136, 0.22) 78%,
    transparent);
}

/* --- The glass bubble ---------------------------------------------------
   Same three-layer glass recipe as the hero bubbles: white highlight at
   28%/24% for the light source, a soft bounce highlight bottom-right, and
   a barely-there tint so it stays clear against the clouds. The rim is a
   1.5px inset ring — that is what makes it read as blown glass rather than
   a flat circle. */
.trust--bubbles .trust-icon {
  width:  clamp(80px, 8.6vw, 116px);
  height: clamp(80px, 8.6vw, 116px);
  border-radius: 50%;
  align-self: center !important;
  margin: 0 0 clamp(14px, 1.7vw, 24px) !important;
  /* Nudged up and to the right, as requested */
  transform: translate(9px, -8px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Icons in the footer ink purple, matching the Book a Visit button */
  color: var(--ink);
  background:
    radial-gradient(circle at 28% 24%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.34) 22%,
      rgba(255, 255, 255, 0)    52%),
    radial-gradient(circle at 72% 78%,
      rgba(255, 255, 255, 0.44) 0%,
      rgba(255, 255, 255, 0)    46%),
    linear-gradient(135deg,
      rgba(244, 220, 232, 0.22) 0%,
      rgba(214, 222, 240, 0.24) 100%);
  -webkit-backdrop-filter: blur(3px) saturate(1.06);
          backdrop-filter: blur(3px) saturate(1.06);
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, 0.75),
    inset -5px -5px 14px rgba(180, 170, 210, 0.16),
    inset 7px 7px 16px rgba(255, 255, 255, 0.48),
    0 14px 34px -14px rgba(180, 160, 190, 0.42);
  animation: trustBubbleFloat 13s ease-in-out infinite;
  will-change: transform;
}
/* Stagger so the four never bob in unison */
.trust--bubbles .trust-item:nth-child(1) .trust-icon { animation-duration: 13s; animation-delay: 0s;   }
.trust--bubbles .trust-item:nth-child(2) .trust-icon { animation-duration: 16s; animation-delay: 1.4s; }
.trust--bubbles .trust-item:nth-child(3) .trust-icon { animation-duration: 14s; animation-delay: 2.8s; }
.trust--bubbles .trust-item:nth-child(4) .trust-icon { animation-duration: 17s; animation-delay: 0.7s; }

/* The travelling shine — a narrow white band sweeping across the glass.
   It rides an ::after clipped to the circle, so it never spills outside. */
.trust--bubbles .trust-icon::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background: linear-gradient(105deg,
    transparent 38%,
    rgba(255, 255, 255, 0.62) 48%,
    rgba(255, 255, 255, 0.20) 55%,
    transparent 64%);
  background-size: 260% 100%;
  background-repeat: no-repeat;
  animation: trustBubbleShine 6.5s ease-in-out infinite;
  pointer-events: none;
}
.trust--bubbles .trust-item:nth-child(2) .trust-icon::after { animation-delay: 1.6s; }
.trust--bubbles .trust-item:nth-child(3) .trust-icon::after { animation-delay: 3.2s; }
.trust--bubbles .trust-item:nth-child(4) .trust-icon::after { animation-delay: 4.8s; }

.trust--bubbles .trust-icon svg {
  width:  38%;
  height: 38%;
  position: relative;
  z-index: 1;
  /* Slightly finer stroke — ink is much denser than the old gold, so the
     same weight would read as heavy. */
  stroke-width: 1.05;
}
/* The blue variant loses its blue here — all four icons go warm gold so the
   row reads as one set, as in the reference. */
.trust--bubbles .trust-icon.blue {
  color: var(--ink);
  background:
    radial-gradient(circle at 28% 24%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.34) 22%,
      rgba(255, 255, 255, 0)    52%),
    radial-gradient(circle at 72% 78%,
      rgba(255, 255, 255, 0.44) 0%,
      rgba(255, 255, 255, 0)    46%),
    linear-gradient(135deg,
      rgba(244, 220, 232, 0.22) 0%,
      rgba(214, 222, 240, 0.24) 100%);
  border-color: transparent;
}

@keyframes trustBubbleFloat {
  0%, 100% { transform: translate( 9px,  -8px) scale(1);    }
  30%      { transform: translate(13px, -16px) scale(1.02); }
  60%      { transform: translate( 5px, -12px) scale(1.01); }
  80%      { transform: translate(11px,  -4px) scale(1.02); }
}
@keyframes trustBubbleShine {
  0%,  8%  { background-position: 150% 0; }
  46%      { background-position: -50% 0; }
  100%     { background-position: -50% 0; }
}

/* --- Typography: serif title, sentence-case caption ----------------------
   To keep the old uppercase letterspaced caption instead, delete the
   `text-transform` and `letter-spacing` lines from .trust-item span below. */
.trust--bubbles .trust-item strong {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(16px, 1.5vw, 20px);
  letter-spacing: 0.005em;
  color: var(--ink);
  margin-bottom: 8px;
}
.trust--bubbles .trust-item span {
  font-size: clamp(12.5px, 1.05vw, 14px);
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.65;
  color: var(--ink-soft);
  font-weight: 400;
  /* Widened from 26ch: with hyphenation off, a justified column needs more
     room or the word gaps blow out. */
  max-width: 30ch;
  /* Justified body, last line centred under the bubble. Hyphenation is
     explicitly OFF — it was splitting "sterilised" across two lines. */
  text-align: justify;
  text-align-last: center;
  -webkit-hyphens: none;
          hyphens: none;
}

/* --- Responsive ---------------------------------------------------------- */
@media (max-width: 900px) {
  .trust--bubbles .trust-grid { grid-template-columns: repeat(2, 1fr); gap: 40px 0; }
  .trust--bubbles .trust-item:nth-child(odd)::before { display: none; }
}
@media (max-width: 560px) {
  .trust--bubbles .trust-grid { grid-template-columns: 1fr; gap: 34px; }
  .trust--bubbles .trust-item::before { display: none; }
  .trust--bubbles .trust-icon { width: 86px; height: 86px; }
  .trust--bubbles .trust-cloud { opacity: 0.10; }
}
@media (max-width: 820px) {
  .trust--bubbles .trust-icon {
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .trust--bubbles .trust-icon,
  .trust--bubbles .trust-icon::after,
  .trust--bubbles .trust-cloud { animation: none; }
}


/* --------------------------------------------------------------------------
   CLOUD SILHOUETTES — four different outlines.
   Every cloud used to share one path, so the eye picked up the repeat and the
   band looked stamped rather than natural. Cycling four shapes at different
   sizes fixes that. Assign with .cloud-a … .cloud-d.
   -------------------------------------------------------------------------- */
.cloud-a { --cloud-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100' preserveAspectRatio='none'><path d='M 30 70 C 12 70 6 52 22 45 C 8 30 30 15 50 25 C 60 5 90 5 100 25 C 115 8 145 15 148 35 C 168 32 180 50 170 62 C 182 68 178 82 165 82 C 158 92 130 92 122 82 C 108 92 82 92 72 82 C 62 92 40 90 32 82 C 20 84 12 78 30 70 Z' fill='white'/></svg>"); }
.cloud-b { --cloud-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100' preserveAspectRatio='none'><path d='M 40 74 C 20 74 12 54 30 46 C 22 22 54 8 74 24 C 86 2 120 4 128 26 C 152 12 178 30 170 52 C 186 58 184 78 164 79 C 152 91 120 91 110 80 C 96 92 64 90 54 79 C 44 85 32 83 40 74 Z' fill='white'/></svg>"); }
.cloud-c { --cloud-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100' preserveAspectRatio='none'><path d='M 14 68 C 2 68 0 52 16 47 C 12 33 32 24 46 34 C 56 18 84 18 94 34 C 110 22 136 28 142 44 C 164 39 184 48 188 62 C 198 66 196 78 180 79 C 160 88 128 88 114 80 C 98 88 68 88 54 80 C 38 86 20 80 14 68 Z' fill='white'/></svg>"); }
.cloud-d { --cloud-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 100' preserveAspectRatio='none'><path d='M 54 76 C 36 76 30 56 48 48 C 40 26 68 12 88 26 C 100 6 132 10 138 32 C 160 30 172 50 158 62 C 170 70 164 82 148 81 C 132 92 102 92 90 80 C 76 90 60 86 54 76 Z' fill='white'/></svg>"); }


/* ==========================================================================
   7. "COMING SOON" — 3D gold ribbon
   --------------------------------------------------------------------------
   Overrides the pill in styles.css. Scoped to the home hero so the badge
   elsewhere is untouched.
   ========================================================================== */

.hero--bubbles .coming-soon-badge--gold {
  /* Ribbon silhouette: a V notched into each end, the way a real banner tail
     is cut. clip-path rather than borders so the notch follows the metal. */
  border-radius: 3px;
  clip-path: polygon(
    0 0,
    100% 0,
    calc(100% - 22px) 50%,
    100% 100%,
    0 100%,
    22px 50%);
  padding: 16px 52px 16px 48px;

  /* Brighter, higher-contrast foil than the flat pill. The extra stops are
     what make it read as polished metal: dark bronze edge, a hot near-white
     highlight band, then back down to bronze. */
  background:
    /* barrel shading — this is the 3D. Light along the top third, shadow
       gathering at the bottom, so the strip looks rolled rather than flat. */
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.46) 0%,
      rgba(255, 252, 232, 0.18) 18%,
      rgba(255, 255, 255, 0)    40%,
      rgba(72, 48, 12, 0.07)    70%,
      rgba(72, 48, 12, 0.20)    100%),
    /* Nine stops: bronze edge -> warm gold -> hot near-white highlight ->
       back down. The highlight band is what makes it read as polished rather
       than painted; the sweep animation slides this whole gradient. */
    linear-gradient(100deg,
      #7A5722  0%,
      #B98F42  9%,
      #E9D189 21%,
      #FFFAE6 34%,
      #F6E4AC 43%,
      #E0BE6E 56%,
      #C9A052 70%,
      #A57C36 85%,
      #7A5722 100%);
  background-size: 100% 100%, 210% 100%;

  box-shadow:
    inset 0  2px 0 rgba(255, 252, 232, 0.85),   /* top foil edge   */
    inset 0 -2px 0 rgba(52, 34, 8, 0.42),       /* bottom foil edge*/
    inset  3px 0 0 rgba(255, 250, 224, 0.20),
    inset -3px 0 0 rgba(52, 34, 8, 0.20);

  /* clip-path crops box-shadows, so the lift has to be a drop-shadow filter —
     it follows the notched outline instead of the old rectangle. */
  filter:
    drop-shadow(0 10px 16px rgba(74, 52, 16, 0.34))
    drop-shadow(0 2px 3px rgba(74, 52, 16, 0.30));

  animation:
    goldShineSweep 4.5s ease-in-out infinite,
    ribbonLift 6s ease-in-out infinite;
}

/* Folded tails behind the ribbon — the small darker flaps that make a banner
   look like it is wrapping around something. */
.hero--bubbles .coming-soon-badge--gold {
  position: relative;
  z-index: 2;
}

.hero--bubbles .coming-soon-badge--gold .cs-label {
  text-shadow:
    0 1px 0 rgba(255, 250, 224, 0.65),
    0 -1px 0 rgba(52, 34, 8, 0.28);
}

.hero--bubbles .coming-soon-badge--gold .cs-shine {
  /* Wider and brighter than the pill's sweep, so the metal actually flashes */
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.75) 50%,
    rgba(255, 255, 255, 0) 100%);
  width: 46%;
}

@keyframes ribbonLift {
  0%, 100% { transform: translateY(0);     }
  50%      { transform: translateY(-2px);  }
}

@media (max-width: 620px) {
  .hero--bubbles .coming-soon-badge--gold {
    padding: 13px 38px 13px 34px;
    font-size: 11.5px;
    clip-path: polygon(0 0, 100% 0, calc(100% - 15px) 50%, 100% 100%, 0 100%, 15px 50%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero--bubbles .coming-soon-badge--gold { animation: none; }
}


/* ==========================================================================
   8. HERO CAPTION — cursive
   The eyebrow above the headline was uppercase Inter with wide tracking.
   Script needs the opposite treatment: no uppercasing (capitals destroy the
   joins between letters), no letter-spacing (it pulls the joins apart), and a
   larger size, because cursive reads smaller than a sans at the same px.
   Requires Dancing Script in the <head> font link.
   ========================================================================== */
.hero--bubbles .hero-content > .eyebrow {
  font-family: 'Dancing Script', 'Allura', cursive;
  /* Smaller than the first pass — a script at headline scale competes with
     the headline itself. Dancing Script ships no true italic file, so this
     is a synthesised oblique; on a cursive that reads as extra slant rather
     than as fake italic, which is what we want here. */
  font-style: italic;
  font-size: clamp(17px, 1.5vw, 21px);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.35;
  color: var(--cloud-blue-deep);
  margin-bottom: 16px;
  display: block;
}
/* styles.css draws a short rule before the eyebrow text; it reads as a
   stray dash next to script, so it goes. */
.hero--bubbles .hero-content > .eyebrow::before,
.hero--bubbles .hero-content > .eyebrow::after {
  display: none;
}


/* ==========================================================================
   9. HERO BACKGROUND — two soft spots instead of four
   --------------------------------------------------------------------------
   styles.css paints five overlapping 330px radial drops behind the wording
   (pink NW, blue NE, blue SW, pink SE, plus a mauve mix in the middle). Where
   they meet they blend into a busy pink-blue-pink-blue wash. This replaces
   the whole stack with two: pink upper-left, blue lower-right, sized and
   placed to sit within the text block rather than across the section.
   ========================================================================== */
.hero--bubbles {
  background:
    /* Pink pom-pom, upper-left behind the headline.
       The falloff is spelled out in twelve closely-spaced stops tracing an
       ease-out curve. Three or four stops looks like it should be enough, but
       the browser interpolates LINEARLY between stops, so each one becomes a
       visible ring wherever the rate of fade changes — that banding was the
       "line" running through the ball. Many small steps make the change
       imperceptible: solid at the centre, dissolving to nothing at the rim.

       `closest-side` rather than a fixed px radius: it sets the radius to the
       distance from the centre to the nearest edge of the hero, so the fade
       reaches zero exactly AT that edge. A fixed radius that overshoots gets
       chopped by the box and leaves a straight line across the design — which
       is what kept reappearing at the top and bottom of the hero. This version
       re-solves itself at every viewport size. */
    /* 25 Aug 2026 — anchored on the word "Malaysia", and a third darker.
       The Y is in PIXELS, not per cent: the hero is a screen tall now, so its
       height changes with the window while the copy always begins the same
       distance below the bar. A percentage drifted 30px between a 887px and a
       1080px screen; 235px lands on the headline at every size. */
    radial-gradient(circle closest-side at 14% 235px,
      rgba(244, 165, 184, 0.401) 0%,
      rgba(244, 165, 184, 0.374) 10%,
      rgba(244, 165, 184, 0.337) 20%,
      rgba(244, 165, 184, 0.293) 30%,
      rgba(244, 165, 184, 0.240) 40%,
      rgba(244, 165, 184, 0.189) 50%,
      rgba(244, 165, 184, 0.136) 60%,
      rgba(244, 165, 184, 0.088) 70%,
      rgba(244, 165, 184, 0.048) 80%,
      rgba(244, 165, 184, 0.024) 88%,
      rgba(244, 165, 184, 0.008) 94%,
      rgba(244, 165, 184, 0.000) 100%),
    /* Blue pom-pom, lower-right of the text block, on the diagonal */
    /* …and its partner just past the end of the description, stepped down and
       out to the right (25 Aug 2026). Note the radius is `closest-side`, so
       the further down it goes the smaller it gets — its radius is the
       distance to the nearest edge of the hero. That is deliberate: a fixed
       radius that overshoots the box gets sliced off square by the background
       painting area and draws a ruled line across the page. 470px is as low as
       it can sit and still read as a soft ball. */
    radial-gradient(circle closest-side at 36% 470px,
      rgba(155, 180, 222, 0.359) 0%,
      rgba(155, 180, 222, 0.335) 10%,
      rgba(155, 180, 222, 0.301) 20%,
      rgba(155, 180, 222, 0.263) 30%,
      rgba(155, 180, 222, 0.216) 40%,
      rgba(155, 180, 222, 0.169) 50%,
      rgba(155, 180, 222, 0.122) 60%,
      rgba(155, 180, 222, 0.078) 70%,
      rgba(155, 180, 222, 0.043) 80%,
      rgba(155, 180, 222, 0.022) 88%,
      rgba(155, 180, 222, 0.007) 94%,
      rgba(155, 180, 222, 0.000) 100%),
    var(--ivory);
}
/* The pulsing gold speck layer belongs to the four-drop treatment; without
   its backdrop it just reads as dust on the screen. */
.hero--bubbles::before { display: none; }

@media (max-width: 900px) {
  /* Stacked layout — bring both spots inward so they stay behind the copy */
  /* Mobile keeps FIXED radii rather than closest-side. Once the layout
     stacks, the hero is ~980px tall but only ~390px wide, so closest-side
     measures to the nearest SIDE — collapsing each ball to about 95px and
     making the blue one all but disappear. Vertical clipping is what leaves
     a visible line, and at this height there is plenty of room; horizontal
     bleed just runs off the screen edge, which nobody sees. */
  .hero--bubbles {
    background:
      /* Two quiet accents, not two washes. They used to be 170px and 160px
         across, which put a tinted field behind almost every line of the
         copy; at this size each one reads as a soft spot of colour and the
         type sits on clean ivory. They are also drawn in towards each other
         and stacked more steeply — the pink swings out to the left and the
         blue to the right, and each drops a little further from the other,
         so the line between them still falls at about 50 degrees and the
         pair reads as a diagonal rather than a level pair. Both still stop
         short of the photograph.

         25 Aug 2026 — the hero was reordered on phones (ribbon, picture, then
         the words), so 14%/38% now sits behind the PICTURE. Both balls moved
         down over the copy: 24%/66% and 72%/90%. The offsets between them are
         unchanged (48% across, 24% down), so the pair still reads on the same
         ~50-degree diagonal, and each is a little larger so the wash actually
         covers the description. */
      /* 25 Aug 2026 — matched to the desktop treatment: a third darker, a
         little larger, and anchored on the word "Malaysia". Measured across
         390 / 430 / 600 / 766 / 880px, the headline's first word sits at a
         remarkably steady 25% across and 59-64% down, so percentages hold
         here (unlike the desktop hero, where the box is a screen tall and the
         Y had to be pinned in pixels). */
      radial-gradient(circle 140px at 25% 61%,
        rgba(244, 165, 184, 0.341) 0%,
        rgba(244, 165, 184, 0.317) 10%,
        rgba(244, 165, 184, 0.286) 20%,
        rgba(244, 165, 184, 0.248) 30%,
        rgba(244, 165, 184, 0.205) 40%,
        rgba(244, 165, 184, 0.161) 50%,
        rgba(244, 165, 184, 0.116) 60%,
        rgba(244, 165, 184, 0.075) 70%,
        rgba(244, 165, 184, 0.041) 80%,
        rgba(244, 165, 184, 0.020) 88%,
        rgba(244, 165, 184, 0.007) 94%,
        rgba(244, 165, 184, 0.000) 100%),
      /* …and its partner out at the RIGHT-HAND EDGE, level with the end of the
         description (25 Aug 2026, Winnie: "place the blue one at the right
         side near the screen end"). Its radius is wider than the margin it has
         left, so it runs off the edge of the screen — which is the point: it
         reads as light coming in from the side rather than as a ball. */
      /* 86%, not 79%: on a 390x971 hero the pink is 246px to the left, so the
         blue needs ~246px of drop for the line between them to read as a true
         45-degree diagonal rather than a shallow lean. 25% of the hero's
         height is that distance. */
      radial-gradient(circle 125px at 88% 86%,
        rgba(155, 180, 222, 0.400) 0%,
        rgba(155, 180, 222, 0.371) 10%,
        rgba(155, 180, 222, 0.336) 20%,
        rgba(155, 180, 222, 0.292) 30%,
        rgba(155, 180, 222, 0.240) 40%,
        rgba(155, 180, 222, 0.188) 50%,
        rgba(155, 180, 222, 0.136) 60%,
        rgba(155, 180, 222, 0.088) 70%,
        rgba(155, 180, 222, 0.049) 80%,
        rgba(155, 180, 222, 0.024) 88%,
        rgba(155, 180, 222, 0.008) 94%,
        rgba(155, 180, 222, 0.000) 100%),
      var(--ivory);
  }
}


/* ==========================================================================
   10. HERO BUTTONS — squared modern shape, ink fill, dreamy hover
   ========================================================================== */

/* Both buttons: soft-cornered rectangle instead of the 999px pill. */
.hero--bubbles .hero-cta-group .btn {
  border-radius: 10px;
  padding: 17px 30px;
  transition:
    background 0.45s var(--ease),
    color 0.45s var(--ease),
    border-color 0.45s var(--ease),
    transform 0.45s var(--ease),
    box-shadow 0.45s var(--ease);
}

/* ---- Book a Visit — solid ink purple, the same tone as the footer ------- */
.hero--bubbles .hero-cta-group .btn-gold {
  background: var(--ink);          /* #2A2438 — footer background */
  background-image: none;
  color: var(--ivory);
  border: none;
  box-shadow: 0 10px 24px -12px rgba(42, 36, 56, 0.55);
}
.hero--bubbles .hero-cta-group .btn-gold:hover,
.hero--bubbles .hero-cta-group .btn-gold:focus-visible {
  background: #3A3350;             /* one step up, so the press still reads */
  color: var(--ivory);
  transform: translateY(-3px);
  box-shadow: 0 16px 32px -12px rgba(42, 36, 56, 0.55);
}
.hero--bubbles .hero-cta-group .btn-gold .arrow { color: inherit; }

/* ---- Discover Baby Angels — outline that fills with a dreamy wash -------
   The gradient lives on a ::before rather than on the button itself, because
   background-image cannot be transitioned; opacity can. The label is wrapped
   in .btn-label so it keeps painting above that layer. */
.hero--bubbles .hero-cta-group .btn-outline {
  position: relative;
  overflow: hidden;
  background: transparent;
  border: 1px solid rgba(42, 36, 56, 0.55);
  color: var(--ink);
}
.hero--bubbles .hero-cta-group .btn-outline::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  /* Mother-of-pearl, in three layers. A single linear ramp reads flat and
     cheap no matter how nice the colours are — the depth comes from the two
     light sources sitting on top of it:
       1. a white sheen falling in from the upper-left
       2. a warm champagne glow rising from the lower-right
       3. the pink -> orchid -> periwinkle body underneath
     The pinks are also pulled back from the earlier saturated #F4A5B8 to a
     dustier rose, which is what stops it looking like a highlighter. */
  background:
    radial-gradient(ellipse 85% 150% at 10% -25%,
      rgba(255, 255, 255, 0.86) 0%,
      rgba(255, 255, 255, 0.36) 32%,
      rgba(255, 255, 255, 0) 62%),
    radial-gradient(ellipse 75% 140% at 90% 125%,
      rgba(255, 229, 214, 0.55) 0%,
      rgba(255, 229, 214, 0.18) 38%,
      rgba(255, 229, 214, 0) 68%),
    /* Same hue ramp as the active nav link (HOME), which runs
       #D47896 -> #C08FB4 -> #8FA3C9 left to right, but lifted in lightness so
       it reads as a soft wash behind dark text rather than a saturated fill. */
    linear-gradient(90deg,
      #F7CFDC  0%,
      #F0BFD0 22%,
      #E3C4DE 45%,
      #CFD0E7 72%,
      #C2D2EC 100%);
  background-size: 100% 100%, 100% 100%, 165% 100%;
  background-position: 0% 50%, 0% 50%, 0% 50%;
  opacity: 0;
  transition: opacity 0.5s var(--ease), background-position 1.4s var(--ease);
  pointer-events: none;
}
.hero--bubbles .hero-cta-group .btn-outline .btn-label {
  position: relative;
  z-index: 1;
}
.hero--bubbles .hero-cta-group .btn-outline:hover,
.hero--bubbles .hero-cta-group .btn-outline:focus-visible,
.hero--bubbles .hero-cta-group .btn-outline:active {
  border-color: rgba(255, 255, 255, 0.75);
  color: var(--ink);
  transform: translateY(-3px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),        /* top glass edge */
    0 18px 36px -16px rgba(150, 132, 178, 0.50),
    0 4px 10px  -6px rgba(150, 132, 178, 0.28);
}
.hero--bubbles .hero-cta-group .btn-outline:hover::before,
.hero--bubbles .hero-cta-group .btn-outline:focus-visible::before,
.hero--bubbles .hero-cta-group .btn-outline:active::before {
  opacity: 1;
  /* Only the colour body drifts; the two light layers stay put, so the sheen
     reads as a fixed light source rather than sliding across. */
  background-position: 0% 50%, 0% 50%, 100% 50%;
}

@media (prefers-reduced-motion: reduce) {
  .hero--bubbles .hero-cta-group .btn,
  .hero--bubbles .hero-cta-group .btn-outline::before { transition: none; }
  .hero--bubbles .hero-cta-group .btn:hover { transform: none; }
}


/* ==========================================================================
   11. OUR VISION / OUR MISSION — full page width
   --------------------------------------------------------------------------
   styles.css caps .philosophy-brief-inner at 880px, while the hero and trust
   strip both run to --max-width (1320px). That 440px difference is why this
   block looked inset from everything above it. Opt in with the
   `philosophy-brief--wide` class so the same component keeps its narrow
   measure anywhere else it is used.
   ========================================================================== */
.philosophy-brief--wide .philosophy-brief-inner {
  max-width: var(--max-width);
}
.philosophy-brief--wide .photo-text-grid {
  max-width: none;
  gap: clamp(40px, 6vw, 90px);
}
/* The paragraphs were capped at 520px inside a now-wider column, which would
   just move the slimness in one level. Let them fill the column instead —
   at this width a line lands around 60–70 characters, which is comfortable. */
.philosophy-brief--wide .text-column .body-text,
.philosophy-brief--wide .text-column .lede {
  max-width: 100%;
}


/* ==========================================================================
   12. MOBILE FIXES
   ========================================================================== */

/* --- Trust strip clouds on a stacked layout -----------------------------
   Once the strip becomes one column the bubbles run down the CENTRE, so the
   desktop cloud positions land squarely behind them. On phones the clouds
   move out to the left and right margins and sit low, wrapping the glass
   rather than hiding behind it. */
@media (max-width: 560px) {
  .trust--bubbles .trust-cloud--1 {
    top: auto; bottom: 12%; left: -34%; right: auto;
    width: 210px; height: 105px; opacity: 0.15;
  }
  .trust--bubbles .trust-cloud--3 {
    top: auto; bottom: 40%; left: auto; right: -36%;
    width: 190px; height: 95px; opacity: 0.13;
  }
  .trust--bubbles .trust-cloud--5 {
    top: auto; bottom: -2%; right: -30%; left: auto;
    width: 200px; height: 100px; opacity: 0.14;
  }
}

/* --- Walkthrough video card ---------------------------------------------
   At 16:9 the card is only ~220px tall on a phone, and a 96px play button
   plus a 32px gap plus the caption simply does not fit — so they collided.
   A taller ratio and a smaller button give everything room. */
@media (max-width: 620px) {
  .walkthrough .video-placeholder { aspect-ratio: 4 / 3; }
  .walkthrough .video-overlay {
    gap: 16px;
    padding: 0 20px;
  }
  .walkthrough .play-icon {
    width: 62px;
    height: 62px;
  }
  /* styles.css (~line 3014) hard-codes the halo ring to `width/height: 72px`
     on mobile while ALSO leaving `inset: -1px` on it. Explicit dimensions plus
     a top/left offset over-constrain the box: the ring keeps its own 72px size
     but anchors to the button's top-left corner, so it hangs off the
     bottom-right instead of sitting concentric. Handing size back to `inset`
     re-centres it on the button at whatever size the button is. */
  .walkthrough .play-icon::before {
    inset: -1px;
    width: auto;
    height: auto;
  }
  .walkthrough .play-icon svg { width: 22px; height: 22px; }
  .walkthrough .video-caption h3 { font-size: clamp(24px, 7vw, 32px); }
}


/* ==========================================================================
   14. WALKTHROUGH CARD — neutral shadow
   styles.css gives .video-placeholder a rose glow:
     0 40px 80px -30px rgba(212, 120, 150, 0.4)
   Against the ivory page that spreads a visible pink haze under the card.
   Swapped for a neutral ink shadow of the same softness.
   ========================================================================== */
.walkthrough .video-placeholder {
  /* Wide and shallow. The earlier 34px offset / -36px spread version ended
     abruptly about 70px below the card, and that shadow's own outer edge was
     the faint horizontal line running across the page above the book. */
  box-shadow:
    0 18px 90px -46px rgba(42, 36, 56, 0.26),
    0 0 0 1px rgba(42, 36, 56, 0.05);
}


/* ==========================================================================
   15. OUR VISION / OUR MISSION — open book spread
   --------------------------------------------------------------------------
   Two pages hinged at a centre spine. Both start folded back in 3D and swing
   open as the section scrolls into view, using the site's existing `.reveal`
   → `.in` observer in script.js as the trigger.

   The `.reveal` class sits on the OUTER .book and the 3D transforms on the
   .book-page children — deliberately different elements, because styles.css
   animates transform on `.reveal.in` and the two would otherwise fight.
   ========================================================================== */
.book {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: stretch;
  position: relative;
  /* The depth of the "room" the book sits in. Too little and the open pages
     look sheared rather than hinged. */
  perspective: 2400px;
  perspective-origin: 50% 42%;
}

/* Soft pool of light under the whole book */
.book-glow {
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: -18px;
  height: 46px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
    rgba(42, 36, 56, 0.20) 0%, rgba(42, 36, 56, 0.07) 45%, rgba(42, 36, 56, 0) 72%);
  filter: blur(14px);
  pointer-events: none;
}

.book-page {
  position: relative;
  padding: clamp(32px, 3.6vw, 58px) clamp(28px, 3.2vw, 50px) clamp(46px, 4vw, 64px);
  text-align: left;
  /* Paper: warm cream, very slightly brighter at the outer edge than at the
     gutter, which is how a real open page catches light. */
  background:
    linear-gradient(90deg,
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, 0.55) 60%,
      rgba(255, 255, 255, 0.85) 100%),
    linear-gradient(180deg, #FFFCF9 0%, #FBF5EE 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 22px 44px -30px rgba(42, 36, 56, 0.34);
  backface-visibility: hidden;
  transition: transform 1.15s cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}

/* Hinge each page at the spine. The covers start folded UP TOWARD the reader,
   the way a closed book sits before you open it, and swing down flat — the
   pages used to start folded away behind the spine, which read as the book
   closing backwards rather than opening. */
.book-page--left {
  transform-origin: right center;
  transform: rotateY(74deg);
  border-radius: 10px 2px 2px 10px;
}
.book-page--right {
  transform-origin: left center;
  transform: rotateY(-74deg);
  border-radius: 2px 10px 10px 2px;
  /* mirror the paper sheen so both pages light from the gutter outward */
  background:
    linear-gradient(270deg,
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, 0.55) 60%,
      rgba(255, 255, 255, 0.85) 100%),
    linear-gradient(180deg, #FFFCF9 0%, #FBF5EE 100%);
}
/* Opened. Staggered a beat apart so it reads as a book being opened by hand
   rather than two panels snapping flat together. */
.book.in .book-page--left  { transform: rotateY(0deg); transition-delay: 0.10s; }
.book.in .book-page--right { transform: rotateY(0deg); transition-delay: 0.22s; }

/* Stack of page edges along each outer edge — this is most of what makes it
   read as a bound book rather than two rectangles. */
.book-edge {
  position: absolute;
  top: 8px;
  bottom: 8px;
  width: 7px;
  pointer-events: none;
  background: repeating-linear-gradient(90deg,
    rgba(42, 36, 56, 0.10) 0px, rgba(42, 36, 56, 0.10) 1px,
    rgba(255, 255, 255, 0.85) 1px, rgba(255, 255, 255, 0.85) 3px);
}
.book-page--left  .book-edge { left: -7px;  border-radius: 4px 0 0 4px; }
.book-page--right .book-edge { right: -7px; border-radius: 0 4px 4px 0; }

/* Gutter — the shadow that falls into the fold, darkest at the spine */
.book-page--left::after,
.book-page--right::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: clamp(26px, 3vw, 46px);
  pointer-events: none;
}
.book-page--left::after {
  right: 0;
  background: linear-gradient(90deg,
    rgba(42, 36, 56, 0) 0%, rgba(42, 36, 56, 0.05) 55%, rgba(42, 36, 56, 0.13) 100%);
}
.book-page--right::after {
  left: 0;
  background: linear-gradient(270deg,
    rgba(42, 36, 56, 0) 0%, rgba(42, 36, 56, 0.05) 55%, rgba(42, 36, 56, 0.13) 100%);
}

/* Spine with the logo mark set into it */
.book-spine {
  position: relative;
  width: clamp(28px, 3vw, 46px);
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(90deg, #F3EAE1 0%, #E9DDD1 50%, #F3EAE1 100%);
  box-shadow:
    inset 3px 0 6px -3px rgba(42, 36, 56, 0.34),
    inset -3px 0 6px -3px rgba(42, 36, 56, 0.34);
}
.book-spine img {
  width: clamp(20px, 2.1vw, 30px);
  height: auto;
  opacity: 0.85;
  filter: drop-shadow(0 1px 1px rgba(255, 255, 255, 0.8));
}

.book .eyebrow { margin-bottom: 20px; }

.book-statement {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(26px, 2.9vw, 41px);
  letter-spacing: -0.012em;
  line-height: 1.24;
  color: var(--ink);
  margin: 0 0 20px;
  text-align: left;
}
.book-statement--sm { font-size: clamp(21px, 2.2vw, 30px); line-height: 1.34; }
.book-statement em { font-style: normal; color: var(--gold-deep); }
.book-page--right .book-statement em { color: var(--cloud-blue-deep); }

.book-support {
  font-size: 16.5px;
  line-height: 1.75;
  color: var(--ink-soft);
  margin: 0;
  text-align: left;
}

/* Corner curl — lifts on hover like a page you are about to turn */
.book-curl {
  position: absolute;
  bottom: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  transition: border-width 0.45s var(--ease), filter 0.45s var(--ease);
  filter: drop-shadow(-2px -2px 3px rgba(42, 36, 56, 0.16));
}
.book-page--left .book-curl {
  left: 0;
  border-bottom: 0 solid transparent;
  border-right: 0 solid #F1E7DC;
}
.book-page--right .book-curl {
  right: 0;
  border-bottom: 0 solid transparent;
  border-left: 0 solid #F1E7DC;
}
.book-page--left:hover  .book-curl { border-bottom-width: 34px; border-right-width: 34px; }
.book-page--right:hover .book-curl { border-bottom-width: 34px; border-left-width: 34px; }

/* --- Responsive ---------------------------------------------------------- */
@media (max-width: 900px) {
  /* Stacked: the spine becomes a horizontal seam between the two pages and
     the hinge swings on the X axis so the "opening" still reads. */
  .book {
    grid-template-columns: 1fr;
    perspective: 1400px;
    perspective-origin: 50% 50%;
  }
  /* stacked on a phone the same rule applies: the free edge starts toward the
     reader and folds down, not away behind the spine */
  .book-page--left  { transform-origin: center bottom; transform: rotateX(-52deg); border-radius: 10px 10px 2px 2px; }
  .book-page--right { transform-origin: center top;    transform: rotateX(52deg);  border-radius: 2px 2px 10px 10px; }
  .book.in .book-page--left,
  .book.in .book-page--right { transform: rotateX(0deg); }
  .book-spine {
    width: auto;
    height: clamp(30px, 7vw, 44px);
    background: linear-gradient(180deg, #F3EAE1 0%, #E9DDD1 50%, #F3EAE1 100%);
    box-shadow:
      inset 0 3px 6px -3px rgba(42, 36, 56, 0.34),
      inset 0 -3px 6px -3px rgba(42, 36, 56, 0.34);
  }
  .book-edge { display: none; }
  .book-page--left::after {
    inset: auto 0 0 0; width: auto; height: 26px;
    background: linear-gradient(180deg, rgba(42,36,56,0) 0%, rgba(42,36,56,0.10) 100%);
  }
  .book-page--right::after {
    inset: 0 0 auto 0; width: auto; height: 26px;
    background: linear-gradient(0deg, rgba(42,36,56,0) 0%, rgba(42,36,56,0.10) 100%);
  }
  .book-curl { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .book-page { transition: none; transform: none !important; }
  .book-curl { transition: none; }
}


/* ==========================================================================
   16. BOOK BUBBLES — soap bubbles drifting around the spread
   Positioned OUTSIDE the page edges (negative offsets) so they never float
   over the wording, and pinned behind the pages so the paper stays clean.
   ========================================================================== */
.book-bubbles {
  position: absolute;
  inset: -70px -80px -60px;
  pointer-events: none;
  z-index: 0;
}
.bk-bubble {
  position: absolute;
  border-radius: 50%;
  /* Same clear-glass recipe as the hero's bubble-glass: bright sheen at
     28%/24%, a soft bounce highlight opposite it, and a white rim. */
  background:
    radial-gradient(circle at 28% 24%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.32) 22%,
      rgba(255, 255, 255, 0)    50%),
    radial-gradient(circle at 72% 78%,
      rgba(255, 255, 255, 0.42) 0%,
      rgba(255, 255, 255, 0)    46%),
    linear-gradient(135deg,
      rgba(244, 200, 216, 0.26) 0%,
      rgba(206, 216, 238, 0.28) 100%);
  box-shadow:
    inset 0 0 0 1.4px rgba(255, 255, 255, 0.70),
    inset -4px -4px 12px rgba(180, 170, 210, 0.14),
    inset 6px 6px 14px rgba(255, 255, 255, 0.42),
    0 10px 26px -12px rgba(180, 170, 210, 0.34);
  animation: bubbleFloat 17s ease-in-out infinite;
  will-change: transform;
}
/* Pink-leaning on the Vision side, blue-leaning on the Mission side */
.bk-bubble--1 { width: 78px; height: 78px; top: 2%;   left: -2%;  animation: bubbleFloat    19s ease-in-out infinite; animation-delay: 0s;
  background:
    radial-gradient(circle at 28% 24%, rgba(255,255,255,0.92) 0%, rgba(255,255,255,0.30) 22%, rgba(255,255,255,0) 50%),
    linear-gradient(135deg, rgba(242,184,204,0.38) 0%, rgba(226,166,190,0.28) 100%); }
.bk-bubble--2 { width: 40px; height: 40px; top: 24%;  left: 3%;   animation: bubbleFloatAlt 14s ease-in-out infinite; animation-delay: 1.6s; }
.bk-bubble--3 { width: 26px; height: 26px; bottom: 16%; left: 1%; animation: bubbleFloat    12s ease-in-out infinite; animation-delay: 3.4s; }
.bk-bubble--4 { width: 58px; height: 58px; bottom: 2%;  left: 26%; animation: bubbleFloatAlt 21s ease-in-out infinite; animation-delay: 2.2s; }
.bk-bubble--5 { width: 70px; height: 70px; top: 6%;   right: -1%; animation: bubbleFloatAlt 18s ease-in-out infinite; animation-delay: 0.8s;
  background:
    radial-gradient(circle at 28% 24%, rgba(255,255,255,0.92) 0%, rgba(255,255,255,0.30) 22%, rgba(255,255,255,0) 50%),
    linear-gradient(135deg, rgba(186,206,238,0.40) 0%, rgba(158,184,224,0.28) 100%); }
.bk-bubble--6 { width: 34px; height: 34px; bottom: 20%; right: 2%; animation: bubbleFloat    15s ease-in-out infinite; animation-delay: 4.2s; }
.bk-bubble--7 { width: 22px; height: 22px; top: 46%;  right: -1%; animation: bubbleFloatAlt 13s ease-in-out infinite; animation-delay: 5.0s; }

/* The pages sit above the bubbles so nothing drifts across the words */
.book-page, .book-spine { z-index: 1; }

@media (max-width: 900px) {
  .book-bubbles { inset: -40px -30px; }
  .bk-bubble--2, .bk-bubble--4, .bk-bubble--7 { display: none; }
}
@media (max-width: 820px) {
  .bk-bubble { -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bk-bubble { animation: none; }
}


/* ==========================================================================
   17. "STEP INSIDE" HEADER — matched to the rest of the page
   Same vocabulary used everywhere else on this page: a two-spot wash behind
   the words, clear glass bubbles drifting at the margins, and a hairline
   ornament with the four-point sparkle set into it.
   ========================================================================== */
.walkthrough-head--lux {
  position: relative;
  max-width: 900px;
  margin: 0 auto;
  padding: clamp(18px, 2.4vw, 34px) clamp(20px, 4vw, 60px) clamp(6px, 1vw, 14px);
  /* Faint pink-left / blue-right halo. closest-side keeps the falloff inside
     the block, so it can never end on a hard edge. */
  background:
    radial-gradient(circle closest-side at 20% 34%,
      rgba(244, 165, 184, 0.20) 0%, rgba(244, 165, 184, 0.13) 42%,
      rgba(244, 165, 184, 0.04) 74%, rgba(244, 165, 184, 0) 100%),
    radial-gradient(circle closest-side at 80% 66%,
      rgba(155, 180, 222, 0.20) 0%, rgba(155, 180, 222, 0.13) 42%,
      rgba(155, 180, 222, 0.04) 74%, rgba(155, 180, 222, 0) 100%);
}

/* Phones: two marks only, and they are painted on a band that runs the full
   width of the screen and a little past the block top and bottom. Painted on
   the block itself they were cut into a rectangle by its own edges — a soft
   ball has to be able to run off the screen, or fade out entirely, or you see
   where it stops. The pink is set into the top-left corner, the blue sits low
   on the left under the last line, and the two keep the hero's proportion. */
@media (max-width: 900px) {
  .walkthrough-head--lux { background: none; }
  .walkthrough-head--lux::before {
    content: '';
    position: absolute;
    z-index: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 100vw;
    /* the band reaches well past the block so neither ball can end on an edge;
       both are placed in pixels from the block's own top and bottom, so they
       hold their place against the words however the paragraph rewraps */
    /* the band must not reach past the section's own top edge — beyond it the
       page background changes tone, and a ball straddling that seam shows it */
    top: -96px;
    bottom: -80px;
    pointer-events: none;
    background:
      /* pink, upper LEFT, sitting on the first word of the heading and
         running off the screen edge */
      radial-gradient(circle clamp(104px, 28vw, 132px) at 19% 175px,
        rgba(244, 165, 184, 0.22) 0%, rgba(244, 165, 184, 0.14) 42%,
        rgba(244, 165, 184, 0.04) 74%, rgba(244, 165, 184, 0) 100%),
      /* blue, a quarter smaller, lower RIGHT, on the closing word — the two
         hold the same upper-left / lower-right diagonal as the hero */
      radial-gradient(circle clamp(82px, 22vw, 104px) at 76% calc(100% - 128px),
        rgba(155, 180, 222, 0.22) 0%, rgba(155, 180, 222, 0.14) 42%,
        rgba(155, 180, 222, 0.04) 74%, rgba(155, 180, 222, 0) 100%);
  }
}

.walkthrough-head--lux .eyebrow { margin-bottom: 18px; }

.walkthrough-head--lux h2 {
  font-size: clamp(32px, 4.3vw, 56px);
  letter-spacing: -0.022em;
  line-height: 1.12;
  margin-bottom: 20px;
}
.walkthrough-head--lux .lede {
  /* Matched to the hero lede: Inter 300 at 23px / 1.6. The serif version read
     softer on its own but sat oddly against the same kind of intro paragraph
     at the top of the page — these two now share one voice. */
  font-family: var(--font);
  font-weight: 300;
  font-size: clamp(18px, 1.65vw, 23px);
  line-height: 1.6;
  letter-spacing: 0;
  max-width: 660px;
  margin: 0 auto;
  color: var(--ink-soft);
}

/* Hairline ornament with the sparkle set into it */
.wh-ornament {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  width: min(360px, 70%);
  margin: clamp(24px, 2.6vw, 38px) auto 0;
}
.wh-ornament i {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg,
    rgba(42, 36, 56, 0) 0%, rgba(42, 36, 56, 0.18) 50%, rgba(42, 36, 56, 0) 100%);
}
.wh-ornament svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  fill: var(--gold-deep);
  opacity: 0.75;
}

/* Glass bubbles at the margins — never over the wording */
.wh-bubbles {
  position: absolute;
  inset: -34px -70px -20px;
  pointer-events: none;
  z-index: 0;
}
.wh-bubble {
  position: absolute;
  border-radius: 50%;
  background:
    radial-gradient(circle at 28% 24%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.32) 22%,
      rgba(255, 255, 255, 0)    50%),
    radial-gradient(circle at 72% 78%,
      rgba(255, 255, 255, 0.42) 0%,
      rgba(255, 255, 255, 0)    46%),
    linear-gradient(135deg,
      rgba(244, 200, 216, 0.24) 0%,
      rgba(206, 216, 238, 0.26) 100%);
  box-shadow:
    inset 0 0 0 1.3px rgba(255, 255, 255, 0.70),
    inset -4px -4px 12px rgba(180, 170, 210, 0.14),
    inset 5px 5px 12px rgba(255, 255, 255, 0.42),
    0 9px 22px -12px rgba(180, 170, 210, 0.32);
  animation: bubbleFloat 16s ease-in-out infinite;
  will-change: transform;
}
.wh-bubble--1 { width: 54px; height: 54px; top: 6%;   left: 1%;   animation-duration: 19s; animation-delay: 0s;
  background:
    radial-gradient(circle at 28% 24%, rgba(255,255,255,0.92) 0%, rgba(255,255,255,0.30) 22%, rgba(255,255,255,0) 50%),
    linear-gradient(135deg, rgba(242,184,204,0.34) 0%, rgba(226,166,190,0.24) 100%); }
.wh-bubble--2 { width: 26px; height: 26px; bottom: 8%; left: 8%;  animation: bubbleFloatAlt 13s ease-in-out infinite; animation-delay: 2.4s; }
.wh-bubble--3 { width: 18px; height: 18px; top: 52%;  left: -1%;  animation-duration: 15s; animation-delay: 4.1s; }
.wh-bubble--4 { width: 48px; height: 48px; top: 10%;  right: 1%;  animation: bubbleFloatAlt 18s ease-in-out infinite; animation-delay: 1.2s;
  background:
    radial-gradient(circle at 28% 24%, rgba(255,255,255,0.92) 0%, rgba(255,255,255,0.30) 22%, rgba(255,255,255,0) 50%),
    linear-gradient(135deg, rgba(186,206,238,0.36) 0%, rgba(158,184,224,0.26) 100%); }
.wh-bubble--5 { width: 22px; height: 22px; bottom: 12%; right: 7%; animation-duration: 14s; animation-delay: 3.3s; }

.walkthrough-head--lux .eyebrow,
.walkthrough-head--lux h2,
.walkthrough-head--lux .lede,
.walkthrough-head--lux .wh-ornament { position: relative; z-index: 1; }

@media (max-width: 700px) {
  .wh-bubbles { inset: -18px -12px -10px; }
  .wh-bubble--2, .wh-bubble--3 { display: none; }
  .wh-ornament { width: min(240px, 62%); }
}
@media (max-width: 820px) {
  .wh-bubble { -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  .wh-bubble { animation: none; }
}


/* ==========================================================================
   18. BOOK — crawling baby, flat section edges, and a mobile-friendly bind
   ========================================================================== */

/* --- Baby crawling diagonally up the right side of the book -------------
   Reuses the existing 6-frame sprite and `babyCycle` step animation from
   styles.css; only the path is new. It travels up the outer right margin,
   crossing only the empty lower corner of the Mission page — never the text. */
.book-baby {
  left: -170px;
  right: auto;
  bottom: 10px;                 /* sits in the empty lower band of the pages */
  transform-origin: bottom center;
  transform: scale(0.30);       /* static — only `left` and opacity animate */
  z-index: 3;
  animation:
    babyCycle 1.4s steps(6) infinite,
    bookBabyCrawl 34s linear infinite;
}
/* Crawls the full length of the spread, left edge to right edge, then fades
   out at the end and restarts off-canvas. It never pops into view mid-page:
   it enters from beyond the left edge and leaves past the right one.
   The sprite frame is 248px wide but draws ~74px at this scale, centred in
   its box — hence the -170px start and the 80px end inset. */
@keyframes bookBabyCrawl {
  0%        { left: -170px;              opacity: 0; }
  5%        { left: -140px;              opacity: 0.95; }
  88%       { left: calc(100% - 190px);  opacity: 0.95; }
  97%, 100% { left: calc(100% - 110px);  opacity: 0; }
}

/* --- Flat section edges -------------------------------------------------
   Measured: both sections are already the same ivory (251,247,242) and the
   boundary itself is clean. What looked like a rule was the video card's
   drop shadow ending ~70px above it — fixed at the shadow instead (see 14). */
.walkthrough, .philosophy-brief { background: var(--ivory); }

/* --- Mobile: one bound sheet rather than two panels ---------------------
   Stacked, the beige spine block read as a band cutting the card in half.
   On phones the two pages become a single continuous sheet with a bound
   left edge, and the spine turns into a hairline with the logo set on it.
   Desktop is untouched — everything here is inside the query. */
@media (max-width: 900px) {
  .book { box-shadow: none; }

  .book-page {
    box-shadow: none;
    background: linear-gradient(180deg, #FFFCF9 0%, #FDF9F4 100%);
    padding-left: clamp(30px, 7vw, 44px);
  }
  .book-page--left  { border-radius: 14px 14px 0 0; padding-bottom: clamp(20px, 4vw, 30px); }
  .book-page--right { border-radius: 0 0 14px 14px; padding-top: clamp(20px, 4vw, 30px); }

  /* Bound edge down the left of the whole sheet */
  .book-edge { display: block; width: 5px; left: 0; right: auto; top: 0; bottom: 0; border-radius: 0; }
  .book-page--left  .book-edge { border-radius: 14px 0 0 0; }
  .book-page--right .book-edge { border-radius: 0 0 0 14px; }

  /* Spine becomes a hairline with the logo mark centred on it */
  .book-spine {
    height: auto;
    padding: 0;
    background: linear-gradient(180deg, #FFFCF9 0%, #FDF9F4 100%);
    box-shadow: none;
    position: relative;
  }
  .book-spine::before {
    content: '';
    position: absolute;
    left: clamp(30px, 7vw, 44px);
    right: clamp(26px, 6vw, 40px);
    top: 50%;
    height: 1px;
    background: linear-gradient(90deg,
      rgba(42, 36, 56, 0) 0%, rgba(42, 36, 56, 0.16) 25%,
      rgba(42, 36, 56, 0.16) 75%, rgba(42, 36, 56, 0) 100%);
  }
  .book-spine img {
    position: relative;
    z-index: 1;
    width: 30px;
    padding: 0 12px;
    background: #FDF9F4;
  }
  /* the desktop gutter shadows have nothing to fall into now */
  .book-page--left::after, .book-page--right::after { display: none; }

  /* one soft shadow under the whole sheet */
  .book-glow { left: 4%; right: 4%; bottom: -14px; height: 34px; }

  .book-baby {
    bottom: 8px;
    transform: scale(0.22);
    animation-duration: 1.4s, 28s;
  }
  @keyframes bookBabyCrawl {
    0%        { left: -150px;             opacity: 0; }
    6%        { left: -128px;             opacity: 0.95; }
    88%       { left: calc(100% - 150px); opacity: 0.95; }
    97%, 100% { left: calc(100% - 96px);  opacity: 0; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .book-baby { animation: none; opacity: 0; }
}


/* ==========================================================================
   19. APP FEATURES — floating glass orbs
   Replaces the stacked icon-and-paragraph list with the same glass bubble
   language used in the trust strip and around the book. Copy is cut to one
   short line per orb so six fit without the section growing.
   ========================================================================== */
.app-orbs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 2.6vw, 38px) clamp(14px, 1.8vw, 26px);
  margin: clamp(28px, 3vw, 42px) 0 clamp(24px, 2.6vw, 36px);
}
.orb-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;
}
.orb-bubble {
  width: clamp(62px, 6.4vw, 86px);
  height: clamp(62px, 6.4vw, 86px);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
  color: var(--ink);
  /* Same blown-glass recipe as the trust strip: bright specular top-left,
     bounce highlight bottom-right, 1.5px inset rim. */
  background:
    radial-gradient(circle at 28% 24%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.34) 22%,
      rgba(255, 255, 255, 0)    52%),
    radial-gradient(circle at 72% 78%,
      rgba(255, 255, 255, 0.44) 0%,
      rgba(255, 255, 255, 0)    46%),
    linear-gradient(135deg,
      rgba(244, 220, 232, 0.22) 0%,
      rgba(214, 222, 240, 0.24) 100%);
  -webkit-backdrop-filter: blur(3px) saturate(1.06);
          backdrop-filter: blur(3px) saturate(1.06);
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, 0.75),
    inset -5px -5px 14px rgba(180, 170, 210, 0.16),
    inset 7px 7px 16px rgba(255, 255, 255, 0.48),
    0 14px 30px -14px rgba(180, 160, 190, 0.40);
  animation: trustBubbleFloat 14s ease-in-out infinite;
  position: relative;
  will-change: transform;
}
/* Staggered so the six never bob in unison */
.orb-item--1 .orb-bubble { animation-duration: 13s; animation-delay: 0s;   }
.orb-item--2 .orb-bubble { animation-duration: 16s; animation-delay: 1.3s; }
.orb-item--3 .orb-bubble { animation-duration: 14s; animation-delay: 2.6s; }
.orb-item--4 .orb-bubble { animation-duration: 17s; animation-delay: 0.7s; }
.orb-item--5 .orb-bubble { animation-duration: 15s; animation-delay: 3.4s; }
.orb-item--6 .orb-bubble { animation-duration: 18s; animation-delay: 2.0s; }

/* Travelling shine, clipped to the circle */
.orb-bubble::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background: linear-gradient(105deg,
    transparent 38%,
    rgba(255, 255, 255, 0.62) 48%,
    rgba(255, 255, 255, 0.20) 55%,
    transparent 64%);
  background-size: 260% 100%;
  background-repeat: no-repeat;
  animation: trustBubbleShine 6.5s ease-in-out infinite;
  pointer-events: none;
}
.orb-item--2 .orb-bubble::after { animation-delay: 1.1s; }
.orb-item--3 .orb-bubble::after { animation-delay: 2.2s; }
.orb-item--4 .orb-bubble::after { animation-delay: 3.3s; }
.orb-item--5 .orb-bubble::after { animation-delay: 4.4s; }
.orb-item--6 .orb-bubble::after { animation-delay: 5.5s; }

.orb-bubble svg { width: 38%; height: 38%; position: relative; z-index: 1; }

.orb-item strong {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(15px, 1.25vw, 18px);
  color: var(--ink);
  letter-spacing: 0.005em;
}
.orb-note {
  font-size: clamp(12.5px, 1vw, 13.5px);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 22ch;
}

@media (max-width: 1024px) {
  .app-orbs { grid-template-columns: repeat(2, 1fr); }
}
/* On a phone the balls carry the whole grid: drawn larger, standing STILL so
   the six line up in tidy rows, and keeping their glass so the page shines
   through them. The drift was catching each ball at a different point of its
   cycle, which is what made the rows look ragged. */
@media (max-width: 760px) {
  .orb-bubble {
    width: 88px; height: 88px; margin-bottom: 20px;
    animation: none !important;
    -webkit-backdrop-filter: blur(7px) saturate(1.3);
            backdrop-filter: blur(7px) saturate(1.3);
  }
  .orb-bubble::after { animation: none !important; }
  .orb-bubble svg { width: 40%; height: 40%; }
  .orb-item strong { margin-top: 2px; }
  .orb-note { margin-top: 6px; }
}
@media (max-width: 420px) {
  .orb-bubble { width: 80px; height: 80px; margin-bottom: 17px; }
  .orb-note { font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .orb-bubble, .orb-bubble::after { animation: none; }
}


/* ==========================================================================
   20. MOBILE — the book becomes a spiral notepad
   A two-page spread cannot read as a book on a 390px screen, so on phones it
   becomes a single notepad sheet: wire binding across the top, ruled lines,
   a margin rule down the left, and the baby crawling along the bottom line.
   Desktop is untouched — everything here is inside the media query.
   ========================================================================== */
@media (max-width: 900px) {
  .book {
    padding-top: 34px;
    /* room for the wire binding above the sheet */
  }

  /* Wire binding — evenly spaced coils across the top of the pad */
  .book::before {
    content: '';
    position: absolute;
    top: 4px;
    left: 14px;
    right: 14px;
    height: 30px;
    z-index: 4;
    background:
      repeating-linear-gradient(90deg,
        transparent 0 12px,
        rgba(120, 112, 142, 0.50) 12px 14px,
        rgba(160, 152, 180, 0.30) 14px 16px,
        transparent 16px 34px);
    pointer-events: none;
  }
  /* Punched holes the coils pass through */
  .book::after {
    content: '';
    position: absolute;
    top: 26px;
    left: 14px;
    right: 14px;
    height: 14px;
    z-index: 3;
    background:
      repeating-linear-gradient(90deg,
        transparent 0 9px,
        rgba(42, 36, 56, 0.13) 9px 19px,
        transparent 19px 34px);
    -webkit-mask-image: radial-gradient(circle 5px at 14px 50%, #000 99%, transparent 100%);
            mask-image: radial-gradient(circle 5px at 14px 50%, #000 99%, transparent 100%);
    -webkit-mask-size: 34px 14px;
            mask-size: 34px 14px;
    -webkit-mask-repeat: repeat-x;
            mask-repeat: repeat-x;
    pointer-events: none;
  }

  /* Ruled paper. The 32px rhythm matches the body line-height so the text
     sits on the rules rather than floating between them. */
  .book-page {
    background:
      repeating-linear-gradient(180deg,
        transparent 0 31px,
        rgba(143, 163, 201, 0.22) 31px 32px),
      linear-gradient(180deg, #FFFDFA 0%, #FDFAF5 100%);
    background-position: 0 6px, 0 0;
  }
  /* Margin rule down the left, like a real pad */
  .book-page::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: clamp(20px, 5vw, 30px);
    width: 1px;
    background: rgba(232, 155, 175, 0.45);
  }
  .book-page--left  { border-radius: 4px 4px 0 0; }
  .book-page--right { border-radius: 0 0 10px 10px; padding-bottom: 74px; }

  /* Divider between the two entries stays, just quieter on ruled paper */
  .book-spine { background: transparent; }
  .book-spine img { background: #FDFAF5; }

  /* Baby crawls along the bottom of the pad, inside the paper */
  .book-baby { bottom: 26px; }
}


/* ==========================================================================
   21. BABY TRAIL — a dotted path that draws itself behind the crawl
   --------------------------------------------------------------------------
   The trail is full width from the start and REVEALED with clip-path rather
   than grown with width or scaleX. That matters: animating width forces a
   layout pass every frame, and scaleX would stretch the dots into dashes as
   it grew. clip-path does neither — the dots stay the same size and the
   whole thing composites on the GPU.

   Its timing mirrors .book-baby exactly (same duration, same linear easing,
   same keyframe percentages), so the leading edge of the trail stays under
   the baby the whole way across.
   ========================================================================== */
.book-trail {
  position: absolute;
  left: 10px;
  bottom: 22px;                /* just under the baby's hands */
  width: calc(100% - 76px);    /* ends where the baby's centre ends */
  height: 7px;
  z-index: 2;
  pointer-events: none;
  /* Alternating rose and blue dots, fading in size toward the tail */
  background:
    radial-gradient(circle 2.6px at 5px 50%, rgba(232, 155, 175, 0.65) 0 100%, transparent 100%),
    radial-gradient(circle 2px   at 21px 50%, rgba(143, 163, 201, 0.55) 0 100%, transparent 100%);
  background-size: 32px 7px, 32px 7px;
  background-repeat: repeat-x, repeat-x;
  clip-path: inset(0 100% 0 0);
  animation: bookTrailDraw 34s linear infinite;
}
@keyframes bookTrailDraw {
  0%        { clip-path: inset(0 100% 0 0); opacity: 0; }
  5%        { clip-path: inset(0 100% 0 0); opacity: 0.9; }
  88%       { clip-path: inset(0 0 0 0);    opacity: 0.9; }
  /* Gone by the time the baby leaves the page, so nothing is left behind */
  96%, 100% { clip-path: inset(0 0 0 0);    opacity: 0; }
}

@media (max-width: 900px) {
  .book-trail {
    left: clamp(24px, 5.5vw, 34px);
    bottom: 38px;
    width: calc(100% - 96px);
    animation-duration: 28s;
  }
}
@media (prefers-reduced-motion: reduce) {
  .book-trail { animation: none; opacity: 0; }
}


/* ==========================================================================
   22. MOBILE NOTEPAD — one continuous sheet
   --------------------------------------------------------------------------
   The first pass kept the paper on each .book-page, so the two entries each
   carried their own edge strip, their own margin rule and their own set of
   rules that restarted at the divider — three doubled-up lines running down
   the pad. Everything paper-related now lives on the .book container instead,
   and the pages are transparent, so it reads as a single sheet.
   ========================================================================== */
@media (max-width: 900px) {
  .book {
    background:
      repeating-linear-gradient(180deg,
        transparent 0 31px,
        rgba(143, 163, 201, 0.18) 31px 32px),
      linear-gradient(180deg, #FFFDFA 0%, #FDFAF5 100%);
    background-position: 0 40px, 0 0;
    background-repeat: repeat, no-repeat;
    border-radius: 4px 4px 14px 14px;
    box-shadow: 0 24px 46px -32px rgba(42, 36, 56, 0.32);
  }

  /* Pages carry only their text now */
  .book-page {
    background: none;
    box-shadow: none;
    border-radius: 0;
    padding-left: clamp(24px, 6vw, 36px);
    padding-right: clamp(24px, 6vw, 36px);
  }
  .book-page--left  { padding-bottom: clamp(14px, 3vw, 22px); }
  .book-page--right { padding-top: clamp(14px, 3vw, 22px); padding-bottom: 84px; }

  /* All three vertical rules removed */
  .book-page::before { display: none; }   /* pink margin rule */
  .book-edge         { display: none; }   /* page-edge strips */
  .book-page::after  { display: none; }   /* leftover gutter shading */

  /* Divider: just the logo, sitting on a small patch so the ruling doesn't
     run through it */
  .book-spine { background: transparent; box-shadow: none; height: auto; }
  .book-spine::before { display: none; }
  .book-spine img {
    background: #FDFAF5;
    padding: 6px 14px;
    border-radius: 999px;
  }
}


/* ==========================================================================
   23. BABY + TRAIL — scoped to the Mission page only
   --------------------------------------------------------------------------
   Both elements now live INSIDE .book-page--right in the markup, so 0% and
   100% resolve against the Mission page rather than the whole spread. That is
   why the offsets below are simpler than the earlier full-width version — no
   spine arithmetic, and it stays correct at any width.

   The sprite frame is 248px wide but draws ~74px at scale(0.30), centred in
   its box: hence left:-124px puts the VISIBLE baby exactly on the page's left
   edge, and calc(100% - 124px) puts it exactly on the right edge.
   ========================================================================== */
.book-page--right .book-baby {
  left: -124px;
  right: auto;
  bottom: 10px;
  transform: scale(0.30);
  transform-origin: bottom center;
  animation:
    babyCycle 1.4s steps(6) infinite,
    bookBabyCrawl 26s linear infinite;
}
@keyframes bookBabyCrawl {
  0%        { left: -124px;             opacity: 0; }
  6%        { left: -110px;             opacity: 0.95; }
  86%       { left: calc(100% - 150px); opacity: 0.95; }
  96%, 100% { left: calc(100% - 124px); opacity: 0; }
}

.book-page--right .book-trail {
  left: 0;
  width: 100%;
  bottom: 22px;
  animation-duration: 26s;
}

@media (max-width: 900px) {
  .book-page--right .book-baby { bottom: 22px; transform: scale(0.24); }
  .book-page--right .book-trail { left: 0; width: 100%; bottom: 34px; }
}


/* ==========================================================================
   24. BOOK — bubbles clear of the pages, and no shadow band underneath
   --------------------------------------------------------------------------
   Two fixes:
   1. Several bubbles overlapped the page rectangles. Since the pages paint
      above them, the overlapping part was sliced off by the page edge — that
      straight cut is the "line" the bubbles looked like they were hiding
      behind. They now sit entirely in the margins, so nothing clips them.
   2. The pool of light under the spread (.book-glow) plus the page drop
      shadows stacked into a visible horizontal band below the book. Glow
      removed; page shadow reduced to a whisper.
   ========================================================================== */
.book-glow { display: none; }

.book-page {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

/* All seven pushed fully outside the page boxes: left margin, right margin,
   or below the spread. The container's own inset gives them the room. */
.bk-bubble--1 { width: 76px; height: 76px; top: 5%;    left: 0;     right: auto; bottom: auto; }
.bk-bubble--2 { width: 38px; height: 38px; top: 30%;   left: 8px;   right: auto; bottom: auto; }
.bk-bubble--3 { width: 24px; height: 24px; top: auto;  left: 26px;  right: auto; bottom: 26%; }
.bk-bubble--4 { width: 54px; height: 54px; top: auto;  left: 24%;   right: auto; bottom: 0; }
.bk-bubble--5 { width: 68px; height: 68px; top: 9%;    right: 0;    left: auto;  bottom: auto; }
.bk-bubble--6 { width: 32px; height: 32px; top: auto;  right: 10px; left: auto;  bottom: 24%; }
.bk-bubble--7 { width: 20px; height: 20px; top: 50%;   right: 30px; left: auto;  bottom: auto; }

@media (max-width: 900px) {
  /* Narrow screens have almost no side margin, so the survivors sit above
     and below the pad rather than beside it. */
  .bk-bubble--1 { width: 54px; height: 54px; top: -34px; left: 4px; }
  .bk-bubble--5 { width: 48px; height: 48px; top: -30px; right: 4px; }
  .bk-bubble--3 { display: none; }
  .bk-bubble--6 { width: 26px; height: 26px; bottom: -28px; right: 16%; }
}


/* ==========================================================================
   25. MOBILE — wooden clipboard instead of a spiral pad
   --------------------------------------------------------------------------
   .book becomes the wooden board; ::before is the paper sheet laid on it and
   ::after is the metal clip. The wire-coil rules from section 20 are fully
   replaced here (same two pseudo-elements, redefined).

   Wood grain is three stacked gradients rather than an image: two sets of
   near-vertical low-contrast stripes at slightly different angles and
   spacings, over a warm oak base. Offsetting the angles by a few degrees is
   what stops it looking like corduroy.
   ========================================================================== */
@media (max-width: 900px) {
  .book {
    padding: 52px 12px 14px;
    border-radius: 14px;
    background:
      repeating-linear-gradient(93deg,
        rgba(104, 66, 36, 0.10) 0 2px,
        rgba(104, 66, 36, 0)    2px 7px),
      repeating-linear-gradient(87deg,
        rgba(78, 48, 26, 0.07)  0 1px,
        rgba(78, 48, 26, 0)     1px 13px),
      linear-gradient(158deg, #CBA070 0%, #BE8F5D 46%, #AB7C4B 100%);
    box-shadow:
      inset 0 1px 0 rgba(255, 240, 220, 0.35),
      inset 0 -2px 4px rgba(60, 36, 18, 0.30),
      0 26px 46px -30px rgba(60, 36, 18, 0.55);
  }

  /* The paper sheet resting on the board */
  .book::before {
    content: '';
    position: absolute;
    top: 44px;
    left: 12px;
    right: 12px;
    bottom: 14px;
    z-index: 0;
    border-radius: 3px;
    background:
      repeating-linear-gradient(180deg,
        transparent 0 31px,
        rgba(143, 163, 201, 0.18) 31px 32px),
      linear-gradient(180deg, #FFFDFA 0%, #FDFAF5 100%);
    background-position: 0 14px, 0 0;
    box-shadow:
      0 1px 2px rgba(60, 36, 18, 0.22),
      0 6px 12px -6px rgba(60, 36, 18, 0.30);
  }

  /* Metal clip at the top of the board */
  .book::after {
    content: '';
    position: absolute;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    width: clamp(96px, 30vw, 130px);
    height: 30px;
    z-index: 4;
    border-radius: 7px 7px 5px 5px;
    background:
      linear-gradient(180deg,
        #FDFDFE 0%, #E4E7EC 22%, #C3C8D2 52%, #DCE0E7 76%, #A9B0BC 100%);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.95),
      inset 0 -1px 0 rgba(90, 96, 108, 0.55),
      0 3px 6px -2px rgba(60, 36, 18, 0.45);
    -webkit-mask-image: none;
            mask-image: none;
  }

  /* Text sits on the paper */
  .book-page {
    position: relative;
    z-index: 1;
    background: none;
    box-shadow: none;
    padding-left: clamp(26px, 6.5vw, 38px);
    padding-right: clamp(26px, 6.5vw, 38px);
  }
  .book-page--left  { padding-top: clamp(20px, 4vw, 30px); }
  .book-page--right { padding-bottom: 84px; }
  .book-spine { position: relative; z-index: 1; }

  /* The two survivors float ABOVE the board, clear of the section's edge and
     clear of the board itself — pink on the left, blue on the right. Sitting
     at -38px they were half-clipped by the band above. */
  .bk-bubble--1 { width: 58px; height: 58px; top: -30px; left: -14px;  right: auto; bottom: auto; }
  .bk-bubble--5 { width: 50px; height: 50px; top: -22px; right: -10px; left: auto;  bottom: auto; }
}


/* ==========================================================================
   26. FIXES — paper sheet size, baby across the whole board, copy width
   ========================================================================== */

/* Section 20 gave .book::before a fixed `height: 30px` for the wire coils.
   Section 25 reused the same pseudo-element as the paper sheet and set all
   four insets, but that leftover height won and clamped the paper to a strip
   across the top — which is why the text was sitting straight on the wood. */
@media (max-width: 900px) {
  .book::before {
    height: auto;
    width: auto;
  }
  .book::after {
    height: 30px;
    width: clamp(96px, 30vw, 130px);
  }

  /* Baby crawls the full length of the board, edge to edge */
  .book-page--right .book-baby { bottom: 24px; }
  /* She crawls ACROSS THE PAPER, never off it. Starting at -128px she began
     out on the page beside the board, which on a phone reads as a baby
     wandering in from the edge of the screen. */
  @keyframes bookBabyCrawl {
    0%        { left: 14px;               opacity: 0; }
    9%        { left: 30px;               opacity: 0.95; }
    84%       { left: calc(100% - 146px); opacity: 0.95; }
    95%, 100% { left: calc(100% - 126px); opacity: 0; }
  }
}

/* The app intro ran to a different measure than the orb grid beneath it, so
   the two blocks didn't line up on the right. Both now fill the column. */
.tracking-content .body-text {
  max-width: none;
}


/* ==========================================================================
   27. PHONE MOCK-UP — matched to the site's palette and glass language
   The screen was a flat pink panel with white cards. It now uses the same
   ivory base + two-spot wash as the page, and the rows are glass panels with
   the same rim-and-sheen recipe as the trust and app orbs.
   ========================================================================== */
.tracking-visual .phone-screen {
  background:
    radial-gradient(circle 180px at 12% 4%,
      rgba(244, 165, 184, 0.30) 0%, rgba(244, 165, 184, 0.14) 45%, rgba(244, 165, 184, 0) 100%),
    radial-gradient(circle 200px at 92% 88%,
      rgba(155, 180, 222, 0.28) 0%, rgba(155, 180, 222, 0.13) 45%, rgba(155, 180, 222, 0) 100%),
    linear-gradient(180deg, #FFFDFB 0%, #FBF7F2 100%);
}

.tracking-visual .app-logo {
  display: block;
  width: 34px;
  height: auto;
  margin: 0 auto 8px;
  opacity: 0.9;
}
.tracking-visual .app-greeting {
  color: var(--cloud-blue-deep);
  letter-spacing: 0.2em;
}
.tracking-visual .app-baby {
  font-family: var(--font-display);
  color: var(--ink);
}
.tracking-visual .app-subline {
  font-family: var(--font);
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-deep);
  margin-top: 6px;
  text-align: center;
}

/* Rows as glass rather than solid white */
.tracking-visual .app-card {
  background:
    linear-gradient(135deg,
      rgba(255, 255, 255, 0.86) 0%,
      rgba(255, 255, 255, 0.66) 100%);
  border: 1px solid rgba(255, 255, 255, 0.9);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 6px 14px -8px rgba(42, 36, 56, 0.20);
  -webkit-backdrop-filter: blur(6px) saturate(1.05);
          backdrop-filter: blur(6px) saturate(1.05);
}

/* Icon tiles alternate rose and blue down the list, matching the palette */
.tracking-visual .app-card-icon {
  background: linear-gradient(135deg, rgba(244, 194, 208, 0.55), rgba(240, 170, 190, 0.35));
  color: var(--gold-deep);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.7);
}
.tracking-visual .app-card:nth-child(odd) .app-card-icon {
  background: linear-gradient(135deg, rgba(196, 214, 240, 0.55), rgba(163, 189, 226, 0.35));
  color: var(--cloud-blue-deep);
}
.tracking-visual .app-card-label { color: var(--ink-mute); }
.tracking-visual .app-card-value { color: var(--ink); }
.tracking-visual .app-card-time  { color: var(--gold-deep); }
.tracking-visual .app-card:nth-child(odd) .app-card-time { color: var(--cloud-blue-deep); }

/* Six rows need a tighter rhythm than five did, or the last one runs off the
   bottom of the screen. Values are kept on one line for the same reason —
   a wrapped value silently makes its row 50% taller. */
.tracking-visual .app-card {
  padding: 9px 11px;
  gap: 9px;
  margin-bottom: 8px;
}
.tracking-visual .app-card-icon { width: 26px; height: 26px; border-radius: 8px; }
.tracking-visual .app-card-label { font-size: 8px; letter-spacing: 0.16em; }
.tracking-visual .app-card-value { font-size: 11.5px; white-space: nowrap; }
.tracking-visual .app-card-time  { font-size: 9px; white-space: nowrap; }
.tracking-visual .app-header { margin-bottom: 12px; }
.tracking-visual .app-logo { width: 28px; margin-bottom: 6px; }
.tracking-visual .app-baby { font-size: 15px; }
.tracking-visual .app-subline { font-size: 8.5px; margin-top: 4px; }

/* Trimmed further so the sixth row sits almost fully on screen, with a soft
   fade at the bottom edge — a real app list continues below the fold, and the
   fade reads as "scrolls" rather than "clipped". */
.tracking-visual .app-card { padding: 8px 10px; margin-bottom: 6px; }
.tracking-visual .app-card-icon { width: 24px; height: 24px; }
.tracking-visual .app-header { margin-bottom: 9px; }
.tracking-visual .app-logo { width: 24px; margin-bottom: 4px; }
.tracking-visual .app-greeting { font-size: 8.5px; }
.tracking-visual .app-baby { font-size: 14px; }

.tracking-visual .phone-screen {
  position: relative;
  overflow: hidden;
}
.tracking-visual .phone-screen::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 46px;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(251, 247, 242, 0) 0%,
    rgba(251, 247, 242, 0.85) 62%,
    rgba(251, 247, 242, 1) 100%);
}


/* ==========================================================================
   28. Two more shadow / clipping fixes
   ========================================================================== */

/* --- Map card: neutral shadow -------------------------------------------
   styles.css line ~1314 gives .map-card a rose glow —
     0 30px 60px -20px rgba(212, 120, 150, 0.25)
   which spreads a pink haze across the ivory beneath it, the same way the
   video card did. Same treatment: neutral ink, wider and shallower. */
.map-section .map-card {
  box-shadow:
    0 18px 70px -40px rgba(42, 36, 56, 0.28),
    0 0 0 1px rgba(42, 36, 56, 0.06);
}

/* --- Book bubbles: keep them inside their own section --------------------
   Measured: there is only 55px of section padding above and below the book,
   and bubbles 1 and 4 were overshooting it by 6–7px. The next section's
   opaque ivory background paints over whatever escapes, slicing the bubble
   flat — that cut is the "line" above and below the book. Pulling the layer
   in to match the available room fixes both at once. */
.book-bubbles {
  inset: -46px -80px -46px;
}
.bk-bubble--1 { top: 8%; }
.bk-bubble--4 { bottom: 6px; }


/* ==========================================================================
   29. PHONE — neutral shadow, and soft clouds around it
   ========================================================================== */
.tracking-visual { position: relative; }

/* styles.css line ~1195 wraps the phone in a rose glow and a pink ring:
     0 40px 80px -30px rgba(212, 120, 150, 0.5)
     0 0 0 4px rgba(232, 155, 175, 0.15)
   Both replaced with neutral ink so the device reads as lifted, not tinted. */
.tracking-visual .phone-frame {
  box-shadow:
    0 34px 70px -34px rgba(42, 36, 56, 0.42),
    0 0 0 3px rgba(42, 36, 56, 0.06);
}

.phone-clouds {
  position: absolute;
  inset: -30px -6% -20px;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
  /* Feathered on every edge so a cloud crossing the boundary fades out
     instead of being sliced by the section edge. */
  -webkit-mask-image:
    linear-gradient(180deg, transparent 0%, #000 12%, #000 88%, transparent 100%),
    linear-gradient(90deg,  transparent 0%, #000 8%,  #000 92%, transparent 100%);
          mask-image:
    linear-gradient(180deg, transparent 0%, #000 12%, #000 88%, transparent 100%),
    linear-gradient(90deg,  transparent 0%, #000 8%,  #000 92%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
.ph-cloud {
  position: absolute;
  object-fit: cover;
  -webkit-mask-image: var(--cloud-mask);
          mask-image: var(--cloud-mask);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: cloudDrift 26s ease-in-out infinite;
  will-change: transform;
}
.ph-cloud--1 { top: 6%;  left: -6%;  width: 190px; height: 95px; opacity: 0.16; animation-delay: 0s;  }
.ph-cloud--2 { bottom: 8%; left: -4%; width: 160px; height: 80px; opacity: 0.13; animation-delay: 5s; animation-duration: 30s; }
.ph-cloud--3 { top: 12%; right: -7%; width: 200px; height: 100px; opacity: 0.15; animation-delay: 2s; }
.ph-cloud--4 { bottom: 4%; right: -5%; width: 150px; height: 75px; opacity: 0.12; animation-delay: 8s; animation-duration: 28s; }

/* The phone sits above the clouds */
.tracking-visual .phone-frame { position: relative; z-index: 1; }

@media (max-width: 900px) {
  .ph-cloud--2, .ph-cloud--4 { display: none; }
  .phone-clouds { inset: -18px -2% -14px; }
}
@media (prefers-reduced-motion: reduce) {
  .ph-cloud { animation: none; }
}


/* ==========================================================================
   30. WOODPAD — plain paper, no rules
   The ruling was struck through the wording rather than sitting behind it,
   because the 32px rhythm no longer matches the mixed type sizes on the pad
   (display serif headings and sans body in the same column). Plain sheet.
   ========================================================================== */
@media (max-width: 900px) {
  .book::before {
    background: linear-gradient(180deg, #FFFDFA 0%, #FDFAF5 100%);
  }
}


/* ==========================================================================
   31. MOBILE — fridge note, replacing the wooden clipboard
   --------------------------------------------------------------------------
   A plain paper note pinned by a round magnet. Overrides the board, clip and
   paper-sheet rules from sections 25/26/30 (same selectors, redefined).
   ========================================================================== */
@media (max-width: 900px) {
  .book {
    /* the note itself — no board behind it any more */
    padding: 52px 0 20px;
    border-radius: 2px;
    background: linear-gradient(178deg, #FFFEFC 0%, #FDF9F3 55%, #FAF4EC 100%);
    /* A hair off square. Perfectly straight reads as a UI card; a fraction of
       a degree reads as something a person actually stuck up there. */
    transform: rotate(-0.7deg);
    margin: 0 4px;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.9),
      0 1px 2px rgba(42, 36, 56, 0.10),
      0 20px 36px -24px rgba(42, 36, 56, 0.38);
  }

  /* Soft shadow the magnet casts down the paper */
  .book::before {
    content: '';
    position: absolute;
    top: 26px;
    left: 50%;
    transform: translateX(-50%);
    width: 66px;
    height: 26px;
    border-radius: 50%;
    background: radial-gradient(ellipse at center,
      rgba(42, 36, 56, 0.18) 0%, rgba(42, 36, 56, 0.05) 55%, rgba(42, 36, 56, 0) 78%);
    filter: blur(4px);
    z-index: 4;
    /* Clearing the clipboard rules. NOTE: `inset: auto` must come BEFORE the
       individual offsets — it is shorthand for all four, so declaring it
       afterwards wipes the `left: 50%` above and drops this shadow into the
       top-left corner of the note. That was the stray dark smudge. */
    inset: auto;
    top: 26px;
    left: 50%;
    right: auto;
    bottom: auto;
    box-shadow: none;
    -webkit-mask-image: none;
            mask-image: none;
  }

  /* The magnet — glossy dome, lit from the upper left like the bubbles */
  .book::after {
    content: '';
    position: absolute;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    width: 34px;
    height: 34px;
    border-radius: 50%;
    z-index: 5;
    background:
      radial-gradient(circle at 32% 27%,
        rgba(255, 255, 255, 0.95) 0%,
        rgba(255, 255, 255, 0.35) 16%,
        rgba(255, 255, 255, 0) 40%),
      radial-gradient(circle at 50% 50%,
        #6B5788 0%, #55446F 48%, #3F3157 80%, #2E2440 100%);
    box-shadow:
      inset 0 -3px 6px rgba(20, 12, 34, 0.55),
      inset 0 2px 3px rgba(255, 255, 255, 0.42),
      0 5px 9px -2px rgba(42, 36, 56, 0.55);
    -webkit-mask-image: none;
            mask-image: none;
  }

  .book-page {
    background: none;
    box-shadow: none;
    padding-left: clamp(24px, 6vw, 34px);
    padding-right: clamp(24px, 6vw, 34px);
  }
  .book-page--right { padding-bottom: 78px; }
  .book-spine img { background: transparent; padding: 0; }
}

/* Softened corners on the note — 2px read as a sharp-cut card. Slightly
   different radius per corner so it looks like paper rather than a rounded
   rectangle primitive. */
@media (max-width: 900px) {
  .book { border-radius: 18px 14px 20px 16px; }
}


/* ==========================================================================
   32. Book backdrop, highlight colour, and a modern map
   ========================================================================== */

/* --- No ambient blob behind the book ------------------------------------
   styles.css floats two large tinted blobs inside each section. Behind the
   book they read as a stray pink pom-pom sitting under the paper. */
.philosophy-brief::before,
.philosophy-brief::after {
  background: none !important;
  animation: none !important;
}

/* --- Highlight colour: deep plum ----------------------------------------
   #5B4869 is a lifted version of the site's own ink (#2A2438), so it reads as
   part of the family rather than a new hue, and it holds its weight against
   the black serif in a way the pastel blue could not. The pinks and blues
   stay where they belong — on the decoration. */
.book-statement em,
.book-page--right .book-statement em {
  color: #5B4869;
}

/* --- Map: soft monochrome instead of default Google colours -------------
   The embed's own styling can't be reached from outside the iframe, so the
   modernising is done with a filter: most of the saturation pulled out, a
   touch brighter, contrast eased. The red pins and orange POI markers were
   what made it look dated against this palette. */
.map-section .map-card iframe,
.map-section .map-card .map-embed,
.map-section .map-card img[src*="maps"] {
  filter: grayscale(0.82) saturate(0.55) contrast(0.92) brightness(1.06);
  transition: filter 0.6s var(--ease);
}
/* Full colour on hover, so the detail is still there when someone wants it */
.map-section .map-card:hover iframe,
.map-section .map-card:hover .map-embed {
  filter: grayscale(0.25) saturate(0.85) contrast(0.96) brightness(1.02);
}
.map-section .map-card {
  border-radius: 16px;
  overflow: hidden;
}

/* styles.css line ~1002 has `.philosophy-brief-inner h2 em { color: var(--cloud-blue-deep) }`,
   which is two classes deep and beat the plain `.book-statement em` above.
   Matching its specificity from this file wins on source order. */
.philosophy-brief-inner .book-statement em,
.philosophy-brief-inner h2.book-statement em,
.philosophy-brief-inner .book-page--right .book-statement em {
  color: #5B4869;
}

/* Map colour restored — the greyscale filter is removed entirely now that the
   map is Leaflet with a quiet colour basemap, rather than Google's default. */
.map-section .map-card iframe,
.map-section .map-card .map-embed,
.map-section .map-card:hover iframe,
.map-section .map-card:hover .map-embed {
  filter: none;
}
.map-section .map-embed,
.map-section #ba-map {
  width: 100%;
  height: 100%;
  min-height: 420px;
}
/* Brand pin — a teardrop in the site's rose, with the logo dot inside */
.ba-pin-wrap { background: none; border: none; }
.ba-pin {
  width: 34px;
  height: 34px;
  margin: 0 auto;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  background: linear-gradient(135deg, #F0A9BF 0%, #D47896 60%, #B85E7C 100%);
  box-shadow: 0 6px 14px -4px rgba(42, 36, 56, 0.5), inset 0 1px 0 rgba(255,255,255,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ba-pin span {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #FFFDFB;
  box-shadow: inset 0 1px 2px rgba(42, 36, 56, 0.25);
}
.leaflet-popup-content strong { font-family: var(--font-display); font-size: 15px; display: block; }
.leaflet-popup-content .ba-pop { display: block; margin-top: 4px; font-size: 12.5px; color: var(--ink-soft); line-height: 1.55; }

/* ==========================================================================
   32. BOOK BUBBLES — never past the section edge (06 Aug 2026)
   The earlier fix only checked where the bubbles SIT. They also drift: both
   float keyframes translate up to 14-20px and scale to 1.06, so a bubble
   resting 6px inside the boundary still crossed it mid-animation. The next
   section's opaque ivory then paints over whatever escaped and slices the
   bubble flat — that flat cut is the "line" between the sections.

   The layer now stops INSIDE the book on both sides, and the bottom-anchored
   bubbles are lifted by more than their worst-case downward travel. Measured
   across 20 animation frames per bubble at every breakpoint; nothing reaches
   the boundary any more, so there is no cut and no line.
   ========================================================================== */
.book-bubbles {
  inset: -30px -80px 34px;
}
.bk-bubble--3 { bottom: 24%; }
.bk-bubble--4 { bottom: 30px; left: 20%; }
.bk-bubble--6 { bottom: 26%; }
.bk-bubble--1 { top: 12%; }

@media (max-width: 900px) {
  .book-bubbles { inset: -22px -30px 46px; }
  .bk-bubble--6 { bottom: 30%; }
}
@media (max-width: 560px) {
  .book-bubbles { inset: -18px -18px 62px; }
  .bk-bubble--6 { bottom: 34%; }
}

/* ---------------------------------------------------------------------------
   COMING SOON — a real corner ribbon on the app mock
   A band pinned across the phone's top-right corner, clipped to the frame's
   own rounded box so it reads as sewn onto the device rather than floating
   beside it. 45 degrees, so it meets both edges square.
   --------------------------------------------------------------------------- */
/* The band belongs to the SCREEN, not the body — crossing the bezel it sat on
   the phone's rounded corner and read as a sticker stuck over the device. */
.tracking-visual .phone-screen { position: relative; overflow: hidden; }
.phone-ribbon {
  position: absolute;
  top: 32px;
  right: -50px;
  width: 214px;
  padding: 6px 0;
  transform: rotate(45deg);
  transform-origin: center;
  z-index: 6;
  text-align: center;
  background: linear-gradient(180deg, #E24A5C 0%, #C8203A 100%);
  color: #fff;
  font-family: var(--font, 'Inter', sans-serif);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  /* a hairline of gold along both edges, the way a printed band is foiled */
  box-shadow:
    inset 0 1px 0 rgba(255, 232, 200, .55),
    inset 0 -1px 0 rgba(120, 12, 30, .5),
    0 8px 18px -8px rgba(150,20,45,.75);
  pointer-events: none;
}
/* a hairline of shadow where the band crosses the bezel */
.phone-ribbon::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgba(0,0,0,.22) 0%, rgba(0,0,0,0) 18%,
    rgba(0,0,0,0) 82%, rgba(0,0,0,.22) 100%);
}

@media (max-width: 640px) {
  .phone-ribbon { top: 26px; right: -48px; width: 190px; font-size: 8.5px; padding: 5px 0; letter-spacing: .09em; }
}
@media (prefers-reduced-motion: reduce) { .phone-ribbon { box-shadow: none; } }


/* The balls around the vision/mission board are gone — the plum pin carries
   that corner on its own now. (Winnie, 15 Aug 2026) */
.book-bubbles, .bk-bubble { display: none !important; }


/* ---------------------------------------------------------------------------
   THE CRAWL AND ITS TRAIL  (fixed, 15 Aug 2026)
   She was not crawling at all: the rule pinning her start position used
   `left: 10px !important`, and an !important author declaration beats a
   keyframe, so the animation's own `left` values were being thrown away every
   frame. She sat still while her sprite cycled — which is exactly why she
   appeared to stop half way. No !important on anything the animation drives.

   Her sprite frame is 248px wide but she only fills a fraction of it, so the
   box is scaled from its BOTTOM LEFT corner: that makes `left` mean where she
   visually is, and one set of keyframes then works at every size.
   --------------------------------------------------------------------------- */
@keyframes babyCrawlPage {
  0%        { left: 4px;                opacity: 0; }
  7%        { left: 26px;               opacity: .95; }
  86%       { left: calc(100% - 96px);  opacity: .95; }
  96%, 100% { left: calc(100% - 72px);  opacity: 0; }
}
.book-baby,
.book-page--right .book-baby {
  left: 4px;
  right: auto;
  transform-origin: bottom left;
  animation:
    babyCycle 1.4s steps(6) infinite,
    babyCrawlPage 30s linear infinite;
}
/* The dots are a PATH SHE LEAVES, not something she tows. The strip lies
   still across her whole route and is uncovered from the left as she passes,
   so each dot appears under her and stays where she made it. Travelling the
   strip with her was the bug: the same five dots were being dragged along
   behind her the whole way. */
.book-trail,
.book-page--right .book-trail {
  display: block;
  position: absolute;
  left: 18px;
  right: 78px;
  width: auto;
  height: 7px;
  bottom: 26px;
  z-index: 2;
  transform: none;
  -webkit-mask-image: none;
          mask-image: none;
  clip-path: inset(0 100% 0 0);
  animation: bookTrailDraw 30s linear infinite;
}
/* uncovered in step with her, beat for beat */
@keyframes bookTrailDraw {
  0%        { clip-path: inset(0 100% 0 0); opacity: 0; }
  7%        { clip-path: inset(0 100% 0 0); opacity: .95; }
  86%       { clip-path: inset(0 0 0 0);    opacity: .95; }
  96%, 100% { clip-path: inset(0 0 0 0);    opacity: 0; }
}
@media (max-width: 900px) {
  .book-trail, .book-page--right .book-trail {
    bottom: 38px; left: 16px; right: 52px; width: auto; transform: none;
  }
  @keyframes bookTrailDraw {
    0%        { clip-path: inset(0 100% 0 0); opacity: 0; }
    7%        { clip-path: inset(0 100% 0 0); opacity: .95; }
    88%       { clip-path: inset(0 0 0 0);    opacity: .95; }
    97%, 100% { clip-path: inset(0 0 0 0);    opacity: 0; }
  }
  /* she is drawn smaller here, so she can travel further before she runs out
     of paper — without this she left the page at 81% and looked to stop short */
  @keyframes babyCrawlPage {
    0%        { left: 4px;               opacity: 0; }
    7%        { left: 24px;              opacity: .95; }
    88%       { left: calc(100% - 62px); opacity: .95; }
    97%, 100% { left: calc(100% - 44px); opacity: 0; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .book-trail, .book-page--right .book-trail { animation: none; opacity: 0; }
}

/* The mark in the gutter, between vision and mission, in black — the pale
   pink one all but vanished against the paper. (Winnie, 15 Aug 2026) */
.book-spine img {
  filter: brightness(0) saturate(100%);
  opacity: .72;
}

/* ==========================================================================
   24. THE BOOK STILL READS AS A BOOK ON A PHONE (24 Aug 2026, Winnie)
   The mobile pass had stripped the paper back to a plain sheet: page edges
   hidden, the spine reduced to a bare logo on a transparent patch. It looked
   like a piece of paper rather than an open book.
   The spread cannot sit side by side at 390px, so the fold turns through 90
   degrees: the crease runs ACROSS the card between the two pages instead of
   down between them. Same three ingredients as the desktop spine — paper
   curving into the gutter, a crease line, the logo medallion resting on it.
   ========================================================================== */
@media (max-width: 900px) {
  .book {
    position: relative;
    /* the stacked page edges, as if more leaves sit under this one */
    box-shadow:
      0 24px 46px -32px rgba(42, 36, 56, 0.32),
      0 3px 0 -1px #FBF7F1,
      0 4px 0 -1px rgba(42, 36, 56, 0.07),
      0 7px 0 -2px #FBF7F1,
      0 8px 0 -2px rgba(42, 36, 56, 0.05);
  }

  .book-spine {
    display: block !important;
    position: relative !important;
    height: clamp(56px, 13vw, 76px) !important;
    padding: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
  }
  /* the paper curving down into the crease and back out again */
  .book-spine::after {
    content: '';
    position: absolute;
    left: 0; right: 0; top: 0; bottom: 0;
    background: linear-gradient(180deg,
      rgba(42, 36, 56, 0)    0%,
      rgba(42, 36, 56, 0.05) 34%,
      rgba(42, 36, 56, 0.11) 47%,
      rgba(255, 252, 247, 0.95) 50%,
      rgba(42, 36, 56, 0.11) 53%,
      rgba(42, 36, 56, 0.05) 66%,
      rgba(42, 36, 56, 0)    100%);
    /* the crease fades out before the card's edges, so it reads as a fold in
       the paper rather than a rule drawn across it */
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 40%, transparent 46%, transparent 54%, #000 60%, #000 88%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 40%, transparent 46%, transparent 54%, #000 60%, #000 88%, transparent 100%);
  }
  /* the crease itself — one hairline of light along the bottom of the fold */
  .book-spine::before {
    content: '' !important;
    display: block !important;
    position: absolute !important;
    left: 12% !important;
    right: 12% !important;
    top: 50% !important;
    height: 1px !important;
    background: linear-gradient(90deg,
      rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 30%,
      rgba(255,255,255,0.9) 70%, rgba(255,255,255,0) 100%) !important;
    /* a gap in the middle so the crease meets the mark instead of crossing it */
    -webkit-mask-image: linear-gradient(90deg, #000 0 42%, transparent 42% 58%, #000 58% 100%) !important;
            mask-image: linear-gradient(90deg, #000 0 42%, transparent 42% 58%, #000 58% 100%) !important;
  }
  /* The mark is the desktop spine's mark, unchanged: same 29px square, same
     0.72 opacity, no pill behind it. It was being squashed to 34x22 by padding
     inside a fixed width, and the cream pill it sat on read as a dark lozenge
     because the logo is filtered to a solid silhouette. (24 Aug 2026, Winnie) */
  .book-spine img {
    position: absolute !important;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
    width: 29px !important;
    height: 29px !important;
    padding: 0 !important;
    background: transparent !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    object-fit: contain;
  }
}

/* The plum magnet (.book::after) and the shadow it casts (.book::before) were
   a noticeboard detail from the phase when the mobile spread was a pinned
   note. Now that the card is a book with a fold, a magnet on it makes no
   sense — and it was the dark purple dome sitting on the top edge.
   (24 Aug 2026, Winnie) */
@media (max-width: 900px) {
  .book::before,
  .book::after { display: none !important; content: none !important; }
}


/* ===========================================================================
   ONE GLASS BUBBLE, EVERYWHERE (25 Aug 2026, Winnie: "remove the white colour
   outline for all the glass bubble." then "this is very good example of the
   glass bubble. all follow this for the colour-adjust.")

   The reference is the Taegyo care orb on Prenatal Education. Its recipe, used
   verbatim below: a small bright ellipse of a catchlight at 30/20, a wider
   soft one behind it, a bounce at 76/82 where light comes back off the page,
   and a faint violet-grey deepening from 56% out to the edge over a 34% white
   body. Roundness comes entirely from that shading.

   What is NOT carried over is the rim. Every one of these carried a white
   ring — `inset 0 0 0 1.5px rgba(255,255,255,.75)` or `0 0 0 1px` outside —
   and at bubble sizes that reads as a drawn outline rather than as glass. The
   two inset shadows do the edge instead: shade at the lower left, light at the
   upper right.
   =========================================================================== */
.orb-bubble,
.trust--bubbles .trust-icon,
.tracking-visual .app-card-icon,
.hero--bubbles .bubble-glass {
  background:
    radial-gradient(ellipse 22% 16% at 30% 20%,
      rgba(255,255,255,.98) 0%, rgba(255,255,255,.42) 42%, rgba(255,255,255,0) 100%),
    radial-gradient(circle at 30% 26%,
      rgba(255,255,255,.46) 0%, rgba(255,255,255,.12) 28%, rgba(255,255,255,0) 56%),
    radial-gradient(circle at 76% 82%,
      rgba(255,255,255,.42) 0%, rgba(255,255,255,0) 34%),
    radial-gradient(circle at 50% 50%,
      rgba(146,130,168,0) 56%, rgba(146,130,168,.10) 82%, rgba(146,130,168,.20) 100%),
    rgba(255,255,255,.34) !important;
  box-shadow:
    inset -7px -9px 18px rgba(150,135,175,.15),
    inset 7px 8px 15px rgba(255,255,255,.6),
    0 14px 26px -14px rgba(120,100,140,.55) !important;
  border: 0 !important;
}
