picture {
  display: contents;
}

/* ───────────────────────────────────────────────────────────────────
   TWH FigmaImport R1 — recreated from the Figma design
   (node 40017104:15741, "Home Landing page").
   Colors, layout, typography mirror the Figma file; brand-system
   rules deliberately not enforced where the Figma differs.
   ─────────────────────────────────────────────────────────────────── */

:root {
  --purple: #919AFE;
  --purple-soft: #A8AFFE;
  /* R6 X1 audit fix: was #6B6FE6 which gave 3.4–4.2:1 on lavender — failed
     WCAG AA. #4F4FB0 measures 5.5+ on every lavender / white / pale-lime
     background the eyebrow + inline link colours sit over. */
  --purple-deep: #4F4FB0;
  --lavender-bg: #E9E6FE;
  /* hero background */
  --lavender-tint: #F4F1FE;
  /* mid sections */
  --lime: #C7D983;
  --lime-soft: #E4ECC0;
  --navy: #0E1B4D;
  /* testimonials + footer */
  --navy-deep: #081234;
  --dark-purple: #2E2A6E;
  /* snap-a-bill section */
  --ink: #0F1226;
  /* primary heading */
  --blue-ink: #2A316E;
  --ink-2: #2A2C44;
  --grey-text: #7B7F9C;
  --slate: #4A4E68;
  --slate-2: #6E7290;
  --line: #E3E5F2;
  --white: #FFFFFF;
  --card: #FFFFFF;
  --pale-lime: #F8FAEF;
  --Off-white-grey: #F9F9FB;

  /* pillar pastels */
  --pill-lime: #E7EFC8;
  --pill-lavender: #DDE1FE;
  --pill-purple: #BAA8F4;
  --pill-blue: #B7D6FA;

  /* V5 audit fix: about-page surface + secondary-text color hoisted from
     the local .info-body alias block into global :root scope. */
  --surface-light-purple: #F4F0FF;
  --fg-secondary: #414241;

  /* V3 audit fix: pricing.html h3 type scale. The legacy stylesheet
     drives plan-head + gift-plan h3 sizing today; explicit TWH classes
     below make the choice intentional and survive an eventual legacy
     CSS purge (X8). */
  --pricing-h3-size: 22px;
  --pricing-h3-size-mobile: 18px;

  --sans: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --serif: "Playfair Display", "Times New Roman", serif;

  --max: 1280px;
  --pad-x: 24px;
}

/* ───── RESET ───── */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: clip;
}

body {
  font-family: var(--sans);
  font-weight: 400;
  color: var(--ink-2);
  background: var(--white);
  line-height: 1.5;
  overflow-x: clip;
}

img,
svg,
video {
  max-width: 100%;
  display: block;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font-family: inherit;
  cursor: pointer;
  background: none;
  border: 0;
}

ul,
ol {
  list-style: none;
}

/* Italic display serif accent (matches Figma's emphasis style) */
em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  color: var(--purple);
}

/* ───── EYEBROW ───── */
.eyebrow {
  font-size: 16px;
  /* X4 audit fix: 13 → 14 (mobile readability floor) */
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* R6 X1 audit fix: was var(--purple) #919AFE which measured 2.4:1 on
     white sections — failed WCAG AA (needs 4.5). --purple-deep #6B6FE6
     measures ≥ 5:1 on every light background the eyebrow sits over. */
  color: var(--purple);
  margin-bottom: 18px;
}

.eyebrow--on-dark {
  /* R6 X1 audit fix: was var(--purple-soft) #A8AFFE which measured 2.05:1
     on the navy --snap background — failed WCAG AA. White measures
     ~14.5:1 (AAA) and matches the existing snap-sub body colour. */
  /* color: #FFFFFF; */
  color: var(--purple);
}

/* ═══════════════════════════════════════════════════════════════════
   NAV — floating pill
   ═════════════════════════════════════════════════════════════════ */
.nav {
  position: sticky;
  top: 12px;
  z-index: 100;
  padding: 0 var(--pad-x);
  pointer-events: none;
}

.nav-pill {
  pointer-events: auto;
  /* Slimmed to 720px; left group (brand+sep) and right group (links+CTA)
     sit at the two ends. */
  max-width: 720px;
  margin: 0 auto;
  box-sizing: border-box;
  /* background: var(--white); */
  /* background: #FFFFFFCC; */
  background: color-mix(in srgb, var(--white) 80%, transparent);
  backdrop-filter: blur(12px);

  border-radius: 9999px;
  /* Mobile (<640px): equal 6px inset all around. Tablet/desktop override
     padding in their own media queries, so this value only applies here. */
  padding: 6px;
  display: flex;
  align-items: center;
  gap: 12px;
  box-shadow: 0 14px 40px -8px rgba(20, 30, 70, 0.12), 0 2px 6px rgba(20, 30, 70, 0.05);
}

/* Left / right groups. display:contents below 1024px means the containers
   "disappear" and brand/sep/links/CTA lay out as direct pill children exactly
   as before — so tablet and mobile are unaffected. They become real flex
   groups only on desktop (see the min-width:1024px block). */
.nav-left,
.nav-right {
  display: contents;
}

.nav-brand {
  display: flex;
  align-self: stretch;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: -0.005em;
}

.nav-mark {
  align-self: center;
  display: grid;
  place-items: center;
  box-sizing: border-box;
  /* Padding lives on the parent .nav-pill now (6 px around the mark);
     keeping this rule clean — no inner padding. */
  padding-left: 0px;
}

.nav-mark img {
  /* Desktop brand height 44px (width auto-scales). Tablet 38px, mobile 30px
     via the media queries below. */
  height: 48px;
  width: auto;
}

/* Mobile nav (the hamburger pill, < 1024 px) needs a smaller brand mark
   so it doesn't dominate the compressed pill. 48 × 0.65 = 31.2 → 31 px,
   a 35 % reduction. Width remains auto so the wordmark stays in proportion. */
@media (max-width: 1023px) {
  .nav-mark img {
    height: 48px;
  }
}

/* Tablet (640–1023px): proportionate to desktop — pill 48px tall, brand 38px.
   Comes after the rule above so it overrides only the tablet range; mobile
   (< 640px) keeps the 30px brand and its existing pill height (unchanged). */
@media (min-width: 640px) and (max-width: 1023px) {
  .nav-pill {
    height: 60px;
    padding: 6px;
  }

  .nav-mark img {
    height: 48px;
  }
}

.nav-sep {
  width: 2px;
  height: 32px;
  background: var(--line);
}

.nav-links {
  display: none;
  /* Tight gap so the links sit close to each other. The group is pushed to the
     right edge (flex:1 on flat pages; .nav-right margin-left:auto on desktop). */
  gap: 6px;
  flex: 1;
  justify-content: flex-end;
}

.nav-links a {
  /* Content-width (no fixed slot) so the links read compactly and close
     together. */
  flex: 0 0 auto;
  width: auto;
  padding: 8px 14px;
  font-size: 18px;
  font-weight: 500;
  text-align: center;
  white-space: nowrap;
  /* color: var(--ink-2); */
  color: #4B5563;
  border-radius: 9999px;
}

.nav-links a:hover {
  background: var(--lavender-tint);
}

.nav-cta {
  display: none;
  /* Content-width pill. */
  flex: 0 0 auto;
  width: auto;
  padding: 11px 22px;
  justify-content: center;
  text-align: center;
  white-space: nowrap;
  background: var(--purple);
  color: #ffffff;
  border-radius: 9999px;
  font-size: 16px;
  font-weight: 500;
}

.nav-cta:hover {
  background: var(--purple);
}

.nav-menu {
  width: 40px;
  height: 40px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  justify-content: center;
  margin-left: auto;
}

.nav-menu span {
  width: 20px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
}

.nav-mobile {
  /* Center the drawer and cap its width at 80% of the nav padding box
     so it's noticeably narrower than the full pill row. */
  margin: 12px auto 0;
  max-width: 80%;
  background: var(--white);
  border-radius: 24px;
  padding: 16px 24px;
  box-shadow: 0 14px 40px -8px rgba(20, 30, 70, 0.12);
  display: flex;
  flex-direction: column;
  /* .nav header has pointer-events: none so the surrounding hero area
     under the floating pill remains clickable. The pill itself re-enables
     with .nav-pill { pointer-events: auto }; the drawer needs the same
     so its anchor links actually receive taps. */
  pointer-events: auto;
}

.nav-mobile a {
  padding: 14px 0;
  font-size: 16px;
  font-weight: 500;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}

.nav-mobile a:last-child {
  border-bottom: 0;
}

.nav-mobile-cta {
  margin-top: 12px;
  background: var(--purple);
  color: var(--white) !important;
  border-radius: 9999px;
  text-align: center;
  font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════════════
   HERO
   ═════════════════════════════════════════════════════════════════ */
.hero {
  position: relative;
  background: var(--white);
  margin-top: -88px;
  padding: 168px 0 360px;
  overflow: hidden;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("assets/img/hero-banner-family.png");
  background-image: image-set(url("assets/img/hero-banner-family.webp") type("image/webp"), url("assets/img/hero-banner-family.png") type("image/png"));
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0.5;
  pointer-events: none;
}

.hero-watermark {
  position: absolute;
  right: -10%;
  top: calc(-10% + 300px);
  width: 70%;
  aspect-ratio: 1;
  opacity: 0.10;
  background: radial-gradient(circle at 30% 50%, var(--purple) 0%, transparent 60%);
  pointer-events: none;
}

.hero-inner {
  position: relative;
  max-width: var(--max);
  margin: 0 auto;
  padding: 60px var(--pad-x) 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.hero-copy {
  width: 100%;
  text-align: left;
}

.hero-h1 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(40px, 9vw, 80px);
  line-height: 1.16;
  letter-spacing: -0.035em;
  color: var(--ink);
}

.hero-h1 em {
  font-size: 1em;
}

.hero-sub {
  margin-top: 24px;
  max-width: 65ch;
  /* X4: 620px → 65ch (scales with font size) */
  font-size: clamp(16px, 1.4vw, 18px);
  color: var(--slate);
  font-weight: 500;
}

.hero-phones {
  margin-top: 48px;
  position: relative;
  width: 100%;
  max-width: 880px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 0;
}

.hero-phone {
  flex: 0 1 auto;
  max-width: 70%;
  /* border-radius: 52px; */
  overflow: hidden;
  /* background: #ddd; */
  /* box-shadow: 0 30px 60px -20px rgba(20, 30, 70, 0.25); */
}

.hero-phone img {
  display: block;
  width: 70%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
}

.hero-phone--left {
  z-index: 1;
}

.hero-phone--center {
  z-index: 3;
  box-shadow: 0 40px 80px -20px rgba(20, 30, 70, 0.35);
}

.hero-phone--right {
  z-index: 1;
}

.hero-phone--right img {
  margin-left: auto;
  margin-right: 0;
}

/* Store badges inside the hero copy block */
.hero-app-badges {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: center;
  gap: 48px;
  margin-top: 32px;
}

.hero-app-badge {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.hero-app-badge img {
  height: 56px;
  width: auto;
  border-radius: 12px;
}

/* ═══════════════════════════════════════════════════════════════════
   WHY — Built for the way Indian homes
   ═════════════════════════════════════════════════════════════════ */
.why {
  background: var(--white);
  padding: 80px 0 100px;
}

.why-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  gap: 40px;
  grid-template-columns: 1fr;
  align-items: center;
}

.why-copy {
  max-width: 560px;
}

.why-h2 {
  font-weight: 800;
  font-size: clamp(40px, 6vw, 72px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.why-h2 em {
  font-size: 1em;
}

.why-sub {
  margin-top: 28px;
  font-size: 16px;
  color: var(--slate);
  font-weight: 500;
  max-width: 480px;
}

.why-visual {
  display: flex;
  justify-content: center;
}

.why-phone {
  width: 280px;
  border-radius: 52px;
  overflow: hidden;
  background: #ddd;
  box-shadow: 0 30px 60px -20px rgba(20, 30, 70, 0.25);
}

.why-phone img {
  width: 100%;
  height: auto;
}

.why-second-phone {
  margin-bottom: 60px;
  display: flex;
  justify-content: center;
  padding: 0 var(--pad-x);
  /* background-image: url("assets/img/bg-why-home.png"); */
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.why-second-phone figure {
  /* Fixed-height clip window showing only the BOTTOM slice of the phone screenshot
     (image anchored bottom:0). The hero phone lands exactly on this at the pin, so
     --why-slice-h must equal the hero's final slice height. */
  --why-slice-h: 210px;
  position: relative;
  width: 360px;
  height: var(--why-slice-h);
  overflow: hidden;
  border-bottom-right-radius: 88px;
  border-bottom-left-radius: 88px;
  background: #ddd;
  box-shadow: 0 30px 60px -20px rgba(20, 30, 70, 0.25);
}

.why-second-phone img {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: auto;
  display: block;
}

/* ═══════════════════════════════════════════════════════════════════
   FEATURES — 4-up row
   ═════════════════════════════════════════════════════════════════ */
.features {
  background: var(--white);
  background-image: url("assets/img/bg-why-home.png");
  background-image: image-set(url("assets/img/bg-why-home.webp") type("image/webp"), url("assets/img/bg-why-home.png") type("image/png"));
  /* Anchor the bg image to the bottom edge of the section, fill the section
     width, and set the bg image's height to (section height − 82 px) so the
     top of the image lands at the vertical midpoint of the .why-second-phone
     image. At desktop the phone figure is 560 px wide; its image renders
     ~164 px tall (760 × 223 native aspect), so its vertical midpoint sits at
     ~82 px from the top of the section. As the viewport widens, the section
     width changes (bg width stretches horizontally with it) but the section
     height stays roughly constant — so the bg image's height does NOT
     stretch vertically, preserving the visual relationship between the bg
     and the phone midpoint. */
  background-size: 100% calc(100% - 0px);
  background-position: center bottom;
  background-repeat: no-repeat;
  padding: 0px 0 100px;
}

.features-inner {
  max-width: var(--max);
  margin: 80px auto;
  padding: 0 var(--pad-x);
  display: grid;
  gap: 32px;
  grid-template-columns: 1fr;
}

.feature h3 {
  font-size: 17px;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 8px;
}

.feature p {
  font-size: 14px;
  line-height: 1.55;
  color: var(--slate);
  font-weight: 500;
}

.feature-ic {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--lime);
  padding: 4px;
  margin-bottom: 14px;
  position: relative;
}

.feature-ic--doc {
  background: #dce5bb00 url("assets/icons/doc-icon.png") center / contain no-repeat;
  background-image: image-set(url("assets/icons/doc-icon.webp") type("image/webp"), url("assets/icons/doc-icon.png") type("image/png"));
}

.feature-ic--staff {
  background: #dde1fe00 url("assets/icons/staff-icon.png") center / contain no-repeat;
  background-image: image-set(url("assets/icons/staff-icon.webp") type("image/webp"), url("assets/icons/staff-icon.png") type("image/png"));
}

.feature-ic--fin {
  background: #fceeda00 url("assets/icons/fin-icon.png") center / contain no-repeat;
  background-image: image-set(url("assets/icons/fin-icon.webp") type("image/webp"), url("assets/icons/fin-icon.png") type("image/png"));
}

.feature-ic--task {
  background: #e4ecc000 url("assets/icons/task-icon.png") center / contain no-repeat;
  background-image: image-set(url("assets/icons/task-icon.webp") type("image/webp"), url("assets/icons/task-icon.png") type("image/png"));
}

.feature-ic--budget {
  background: transparent url("assets/icons/budget-icon.svg") center / contain no-repeat;
}

.feature-ic--calendar {
  background: transparent url("assets/icons/calendar-icon.svg") center / contain no-repeat;
}

.feature-ic--bill {
  background: transparent url("assets/icons/bill-icon.svg") center / contain no-repeat;
}

.feature-ic--location {
  background: transparent url("assets/icons/location-icon.svg") center / contain no-repeat;
}

/* ═══════════════════════════════════════════════════════════════════
   SNAP A BILL — dark purple, two column
   ═════════════════════════════════════════════════════════════════ */
.snap {
  background: #ffffff;
  padding: 80px 0;
  position: relative;
  /* clip-path instead of overflow:hidden so the inner .snap-visual sticky
     can pin to the viewport (overflow on ancestor breaks sticky). */
  clip-path: inset(0);
}

.snap::before {
  content: "";
  position: absolute;
  right: -10%;
  top: -20%;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.08), transparent 60%);
}

.snap-inner {
  position: relative;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  gap: 48px;
  grid-template-columns: 1fr;
  align-items: start;
  /* start, not center — text scrolls naturally */
}

.snap-copy {
  color: #111827;
}

.snap-h2 {
  font-weight: 700;
  font-size: clamp(32px, 5.5vw, 56px);
  line-height: 1.15;
  letter-spacing: -0.03em;
  color: #111827;
}

.snap-h2 em {
  color: var(--lime);
  font-size: 1em;
}

.snap-sub {
  /* Subtext to the h2: tight 12px gap, and neutral-600 (vs the checks'
     #111827) so it reads one hierarchy notch below the checklist. */
  margin-top: 12px;
  font-size: 18px;
  line-height: 1.6;
  color: #4B5563;
  max-width: 520px;
  font-weight: 500;
}

.snap-checks {
  margin-top: 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ═══ FLAG — show / hide every .snap-checks checklist site-wide ═══
   Default: shown. To hide the checklists (and their mobile "Know more"
   pill) across ALL breakpoints, add the class `snap-checks-hidden` to
   the <body> tag; remove it to show them again. The !important override
   wins over every responsive display rule below. */
body.snap-checks-hidden .snap-checks,
body.snap-checks-hidden .snap-checks-toggle {
  display: none !important;
}

.snap-checks li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 18px;
  color: #111827;
  font-weight: 500;
}

.check {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  background: var(--purple);
  border-radius: 50%;
  position: relative;
  margin-top: 2px;
}

.check::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 4px;
  width: 4px;
  height: 8px;
  border-right: 2px solid var(--white);
  border-bottom: 2px solid var(--white);
  transform: rotate(45deg);
}

.snap-visual {
  display: flex;
  justify-content: center;
  /* On mobile the phone sits below the copy in flow (no sticky). */
}

/* The screenshot PNG already contains the phone bezel — no frame, no
   border, no background, no rounded corners on the wrapper. */
.snap-phone {
  width: 280px;
  border-radius: 54px;
  overflow: visible;
  /* JS sets `style.opacity` per phone for cross-fade. Default = 1 so the
     image is visible before JS attaches. */
  opacity: 1;
  transition: opacity 80ms linear;
  will-change: opacity;
  border: 8px solid var(--Neutral-800, #E5E7EB);
  /* border: 8px solid var(--Neutral-800, #F9F9FB); */
  /* Subtle neutral-grey shadow (hueless black at low alpha — no colour
     tinge), soft and downward. Shared across all breakpoints. */
  box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.38);
  /* box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.18); */
}

.snap-phone img {
  width: 100%;
  height: auto;
  border-radius: 48px;
  display: block;
}

/* Pinned-scroll wrappers (added for the desktop snap choreography) are
   layout-inert until the ≥1024px rules activate them, so mobile/tablet
   layout is byte-for-byte unchanged. */
.snap-track,
.snap-stage {
  display: contents;
}

/* .snap-checks (and its mobile Know-more toggle) now live INSIDE .snap-copy,
   so the mobile/tablet stacking order is simply copy → phone. On desktop
   these orders are inert because the blocks switch to absolute positioning. */
.snap-copy {
  order: 1;
}

.snap-visual {
  order: 2;
}

/* ═══════════════════════════════════════════════════════════════════
   WHAT SETS US APART — 2 photo cards with chat phones
   ═════════════════════════════════════════════════════════════════ */
.apart {
  background: var(--white);
  /* Rhythm pass (Jul 2026): bottom 100 → 64. With .lgn's 72px top the
     white→white junction lands at ~136px (was 172). */
  padding: 100px 0 64px;
}

.apart-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
}

.apart-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 80px;
  flex-wrap: wrap;
}

.apart-h2 {
  font-weight: 800;
  font-size: clamp(36px, 5.5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.apart-h2 em {
  font-size: 1em;
}

.apart-sub {
  font-size: 16px;
  color: var(--slate);
  font-weight: 500;
  max-width: 420px;
  text-align: right;
}

/* ═══════════════════════════════════════════════════════════════════
   APART CAROUSEL — circular, peek-and-fade design (Aug 2025 figma)
   • viewport: overflow:hidden + mask-image creates a fade-to-transparent
     ribbon on the left/right 8% of the viewport — the "circular feel"
   • track: horizontal flexbox of cards; JS centres the active card
     using transform translateX
   • each card: ~ 78% of viewport wide so 10–11% of the previous/next
     card peeks in on each side
   • arrows: round buttons absolutely positioned over the viewport edges
   • JS triples the cards into [clones | originals | clones] and seamlessly
     jumps back on completion — gives true circular looping
   ═════════════════════════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════════════════════════
   APART CAROUSEL — one full Figma card in view at a time (Aug 2025 figma)
   • stage: card-sized frame, centred; holds the scroll viewport + arrows
   • viewport: native horizontal scroll with x-mandatory snap; one card
     fills 100% of the viewport so exactly one card is visible at rest
   • card: an <img> of the exported Figma card — natural aspect ratio is
     preserved so nothing is distorted; lavender placeholder until the
     PNG is dropped into assets/img
   • arrows: small frosted "liquid glass" buttons at the card's left/right
     edges; read on both light and dark cards
   • dots: one per card, generated in JS; active dot widens to a pill
   ═════════════════════════════════════════════════════════════════ */
.apart-carousel {
  position: relative;
  margin-top: 86px;
  width: 100%;
}

.apart-stage {
  position: relative;
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
}

.apart-viewport {
  position: relative;
  width: 100%;
  border-radius: 32px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  -ms-overflow-style: none;
  scrollbar-width: none;
}

.apart-viewport::-webkit-scrollbar {
  display: none;
}

.apart-track {
  display: flex;
  flex-wrap: nowrap;
}

.apart-card {
  flex: 0 0 100%;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}

.apart-card-img {
  display: block;
  width: 100%;
  height: auto;
  /* Real card-asset ratio (2160×1360 — matches the actual PNG/WebP files;
     the old 1960×1560 value reserved ~26% extra height before the lazy
     images loaded, making everything below jump up on first interaction).
     `auto` keeps the loaded image's natural ratio
     authoritative on load; the value only reserves height pre-load to avoid
     layout shift. The rounded corners are baked into the PNG (transparent
     corners), so no border-radius here — and a transparent background so the
     navy cards' corners reveal the section behind, not a tint. */
  aspect-ratio: auto 2160 / 1360;
  background: transparent;
}

/* Arrows — small frosted "liquid glass" controls at the card edges.
   Neutral frosted panel + dark glyph reads on both the light (lavender)
   and dark (navy) cards. */
/* Nav row below the carousel — same design as the testimonials carousel
   ([prev] dots [next], centred): arrows are static flex items, never
   overlaying the cards. Glass palette stays the light-surface variant
   (dark glyph) since this section sits on white. */
.apart-nav {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 18px;
  /* 16px separation from .apart-stage above. */
  margin-top: 48px;
}

.apart-arrow {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 9999px;
  display: grid;
  place-items: center;
  cursor: pointer;
  color: #2b2f44;
  background: rgba(255, 255, 255, 0.22);
  -webkit-backdrop-filter: blur(10px) saturate(150%);
  backdrop-filter: blur(10px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.45);
  box-shadow:
    0 4px 14px rgba(20, 30, 70, 0.14),
    inset 0 1px 1px rgba(255, 255, 255, 0.55);
  transition: background 200ms ease, transform 200ms ease;
}

.apart-arrow:hover,
.apart-arrow:focus-visible {
  background: rgba(255, 255, 255, 0.36);
  transform: scale(1.07);
  outline: none;
}

.apart-arrow:active {
  transform: scale(0.96);
}

/* (The old gutter-lift offsets for the overlay arrows were removed —
   arrows now live in the static .apart-nav row below the carousel.) */

/* Pagination dots — one per card; active dot widens to a brand-blue pill. */
.apart-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  /* Vertical offset now lives on the .apart-nav row (4px margin + the
     dots' 8px hit-area padding = 12px visual gap below the viewport). */
  margin-top: 0;
}

.apart-dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: 9999px;
  background: rgba(20, 30, 70, 0.18);
  cursor: pointer;
  transition: width 240ms cubic-bezier(0.22, 1, 0.36, 1), background 240ms ease;
}

.apart-dot:hover {
  background: rgba(20, 30, 70, 0.32);
}

.apart-dot.is-active {
  /* Selected pill halved: 26px → 13px. */
  width: 13px;
  background: #5C6DFB;
}

@media (prefers-reduced-motion: reduce) {
  .apart-viewport {
    scroll-behavior: auto;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   PILLARS — Your family data, sticky-note style
   ═════════════════════════════════════════════════════════════════ */
.pillars {
  background: var(--white);
  /* Rhythm pass (Jul 2026): top 100 → 80 (pairs with .lgn's 48px bottom);
     bottom stays 100 — the white→navy testi boundary segregates itself. */
  padding: 80px 0 100px;
}

.pillars-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0px var(--pad-x);
}

.pillars-head {
  max-width: 920px;
  margin-bottom: 64px;
}

.pillars-h2 {
  font-weight: 700;
  font-size: clamp(36px, 5.2vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.pillars-h2 em {
  font-size: 1em;
}

.pillars-sub {
  margin-top: 20px;
  font-size: 16px;
  color: var(--slate);
  max-width: 720px;
  font-weight: 500;
}

.pillar-grid {
  display: grid;
  gap: 100px;
  grid-template-columns: 1fr;
}

.pillar {
  padding: 16px 24px 30px;
  border-radius: 24px;
  transform: rotate(-2deg);
  box-shadow: 0 21px 42px -15px rgba(20, 30, 70, 0.18);
  position: relative;
}

.pillar:nth-child(2) {
  transform: rotate(1deg);
}

.pillar:nth-child(3) {
  transform: rotate(-3deg);
}

.pillar:nth-child(4) {
  transform: rotate(2deg);
}

.pillar--lime {
  background: var(--pill-lime) url("assets/img/bg-pillar-grid-card1.png") center / 200% 200% no-repeat;
  /* background-image: image-set(url("assets/img/bg-pillar-grid-card1.png") type("image/webp"), url("assets/img/bg-pillar-grid-card1.png") type("image/png")); */
}

.pillar--lavender {
  background: var(--pill-lavender);
}

.pillar--purple {
  background: var(--pill-purple);
}

.pillar--blue {
  background: var(--pill-blue);
}

.pillar-ic {
  width: 180px;
  height: 180px;
  border-radius: 24px;
  background: transparent;
  margin-bottom: 18px;
}

.pillar-ic img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: left;
}

.pillar h3 {
  font-size: 12px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--blue-ink);
  margin-bottom: 12px;
}

.pillar p {
  font-size: 16px;
  line-height: 1.5;
  color: var(--grey-text);
  font-weight: 500;
}

/* ═══════════════════════════════════════════════════════════════════
   TESTIMONIALS — Running our home (dark navy)
   ═════════════════════════════════════════════════════════════════ */
.testi {
  background: var(--navy);
  padding: 100px 0;
  position: relative;
  overflow: hidden;
}

.testi::before {
  content: "";
  position: absolute;
  left: -8%;
  top: 20%;
  width: 40%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(145, 154, 254, 0.18), transparent 60%);
}

.testi-inner {
  position: relative;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  gap: 48px;
  grid-template-columns: 1fr;
}

.testi-copy {
  color: var(--white);
}

.testi-h2 {
  font-weight: 700;
  font-size: clamp(40px, 6vw, 56px);
  line-height: 1.15;
  letter-spacing: -0.03em;
  color: var(--white);
}

.testi-h2 em {
  font-size: 1em;
  color: var(--purple-soft);
}

.testi-sub {
  margin-top: 28px;
  font-size: 16px;
  color: rgba(255, 255, 255, 0.62);
  max-width: 420px;
  font-weight: 500;
}

.testi-cols {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}

.testi-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.testi-card {
  background: rgba(20, 30, 80, 0.55);
  border: 1px solid rgba(145, 154, 254, 0.22);
  border-radius: 20px;
  padding: 18px 20px 20px;
  backdrop-filter: blur(8px);
}

/* Alternating card backgrounds — odd cards on solid #021C45,
   even cards on white at 6% (a soft translucent panel). */
.testi-col .testi-card:nth-child(odd) {
  background: #021C45;
}

.testi-col .testi-card:nth-child(even) {
  background: rgba(255, 255, 255, 0.06);
}

.testi-card header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.testi-ava {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, #EC8B6A, #8C3A2A);
  flex-shrink: 0;
}

.testi-card header strong {
  display: block;
  font-size: 14px;
  font-weight: 700;
  color: var(--white);
  line-height: 1.2;
}

.testi-card header span {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
  font-weight: 500;
}

.testi-card p {
  font-size: 13.5px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.78);
  font-weight: 500;
}

/* ═══════════════════════════════════════════════════════════════════
   FAQ — Questions Answered
   ═════════════════════════════════════════════════════════════════ */
.faq {
  background: var(--white);
  padding: 100px 0;
}

.faq-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  gap: 48px;
  grid-template-columns: 1fr;
}

.faq-copy {
  max-width: 420px;
}

.faq-h2 {
  font-weight: 700;
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.faq-h2 em {
  font-size: 1em;
}

.faq-sub {
  margin-top: 18px;
  max-width: 65ch;
  /* X4: add reading-width cap */
  font-size: 15px;
  color: var(--slate);
  font-weight: 500;
}

.faq-sub a {
  /* R6 X1 audit fix: inline body link — was --purple #919AFE at 2.4:1 on
     white. --purple-deep #4F4FB0 measures 6.8:1 (AAA). */
  color: var(--purple-deep);
  text-decoration: underline;
}

.faq-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.faq-list details {
  background: #F6F7F9;
  border-radius: 16px;
  padding: 0 22px;
}

.faq-list summary {
  list-style: none;
  padding: 20px 0;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 16px;
  cursor: pointer;
  font-size: 18px;
  font-weight: 500;
  /* color: var(--ink); */
  color: #111827;
}

.faq-list summary::-webkit-details-marker {
  display: none;
}

.faq-list summary::before {
  content: "+";
  font-size: 22px;
  font-weight: 400;
  color: var(--purple);
  width: 22px;
  text-align: center;
  flex-shrink: 0;
}

.faq-list details[open] summary::before {
  content: "−";
  color: var(--purple);
}

.faq-list details>div {
  padding: 0 0 22px 38px;
}

.faq-list details p {
  font-size: 14px;
  line-height: 1.6;
  /* color: var(--slate); */
  color: #374151;
  font-weight: 400;
}

/* ═══════════════════════════════════════════════════════════════════
   DOWNLOAD CTA — Start running your home today (matches Figma 40017332:1974)
   Full-bleed family photograph; copy top-left, wordmark top-right, store
   badges sitting low against the grass.
   ═════════════════════════════════════════════════════════════════════ */
.cta {
  background: var(--white);
  position: relative;
  overflow: hidden;
  padding: 0;
  min-height: clamp(560px, 56vw, 820px);
  isolation: isolate;
}

.cta-photo {
  position: absolute;
  inset: 0;
  /* background-image: url("assets/img/bg-start-running-home.png"); */
  background-image: image-set(url("assets/img/bg-start-running-home2.webp") type("image/webp"), url("assets/img/bg-start-running-home2.png") type("image/png"));
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  z-index: 0;
}

.cta-photo::after {
  /* Soft top fade so the headline + sub read crisply against the photo */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0.18) 28%, transparent 55%);
  pointer-events: none;
}

/* Logo + wordmark — top-right */
.cta-brand {
  position: absolute;
  top: 60px;
  right: 56px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--ink);
}

.cta-brand-mark {
  display: inline-flex;
}

.cta-brand-mark img {
  height: 60px;
  width: auto;
}

.cta-brand-text {
  font-family: var(--sans);
  font-weight: 600;
  font-size: clamp(20px, 2.2vw, 28px);
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Headline + sub — top-left. Width allows the H2 to wrap to 2 lines
   ("Start running your" / "home better — today.") as in Figma. */
.cta-copy {
  position: relative;
  z-index: 1;
  /* Same centred container geometry as every other section's *-inner
     wrapper (max-width + auto margins + --pad-x inset), so .cta-h2 starts
     on the same vertical line as the other section headings. */
  max-width: var(--max);
  margin: 0 auto;
  /* padding-top matches .cta-brand top:60px so .cta-h2 and the brand logo
     share the same horizontal top edge. */
  padding: 60px var(--pad-x) 0;
}

.cta-h2 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(36px, 4.6vw, 56px);
  line-height: 1.15;
  letter-spacing: -0.035em;
  color: var(--ink);
  margin: 0;
}

.cta-h2 em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  color: var(--purple);
  font-size: 1em;
}

.cta-sub {
  margin-top: 18px;
  font-size: clamp(14px, 1.15vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  font-weight: 500;
  max-width: 520px;
}

/* Guard the CTA copy against the legacy legal-doc styles embedded in
   privacy/terms/parental-consent. Their bare `h2`/`p` selectors leak onto
   this shared section: a mobile accordion-capsule h2 (white background,
   purple left stripe, "+" ::after glyph, shadow) and justified/indented
   paragraphs. These class-qualified rules out-specify the bare element
   rules, so the headline sits directly on the photo and the sub copy
   renders exactly as on index.html. */
section.cta .cta-h2 {
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
  cursor: default;
}

section.cta .cta-h2::after {
  content: none;
}

/* terms.html only: its imported legal doc auto-numbers every bare h2 via
   CSS counters (h2::before { content: counter(section) ". " }) — which
   stamped a number onto the CTA headline too. Kill the generated prefix
   and keep the CTA h2 out of the document's numbering sequence. */
section.cta .cta-h2::before {
  content: none;
}

section.cta .cta-h2 {
  counter-increment: none;
}

section.cta .cta-sub {
  color: var(--ink-2);
  font-weight: 500;
  text-align: left;
  padding-left: 0;
  margin-bottom: 0;
}

/* App Store + Google Play badges — pinned over the grass, slightly
   inboard of centre (~ 38–55% from left at desktop, matching Figma) */
.cta-stores {
  position: absolute;
  z-index: 1;
  /* Centred across the full section width (was pinned at left: 38%). */
  left: 0;
  right: 0;
  justify-content: center;
  bottom: 14%;
  display: flex;
  flex-wrap: wrap;
  gap: 64px;
}

.cta-store {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.cta-store img {
  height: 64px;
  width: auto;
  border-radius: 16px;
}

.cta-store-ic {
  flex-shrink: 0;
}

.cta-store-text {
  display: inline-flex;
  flex-direction: column;
  line-height: 1.1;
}

.cta-store-sub {
  font-size: 10px;
  letter-spacing: 0.06em;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.86);
}

.cta-store-main {
  font-size: 18px;
  font-weight: 700;
  color: var(--white);
  letter-spacing: -0.01em;
}

/* ═══════════════════════════════════════════════════════════════════
   FOOTER
   ═════════════════════════════════════════════════════════════════ */
.footer {
  background: var(--white);
  color: rgba(255, 255, 255, 0.62);
  padding: 64px 0 28px;
}

/* Guard against the legacy legal-document styles embedded in
   privacy/terms/parental-consent: their bare `footer { margin-top: 40px;
   border-top: … }` selectors were written for the imported doc's own
   footer but also hit this site-wide one, opening a gap that showed the
   pages' lavender body as a purple band above the footer. The class-
   qualified selector out-specifies the bare element rules. */
footer.footer {
  margin-top: 0;
  border-top: 0;
}

/* Continued guard for the legal pages: the same legacy `footer` rule
   also sets text-align:center — which centres the inline-flex brand
   logo inside its column (≈100px right of the grid line) — and the
   bare `p` rule justifies + bottom-margins the footer text. Scoped to
   ≥640px so the mobile footer's own centring rules stay untouched. */
@media (min-width: 640px) {
  footer.footer {
    text-align: left;
  }

  footer.footer p {
    text-align: left;
    margin-bottom: 0;
    /* The legacy bare `p { padding-left: 20px }` rule indented the text
       20px right of the logo's left edge. */
    padding-left: 0;
  }
}

.footer-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  gap: 48px;
  grid-template-columns: 1fr;
  /* Mobile: brand → socials → cols, all stacked. Desktop overrides below
     turn row 1 into [brand | socials] and put cols on row 2 full-width. */
  grid-template-areas:
    "brand"
    "socials"
    "cols";
}

.footer-brand {
  grid-area: brand;
}

.footer-socials {
  grid-area: socials;
}

.footer-cols {
  grid-area: cols;
}

/* Social icons row — 72×72 (2× the 36 baseline), top-aligned with brand row */
.footer-socials {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.footer-socials a {
  display: inline-flex;
  width: 72px;
  height: 72px;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  transition: transform 200ms ease, opacity 200ms ease;
  opacity: 0.85;
}

.footer-socials a:hover {
  opacity: 1;
  transform: translateY(-1px);
}

.footer-socials img {
  width: 72px;
  height: 72px;
  display: block;
}

.footer-brand {
  max-width: 420px;
}

.footer-logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--white);
  font-weight: 700;
  font-size: 18px;
  /* Logo→blurb gap: 18px → 13.5px (75%). */
  margin-bottom: 13.5px;
  letter-spacing: -0.01em;
}

.footer-mark img {
  height: 56px;
  width: auto;
}

.footer-logo .dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  background: var(--lime);
  border-radius: 50%;
  margin: 0 1px;
  vertical-align: middle;
}

.footer-brand p {
  font-size: 14px;
  line-height: 1.5;
  /* Manrope Medium, neutral-600 */
  font-weight: 400;
  color: #4B5563;
}

.footer-cols {
  display: grid;
  gap: 36px;
  grid-template-columns: repeat(2, 1fr);
}

.footer-col h4 {
  font-size: 13px;
  /* Manrope Medium, neutral-600 */
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #4B5563;
  margin-bottom: 14px;
}

.footer-col a {
  /* X3 audit fix: vertical padding bumped 4 → 8 to lift tap-box from ~30 px to
     ~38 px (≥ 32 px WCAG-recommended). Footer columns are the worst mis-tap
     zone on mobile because of tight column stacking. */
  display: block;
  padding: 8px 0;
  font-size: 14px;
  /* Manrope SemiBold, neutral-700 */
  font-weight: 400;
  color: #4B5563;
}

.footer-col a:hover {
  /* Darken toward neutral-900 on hover — matches the new light-surface
     footer text scheme (base links are neutral-700 #374151). */
  color: #111827;
}

/* Desktop only: footer text steps up to 16px / 24px line height.
   Tablet and mobile keep the 13–14px base sizes above. */
@media (min-width: 1024px) {

  /* .footer-brand p, */
  /* .footer-col h4, */
  .footer-col a {
    font-size: 16px;
    line-height: 24px;
  }
}

/* X6 audit fix: placeholders for footer items whose destination doesn't
   exist yet (Blog, Press, Roadmap, Help centre, How it works, Setup
   guide, Data Processing, DPDP compliance). Rendered like a footer
   link visually but with no anchor (no broken in-page jump). */
.footer-tbd {
  display: block;
  padding: 8px 0;
  font-size: 14px;
  /* Was rgba(255,255,255,0.32) from the dark-footer era — invisible on a
     light surface. Light neutral keeps it recessive but renderable. */
  color: #9CA3AF;
  cursor: default;
}

.footer-meta {
  max-width: var(--max);
  margin: 40px auto 0;
  padding: 24px var(--pad-x) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 12px;
  /* Light-but-visible grey on the white surface — the stylesheet's own
     --grey-text token (also used for pillar body copy). */
  color: var(--grey-text);
  display: flex;
  /* Row layout: "Built with care in Mumbai" on the left, copyright on the right.
     The copyright <p> is first in the HTML; we use flex `order` to flip it
     visually without touching markup. */
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 6px 16px;
}

.footer-meta p:first-child {
  order: 2;
  text-align: right;
}

.footer-meta p:last-child {
  order: 1;
  text-align: left;
}

.footer-meta p {
  margin: 0;
}

/* ── Footer dividers ─────────────────────────────────────────────────
   1px #E5E7EB rules (3px radius) spanning the site's content grid —
   edge to edge of the centred max-width container at each breakpoint,
   NOT the full viewport. One above the link columns, one between
   .footer-inner and .footer-meta. Drawn as absolutely-positioned
   pseudo-elements so neither the footer HTML nor its layout changes. */
.footer-cols,
.footer-meta {
  position: relative;
}

.footer-cols::before,
.footer-meta::before {
  content: "";
  position: absolute;
  height: 1px;
  background: #E5E7EB;
  border-radius: 3px;
}

/* Midway into the grid gap above the link columns. .footer-cols already
   spans the grid content width, so 0/0 lands on the content edges. */
.footer-cols::before {
  top: -24px;
  left: 0;
  right: 0;
}

/* At the top edge of the meta strip — the .footer-inner / .footer-meta
   boundary. .footer-meta's own box includes the --pad-x side padding, so
   inset by it to align the line with the grid's content edges. */
.footer-meta::before {
  top: 0;
  left: var(--pad-x);
  right: var(--pad-x);
}

/* Breathing room above the columns divider — DOUBLE the previous gap
   between the row above and the grey line (tablet 24→48, desktop 12→24,
   mobile 8→16). Padding on the row-1 block pushes the second row (line
   included) down without moving the line relative to the columns below.
   On mobile the row directly above the line is the socials, not the
   brand, so the padding sits there. */
.footer-brand {
  padding-bottom: 24px;
}

@media (max-width: 639px) {
  .footer-brand {
    padding-bottom: 0;
  }

  .footer-socials {
    padding-bottom: 8px;
  }

  /* Mobile: hide the divider below the socials row (the columns line);
     the meta-strip divider stays. */
  .footer-cols::before {
    display: none;
  }
}

@media (min-width: 1024px) {
  .footer-brand {
    padding-bottom: 12px;
  }
}

/* On narrow mobile, stack vertically with copyright on top (HTML order). */
@media (max-width: 639px) {
  .footer-meta {
    flex-direction: column;
    align-items: flex-start;
  }

  .footer-meta p:first-child,
  .footer-meta p:last-child {
    order: 0;
    text-align: left;
  }
}

/* Mobile phone only (< 640px): horizontally centre the footer blocks.
   Tablet/desktop layout (≥ 640px) is untouched. */
@media (max-width: 639px) {
  .footer-brand {
    margin-left: auto;
    margin-right: auto;
    text-align: center;
  }

  .footer-socials {
    justify-content: center;
  }

  .footer-cols {
    justify-items: center;
    text-align: center;
  }

  .footer-meta {
    align-items: center;
    text-align: center;
  }

  .footer-meta p:first-child,
  .footer-meta p:last-child {
    text-align: center;
  }
}

/* CTA mobile (< 640px) — relax the heavy left-padding, drop the absolute
   wordmark down so it can't overlap the headline */
@media (max-width: 639px) {
  .cta {
    min-height: clamp(620px, 130vw, 760px);
  }

  .cta-brand {
    position: static;
    display: flex;
    justify-content: flex-end;
    padding: 24px var(--pad-x) 0;
  }

  .cta-brand-text {
    font-size: 18px;
  }

  .cta-copy {
    padding: 32px var(--pad-x) 0;
    max-width: none;
  }

  .cta-stores {
    position: static;
    padding: 28px var(--pad-x) 36px;
    flex-direction: column;
    left: auto;
    bottom: auto;
  }

  .cta-store {
    width: 100%;
    max-width: 280px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   RESPONSIVE
   ═════════════════════════════════════════════════════════════════ */
@media (min-width: 640px) {
  .features-inner {
    grid-template-columns: repeat(2, 1fr);
  }

  .pillar-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .apart-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-cols {
    grid-template-columns: repeat(4, 1fr);
  }

  /* Desktop: brand on left, socials on right (same row), cols span row 2 */
  .footer-inner {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "brand socials"
      "cols  cols";
  }

  .footer-socials {
    justify-self: end;
    /* push to the right edge of footer */
    align-self: start;
    /* top-align: icons sit on the same row as the brand logo */
  }
}

@media (min-width: 768px) {
  :root {
    --pad-x: 40px;
  }

  .testi-cols {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 1024px) {
  :root {
    --pad-x: 56px;
  }

  /* Nav: full pill with text links + CTA. Pill is 56px tall; brand 44px. */
  .nav-pill {
    height: 60px;
    padding: 6px;
  }

  /* Activate the two groups: brand+sep at the left, links+CTA at the right. */
  .nav-left {
    display: flex;
    align-items: center;
    gap: 20px;
  }

  .nav-right {
    display: flex;
    align-items: center;
    /* gap between the links group and the CTA */
    gap: 6px;
    /* push the whole right group to the right edge of the pill */
    margin-left: auto;
  }

  .nav-links {
    display: flex;
  }

  /* Inside the right group the links are content-width and close together;
     no flex-grow / left-padding needed (the group is positioned by .nav-right). */
  .nav-right .nav-links {
    flex: 0 0 auto;
    padding-left: 0;
  }

  .nav-cta {
    display: inline-flex;
    align-items: center;
  }

  .nav-menu {
    display: none;
  }

  .nav-mobile {
    display: none !important;
  }

  /* Hero: text block left, phones right, top-aligned */
  .hero {
    padding: 100px 0 80px;
  }

  .hero-inner {
    flex-direction: row;
    align-items: stretch;
    text-align: left;
    gap: 48px;
  }

  .hero-copy {
    flex: 1 1 0;
    max-width: 760px;
    display: flex;
    flex-direction: column;
  }

  /* Keep each forced line ("Your home," / "finally organised.") on one row so
     the headline stays exactly two rows; the copy column widens to fit it. */
  .hero-h1 {
    white-space: nowrap;
  }

  /* Push badges toward the bottom of the copy column to fill the lower-left space.
     Then nudge them down so they sit 48px above the hero section's bottom edge:
     the copy-column bottom is 32px (hero-inner pb) + 80px (hero pb) = 112px above
     the section edge, so translateY(64px) lands the badges at 48px. */
  .hero-app-badges {
    margin-top: auto;
    transform: translateY(64px);
  }

  .hero-sub {
    margin-left: 0;
    margin-right: 0;
    /* The headline now sits on two rows instead of three; add back the one lost
       line (80px × 1.16 ≈ 93px) here so the hero keeps its original height and
       the gap before the badges grows accordingly. */
    margin-bottom: 93px;
  }

  .hero-phones {
    margin-top: 0;
    flex: 1 1 0;
    gap: 0;
  }

  .hero-phone {
    max-width: 100%;
    flex-basis: auto;
  }

  /* Why: 2-column text+phone */
  .why-inner {
    grid-template-columns: 1.1fr 0.9fr;
    gap: 80px;
  }

  .why-phone {
    width: 320px;
  }

  .why-second-phone figure {
    width: 560px;
  }

  /* Features: 4-up */
  .features-inner {
    grid-template-columns: repeat(4, 1fr);
    gap: 40px;
  }

  /* ── SNAP — pinned-scroll choreography (R7) ───────────────────────
     The section pins: .snap-stage is sticky (100vh) inside a tall
     .snap-track whose height JS sets to 100vh + the pinned scroll budget.
     While pinned, JS (initSnapPinned) drives the per-block motion:
       • copy (left column, with its checks nested inside it) rises to the
         rest line, HOLDs there (the "5-clicks" pause), then exits the top;
       • only after the outgoing copy has fully left does the next block's
         copy enter from the bottom edge;
       • the right-column phone stays put and its image SNAPS per block
         (display swap — no fade) when the incoming copy reaches the
         phone's bottom.
     Entry (first block + phone rising together) and exit (last block +
     phone leaving together, then the next section scrolls up normally)
     fall out naturally from the sticky stage. */
  .snap {
    padding: 0;
    /* R8: the visible dark panel now lives on the pinned .snap-stage (so the
       "section" the user sees is the stationary window with real top/bottom
       edges). The tall .snap track itself is transparent on desktop. */
    background: none;
    background-image: none;
  }

  /* The decorative glow moves onto the stage (below); hide the section one. */
  .snap::before {
    display: none;
  }

  .snap-track {
    display: block;
    position: relative;
  }

  .snap-stage {
    display: block;
    position: sticky;
    /* Stationary "section" window: JS (measure) sets the exact height + top in
       px so the phone is viewport-centred and this frame's TOP edge is 120px
       above the phone top. overflow:hidden clips copy at the frame edges. */
    top: calc((100vh - 78vh) / 2);
    height: 78vh;
    overflow: hidden;
    /* White panel (moved off .snap) — identical fill to the mobile section. */
    background: #ffffff;
    /* Geometry tokens for the side columns. Frame aligned to the site's
       1280px grid (half = 640px; was a wider 1440px frame) so the copy's
       left edge sits on the same vertical line as every other section's
       headings. */
    --snap-phone-w: 320px;
    --snap-col-gap: 48px;
    --snap-gutter: max(var(--pad-x), calc(50vw - 640px + var(--pad-x)));
  }

  /* Decorative glow, now scoped to the stage (clipped by its overflow). */
  .snap-stage::before {
    content: "";
    position: absolute;
    right: -10%;
    top: -20%;
    width: 70%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.08), transparent 60%);
    pointer-events: none;
    z-index: 0;
  }

  /* Each block fills the pinned stage; JS reveals the active one(s). */
  .snap-inner {
    position: absolute;
    inset: 0;
    display: block;
    grid-template-columns: none;
    gap: 0;
    max-width: none;
    margin: 0;
    padding: 0;
    min-height: 0;
    align-items: stretch;
    pointer-events: none;
  }

  /* Left text column — copy with its checks nested inside, so the whole
     column animates as ONE unit. Anchored at top:0; JS sets translateY and
     matches the column's height to the phone img so the eyebrow top-aligns
     with the img top and the checks bottom-align with the img bottom. */
  .snap-copy {
    position: absolute;
    top: 0;
    margin: 0;
    will-change: transform;
    backface-visibility: hidden;
    order: 0;
    left: var(--snap-gutter);
    /* 56/44 split (was 50/50): the copy keeps reading width while the
       340px phone's column shrinks — its side voids drop from ~138px to
       ~60px, tightening the text↔phone pairing. */
    right: calc(44% + var(--snap-col-gap) / 2);
    text-align: left;
    display: flex;
    flex-direction: column;
  }

  /* Checks ride inside .snap-copy. Collapse pattern (Jul 2026): the
     "Know more" toggle now carries the column's bottom-pinning (see the
     toggle's ≥1024 margin-top:auto rule near the collapse styles); the
     list itself needs no margins/padding of its own — the global
     collapsed/open rules drive them. */
  .snap-checks {
    position: static;
  }

  /* The sub rides directly under the h2 as its subtext (base 12px gap);
     the column's slack pools in the single sub→checks gap, with the
     checks still pinned to the phone-img bottom via their margin-top:auto.
     Desktop sizing: 18/500 (base) → 16/400. */
  .snap-sub {
    font-size: 16px;
    font-weight: 400;
  }

  /* Right-column phone — JS sets `top` and toggles `.is-active` so exactly
     one phone shows at a time → instant snap between images. */
  .snap-visual {
    order: 0;
    position: absolute;
    left: calc(56% + var(--snap-col-gap) / 2);
    right: var(--snap-gutter);
    min-height: 0;
    display: none;
  }

  .snap-visual.is-active {
    /* flex (not block) re-centres the phone inside the right column. */
    display: flex;
    justify-content: center;
  }

  .snap-phone {
    position: static;
    width: var(--snap-phone-w);
    opacity: 1;
    transition: none;
    pointer-events: none;
    z-index: 5;
    /* Same subtle neutral-grey shadow as the base rule — the earlier
       navy-tinted version could pick up a green cast against the warm
       white stage. */
    box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.18);
  }
}

@media (min-width: 1280px) {
  .snap-stage {
    --snap-phone-w: 340px;
  }
}

/* Reduced-motion: skip the pinned choreography entirely and lay the snap
   blocks out as plain, readable stacked sections on desktop (JS also
   bails out, leaving these static styles in charge). */
@media (prefers-reduced-motion: reduce) and (min-width: 1024px) {

  /* The stage becomes display:contents below (no box → no background), and the
     desktop rule made .snap transparent. Restore the dark fill on .snap so the
     white snap copy stays readable in the static stacked fallback. */
  .snap {
    background: #ffffff;
    padding: 80px 0;
  }

  .snap-track,
  .snap-stage {
    display: contents !important;
  }

  .snap-inner {
    position: static;
    display: block;
    max-width: var(--max);
    margin: 0 auto;
    padding: 56px var(--pad-x);
    min-height: 0;
  }

  .snap-copy,
  .snap-checks,
  .snap-visual {
    position: static;
    transform: none;
    inset: auto;
    left: auto;
    right: auto;
    top: auto;
    width: auto;
    display: block;
    text-align: left;
  }

  .snap-visual {
    margin: 24px 0 0;
  }

  .snap-checks {
    margin-top: 24px;
    padding-top: 0;
  }
}

/* Apart carousel + pillars — desktop sizing. These rules used to sit at
   top level and leaked into tablet/mobile (the 4-up pillar row squeezed
   into the 640–1023px range); now correctly scoped to ≥1024px. Desktop
   output is unchanged. */
@media (min-width: 1024px) {

  /* Apart carousel: roomier card frame at desktop */
  .apart-stage {
    max-width: 980px;
  }

  /* Pillars: 4-up sticky-notes */
  .pillar-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
  }

  .pillar {
    padding: 32px 28px 36px;
  }

  .pillar h3 {
    font-size: 24px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   PILLARS — desktop redesign (≥1024 px)
   Fixed 320 × 360 cards laid out in a flex row that lets adjacent
   cards overlap at the corners. Cards are slightly tilted (≤ 3°) in
   alternating directions. Icons are absolutely positioned so a small
   portion (≈ 12% of their width) tucks behind the card's right edge.
   ═══════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  .pillar-grid {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: flex-start;
    gap: 0;
    grid-template-columns: none;
  }

  .pillar-grid .pillar {
    width: 320px;
    height: 360px;
    flex: 0 0 320px;
    box-sizing: border-box;
    /* Reserve the upper area for the absolute-positioned icon. */
    padding: 200px 28px 28px;
    /* Clip the portion of the icon that pokes past the right edge so
       only ~85% of the icon is visible. */
    overflow: hidden;
  }

  /* Every card except the first nudges left, creating a corner-overlap
     with the previous card. */
  .pillar-grid .pillar+.pillar {
    margin-left: -40px;
  }

  /* Stagger z-index so cards layer left-to-right: each later card sits
     visually on top of its neighbour to the left. */
  .pillar-grid .pillar:nth-child(1) {
    z-index: 1;
  }

  .pillar-grid .pillar:nth-child(2) {
    z-index: 2;
  }

  .pillar-grid .pillar:nth-child(3) {
    z-index: 3;
  }

  .pillar-grid .pillar:nth-child(4) {
    z-index: 4;
  }

  /* Card 3's existing -3° rotation is at the boundary; nudge it to
     -2.5° so every tilt is strictly under 3°. */
  .pillar-grid .pillar:nth-child(3) {
    transform: rotate(-2.5deg);
  }

  /* Vary the vertical position of alternate cards by ±12 px (24 px total
     spread) so the row isn't perfectly horizontal — gives the cluster a
     hand-pinned scrapbook feel. */
  .pillar-grid .pillar:nth-child(odd) {
    margin-top: -12px;
  }

  .pillar-grid .pillar:nth-child(even) {
    margin-top: 12px;
  }

  /* Icon: positioned absolutely with right: -22px so ~22px (≈ 12% of
     its 180-px width) is clipped by the card's overflow: hidden. */
  .pillar-grid .pillar-ic {
    position: absolute;
    top: 28px;
    right: -22px;
    width: 180px;
    height: 180px;
    margin: 0;
  }
}

/* Testimonials / FAQ / CTA — desktop 2-column splits and Figma paddings.
   These rules also used to sit at top level, forcing cramped side-by-side
   columns onto 640–1023px tablets; now correctly scoped to ≥1024px so
   tablet falls back to the stacked base layout. Desktop is unchanged. */
@media (min-width: 1024px) {

  /* Testimonials: 1/3 copy + 2/3 cards */
  .testi-inner {
    grid-template-columns: 1fr 1.4fr;
    gap: 56px;
  }

  .testi-cols {
    grid-template-columns: 1fr 1fr;
  }

  /* FAQ: 2-column. faq-list column widened 10% (1.1fr → 1.21fr); the copy
     column absorbs the difference (0.9fr → 0.79fr) so the total stays 2 and
     the 80px gap is unchanged. */
  .faq-inner {
    grid-template-columns: 0.79fr 1.21fr;
    gap: 80px;
  }

  /* CTA: padding-top matches .cta-brand top:72px so .cta-h2 and the brand
     logo share the same horizontal top edge at desktop. Horizontal padding
     stays the symmetric --pad-x so the copy keeps the shared container
     alignment and the stores row stays truly centred. */
  .cta-copy {
    padding: 72px var(--pad-x) 0;
  }

  .cta-stores {
    padding: 64px var(--pad-x) 80px;
  }

  .cta-brand {
    top: 72px;
    right: 80px;
  }
}


@media (min-width: 1280px) {
  :root {
    --pad-x: 80px;
  }

  .hero-phone {
    max-width: 340px;
    flex-basis: 340px;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   WHY — sticky-pinned scroll-jack
   Ported from TWH-website-Koshmoney-design-R4 .usps-pinned mechanics.
   • .why-pinned spans 4 beats × 80vh of scroll height (≈ 320vh)
   • Right column is align-items: stretch so it fills the full grid row;
     .why-phone-frame inside it uses position: sticky; top: 14vh and
     therefore stays pinned through every beat
   • Each .why-beat-text is min-height: 80vh, opacity 0.22 by default;
     IntersectionObserver toggles .is-active → opacity 1
   • Phone screens stack absolutely inside .why-phone-screen; only the
     .is-active one is visible (opacity 1), others opacity 0
   ═════════════════════════════════════════════════════════════════════ */
.why-lead {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  text-align: left;
}

.why-lead .eyebrow {
  /* R6 X1 audit fix: this was overriding the base .eyebrow rule with the
     lower-contrast --purple token. Inherit the new --purple-deep instead. */
  color: var(--purple);
  margin-bottom: 14px;
}

.why-lead .why-h2 {
  max-width: 720px;
}

.why-lead .why-sub {
  max-width: 560px;
}

/* The pinned wrapper. NO overflow:hidden here — any non-visible overflow
   on an ancestor disables sticky in the child. */
.why-pinned {
  position: relative;
  margin-top: 80px;
}

.why-pinned-inner {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--pad-x);
}

.why-pinned-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  align-items: stretch;
}

.why-col {
  display: flex;
  flex-direction: column;
}

.why-col-phone {
  align-items: center;
  justify-content: flex-start;
}

/* The phone screenshot assets already include the device bezel — no frame,
   no border, no background here. .why-phone-frame is purely a positioning
   wrapper that becomes sticky on desktop. */
.why-phone-frame {
  position: static;
  width: 280px;
  /* aspect mirrors the source PNG (≈ 9:18.5 for the screenshots in /assets/img) */
  aspect-ratio: 9 / 18.5;
  height: auto;
  background: transparent;
  border: 0;
  padding: 0;
  box-shadow: none;
  border-radius: 0;
}

.why-phone-screen {
  position: relative;
  width: 100%;
  height: 100%;
  background: transparent;
  border-radius: 0;
}

.why-phone-screen img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* keep the full screenshot visible */
  object-position: top;
  opacity: 0;
  /* No CSS transition — JS drives opacity smoothly via scroll progress.
     A tiny easing on opacity prevents subpixel flicker but keeps things tied
     to scroll. */
  transition: opacity 80ms linear;
  will-change: opacity;
}

/* Compatibility default — if JS doesn't run, show the first screen. */
.why-phone-screen img:first-child {
  opacity: 1;
}

.why-beat-text {
  /* Default (mobile / no-JS): rendered statically — every beat visible. */
  opacity: 1;
  padding: 24px 0;
}

/* Inner wrapper that holds the actual copy — mobile: in flow, desktop: sticky. */
.why-beat-text-inner {
  /* mobile default — no sticky, no opacity tween */
}

.why-num {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sans);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--purple-deep);
  /* AA: eyebrow on light bg */
  margin-bottom: 14px;
}

.why-num::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--purple);
  border-radius: 9999px;
}

.why-beat-text h3 {
  font-family: var(--sans);
  font-weight: 800;
  font-size: clamp(28px, 3.4vw, 48px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0 0 16px;
  text-wrap: balance;
}

.why-beat-text p {
  font-size: 16px;
  line-height: 1.55;
  color: var(--slate);
  font-weight: 500;
  max-width: 460px;
}

/* Desktop ≥ 1024px — sticky scroll-jack with smooth scroll-progress cross-fade.
   • Each .why-beat-text is min-height: 80vh — the section is 4 × 80vh tall.
   • .why-phone-frame is sticky at top: 14vh (top of phone aligns with top of
     the first beat's sticky text).
   • Inside each beat, .why-beat-text-inner is ALSO sticky at top: 14vh, so the
     active copy sits right next to the top of the phone screen.
   • Opacity is NOT toggled via .is-active. JS sets `style.opacity` per beat
     based on a continuous scroll-progress value, so transitions are smooth
     and tied to scroll position. */
@media (min-width: 1024px) {
  .why {
    padding: 80px 0 100px;
  }

  .why-lead {
    padding-bottom: 8vh;
  }

  .why-pinned {
    margin-top: 0;
  }

  .why-pinned-grid {
    grid-template-columns: 1fr minmax(300px, 380px);
    column-gap: 80px;
    align-items: start;
  }

  /* Phone column — stretches the full grid row so the sticky element can
     pin for the entire scroll length of the section. */
  .why-col-phone {
    align-self: stretch;
  }

  .why-phone-frame {
    position: sticky;
    top: 14vh;
    width: 340px;
    margin: 0 auto;
  }

  /* Each beat is 80vh tall; the text inside is sticky-pinned to the top
     of the phone so the active copy and the phone header align. */
  .why-beat-text {
    min-height: 80vh;
    display: block;
    padding-right: 16px;
    position: relative;
  }

  .why-beat-text-inner {
    position: sticky;
    top: 14vh;
    padding-top: 8px;
    /* Default starting opacity for the slot — JS will set the exact value
       on every scroll frame; this avoids a flash before JS boots. */
    opacity: 0;
    transition: opacity 80ms linear;
    will-change: opacity;
  }

  /* First beat is visible on initial paint (before scroll JS attaches). */
  .why-beat-text:first-child .why-beat-text-inner {
    opacity: 1;
  }
}

@media (min-width: 1280px) {
  .why-phone-frame {
    width: 360px;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   PAGE LAYER — for content pages under /pages/* (privacy, terms,
   sitemap, about, faq, etc.). Long-form prose styled to match the TWH
   homepage tokens: Manrope sans body, italic Playfair em accents,
   #919AFE purple, soft lavender hero band, dark navy footer.
   ═════════════════════════════════════════════════════════════════════ */
.page-hero {
  background: linear-gradient(180deg, var(--lavender-bg) 0%, #EFEDFE 60%, #F4F2FE 100%);
  /* Pull the hero up behind the floating nav pill (same trick as homepage .hero)
     so the lavender band reaches the top edge — no white strip above the nav.
     Top padding compensates so visible content sits below the nav at ~80px. */
  margin-top: -88px;
  padding: 168px 0 64px;
  text-align: center;
}

.page-hero-inner {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 var(--pad-x);
}

.page-eyebrow {
  display: inline-block;
  font-size: 14px;
  /* X4 audit fix: 13 → 14 (mobile readability) */
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* R6 X1 audit fix: was var(--purple) #919AFE which measured ~2.5:1 on
     the lavender hero gradient — failed WCAG AA. --purple-deep #6B6FE6
     measures ≥ 5:1 on the same gradient. */
  color: var(--purple);
  margin-bottom: 18px;
}

.page-h1 {
  font-family: var(--sans);
  font-weight: 800;
  font-size: clamp(36px, 6vw, 64px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}

.page-h1 em {
  font-size: 1em;
}

.page-lead {
  margin-top: 18px;
  font-size: clamp(15px, 1.4vw, 17px);
  color: var(--slate);
  font-weight: 500;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.page-body {
  background: var(--white);
  padding: 56px 0 96px;
  color: var(--ink-2);
}

.page-body-inner {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 var(--pad-x);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink-2);
}

.page-body-inner h1,
.page-body-inner h2,
.page-body-inner h3,
.page-body-inner h4 {
  font-family: var(--sans);
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.02em;
}

.page-body-inner h1 {
  font-size: clamp(28px, 4vw, 40px);
  margin: 56px 0 18px;
  line-height: 1.1;
}

.page-body-inner h1.center {
  text-align: center;
}

.page-body-inner h2 {
  font-size: clamp(22px, 2.6vw, 28px);
  margin: 48px 0 14px;
  line-height: 1.2;
}

.page-body-inner h3 {
  font-size: clamp(18px, 2vw, 22px);
  margin: 36px 0 10px;
  line-height: 1.25;
}

.page-body-inner h4 {
  font-size: 16px;
  margin: 24px 0 8px;
}

.page-body-inner p {
  margin: 12px 0;
  color: var(--ink-2);
}

.page-body-inner a {
  color: var(--purple-deep);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.page-body-inner a:hover {
  color: var(--navy);
  /* AA: darken hover (base is --purple-deep) */
}

.page-body-inner ul,
.page-body-inner ol {
  padding-left: 28px;
  margin: 12px 0;
}

.page-body-inner ul ul,
.page-body-inner ul ol,
.page-body-inner ol ul,
.page-body-inner ol ol {
  margin: 6px 0;
}

.page-body-inner ul {
  list-style: disc outside;
}

.page-body-inner ol {
  list-style: decimal outside;
}

.page-body-inner ol ol {
  list-style: lower-alpha outside;
}

.page-body-inner ol ol ol {
  list-style: lower-roman outside;
}

.page-body-inner li {
  margin: 6px 0;
}

.page-body-inner li>ol,
.page-body-inner li>ul {
  margin-top: 6px;
}

.page-body-inner strong,
.page-body-inner b {
  font-weight: 700;
  color: var(--ink);
}

.page-body-inner em,
.page-body-inner i {
  /* Inside body copy, lean on plain italic — don't pull Playfair onto
     every italicised legal phrase, only on intentional accent spans. */
  font-family: inherit;
  font-style: italic;
  font-weight: inherit;
  color: inherit;
}

.page-body-inner .Hyperlink,
.page-body-inner span.Hyperlink {
  color: var(--purple-deep);
  text-decoration: underline;
}

.page-body-inner table {
  border-collapse: collapse;
  width: 100%;
  margin: 18px 0;
  font-size: 15px;
}

.page-body-inner th,
.page-body-inner td {
  border: 1px solid var(--line);
  padding: 10px 14px;
  text-align: left;
  vertical-align: top;
}

.page-body-inner th {
  background: var(--surface-lp, #F4F1FE);
  font-weight: 700;
}

.page-body-inner hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 36px 0;
}

/* Sitemap-specific list of links */
.page-sitemap-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
  margin-top: 32px;
}

@media (min-width: 768px) {
  .page-sitemap-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 40px;
  }
}

.page-sitemap-col h3 {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--purple-deep);
  /* AA: eyebrow-like heading on light bg */
  margin: 0 0 12px;
}

.page-sitemap-col ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.page-sitemap-col li {
  /* X3 audit fix: was margin: 8px 0. The link's own padding now carries the
     vertical rhythm; we keep a small li margin so adjacent rows stay distinct
     without doubling the visible gap. */
  margin: 0;
}

.page-sitemap-col a {
  /* X3 audit fix: was unpadded (~18 px tall). Adding 8 px vertical padding +
     display:block makes the entire row tappable at ~36 px. Sitemap was the
     worst page in the audit with 40 sub-32 px targets. */
  display: block;
  padding: 8px 0;
  font-size: 16px;
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.page-sitemap-col a:hover {
  color: var(--purple-deep);
  border-bottom-color: var(--purple-deep);
}

/* ═══════════════════════════════════════════════════════════════════
   MOBILE NAV — brand on the left, hamburger on the right.
   Scoped to viewports below the desktop breakpoint (≥1024px). Desktop
   already sets .nav-menu { display: none } via its own media query.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  .nav-menu {
    /* default DOM order, pushed right by the existing margin-left:auto
       on .nav-menu in the base rule. Brand sits at the left of the pill. */
    order: 0;
    margin-right: 0;
  }

  .nav-sep {
    display: none;
    /* separator would dangle awkwardly between brand and the empty space
       to its right since nav-links are hidden at mobile. */
  }
}

/* ───────────────────────────────────────────────────────────────────
   Fix: .nav-mobile { display: flex } above was overriding the native
   browser rule [hidden] { display: none }. With this selector, the
   drawer truly hides when initMobileNav() sets menu.hidden = true.
   ─────────────────────────────────────────────────────────────────── */
.nav-mobile[hidden] {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════════════
   FAQ — filter pills + accordion (TWH brand colors, legacy structure)
   Used on pages/faq.html. .trigger li → pill filter, .faq-item.act → visible.
   Accordion: .faq-item.active → answer expanded.
   ═══════════════════════════════════════════════════════════════════ */
.faq-container {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 16px;
}

/* ── Filter pills row ──────────────────────────────────────────────── */
.faq-container .trigger {
  list-style: none;
  text-align: center;
  margin: 0 0 36px;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

.faq-container .trigger li {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  padding: 10px 22px;
  border: 1px solid rgba(145, 154, 254, 0.35);
  border-radius: 9999px;
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink, #1F2940);
  background: #fff;
  transition: background 200ms ease, color 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
  user-select: none;
}

.faq-container .trigger li:hover {
  background: rgba(145, 154, 254, 0.10);
  border-color: var(--purple-soft, #919AFE);
}

.faq-container .trigger li.act {
  background: var(--purple-soft, #919AFE);
  color: #fff;
  border-color: var(--purple-soft, #919AFE);
  font-weight: 700;
  box-shadow: 0 6px 18px -6px rgba(145, 154, 254, 0.6);
}

/* ── FAQ item card + accordion ─────────────────────────────────────── */
.faq-container .faq-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.faq-container .faq-item {
  background: #fff;
  border: 1px solid var(--line, rgba(20, 30, 70, 0.08));
  border-radius: 20px;
  padding: 22px 28px;
  display: none;
  transition: box-shadow 200ms ease, border-color 200ms ease;
}

.faq-container .faq-item.act {
  display: block;
}

.faq-container .faq-item:hover {
  border-color: rgba(145, 154, 254, 0.45);
  box-shadow: 0 8px 24px -10px rgba(20, 30, 70, 0.10);
}

/* Question row — clickable, with +/× indicator on the right */
.faq-container .faq-question {
  position: relative;
  cursor: pointer;
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.4;
  font-weight: 600;
  color: var(--ink, #1F2940);
  padding-right: 40px;
}

.faq-container .faq-question::after {
  content: '+';
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  border-radius: 9999px;
  background: rgba(145, 154, 254, 0.12);
  color: var(--purple-soft, #919AFE);
  font-size: 22px;
  font-weight: 400;
  line-height: 28px;
  text-align: center;
  transition: transform 280ms cubic-bezier(0.22, 1.0, 0.36, 1.0), background 200ms ease;
}

.faq-container .faq-item.active .faq-question::after {
  content: '×';
  transform: translateY(-50%) rotate(180deg);
  background: var(--purple-soft, #919AFE);
  color: #fff;
}

/* Answer — collapsed by default, opens via max-height transition */
.faq-container .faq-answer {
  max-height: 0;
  overflow: hidden;
  transition: max-height 360ms cubic-bezier(0.22, 1.0, 0.36, 1.0);
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-2, #3D4666);
}

.faq-container .faq-item.active .faq-answer {
  max-height: 1200px;
  /* large enough for any answer */
}

.faq-container .faq-answer p {
  margin: 14px 0 0;
}

.faq-container .faq-answer ul,
.faq-container .faq-answer ol {
  margin: 10px 0 0 18px;
  padding-left: 4px;
}

.faq-container .faq-answer li {
  margin: 4px 0;
}

.faq-container .faq-answer a {
  color: var(--purple-soft, #919AFE);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.faq-container .faq-answer a:hover {
  color: var(--purple-deep, #5b65d1);
}

/* The "Download here!" app-store link in the launch answer. */
.faq-container .faq-answer a.faq-download-link {
  color: #919AFE;
}

.faq-container .faq-answer a.faq-download-link:hover {
  color: #032356;
}

/* Mobile: tighter padding + smaller question text */
@media (max-width: 768px) {
  .faq-container {
    padding: 0 8px;
  }

  .faq-container .trigger {
    gap: 8px;
    margin-bottom: 24px;
  }

  .faq-container .trigger li {
    padding: 8px 14px;
    font-size: 13px;
  }

  .faq-container .faq-item {
    padding: 16px 18px;
    border-radius: 16px;
  }

  .faq-container .faq-question {
    font-size: 15px;
    padding-right: 32px;
  }

  .faq-container .faq-question::after {
    width: 24px;
    height: 24px;
    font-size: 19px;
    line-height: 24px;
  }

  .faq-container .faq-answer {
    font-size: 16px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   R5 — Homepage MOBILE overrides (<640 px)
   Scoped strictly to (max-width: 639px) so desktop and tablet are
   completely unaffected. Targets index.html only via the existing
   section classes.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 639px) {

  /* 2. PILLARS — one card per row on phones; each card 80% of screen width,
     alternately pinned to the left and right edge. Icons shrunk 60% (180->72). */
  .pillar-grid {
    grid-template-columns: 1fr;
    gap: 20px;
  }

  .pillar-grid .pillar {
    width: 80%;
    display: flex;
    flex-direction: column;
    word-break: break-word;
    overflow-wrap: anywhere;
    padding: 20px 16px 22px;
  }

  /* alternate edges: 1st & 3rd left, 2nd & 4th right */
  .pillar-grid .pillar:nth-child(odd) {
    justify-self: start;
  }

  .pillar-grid .pillar:nth-child(even) {
    justify-self: end;
  }

  /* 1. FEATURES — no backdrop image on phones (cleaner, lighter). */
  .features {
    background-image: none;
  }

  .pillar-grid .pillar-ic {
    width: 72px;
    height: 72px;
    margin-bottom: 12px;
  }

  /* 3. TESTIMONIALS — testi-copy on top, testi-cols beneath, both full width.
     Each card also full screen width. */
  .testi-inner {
    grid-template-columns: 1fr;
  }

  .testi-copy {
    max-width: none;
    width: 100%;
  }

  .testi-cols {
    grid-template-columns: 1fr;
    width: 100%;
  }

  .testi-col {
    flex-direction: column;
    width: 100%;
  }

  .testi-card {
    width: 100%;
    box-sizing: border-box;
  }

  /* 4. FAQ — copy block + question list stack vertically at full width,
     instead of the desktop 2-column grid. */
  .faq-inner {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  .faq-copy {
    max-width: none;
    width: 100%;
  }

  .faq-list {
    width: 100%;
  }

  /* Mobile: 4px smaller than the original sizes (summary 20→16, answer 16→12) */
  .faq-list summary {
    font-size: 16px;
  }

  .faq-list details p {
    font-size: 14px;
  }

  /* 5. CTA DOWNLOAD — re-order so copy is first (with breathing room),
     brand below it, and store badges side-by-side under that.
     .cta-photo is position:absolute (full-bleed bg) — keep as-is. */
  .cta {
    display: flex;
    flex-direction: column;
    min-height: auto;
  }

  .cta-photo {
    order: 0;
  }

  .cta-copy {
    /* R5: order:2 places .cta-copy BELOW .cta-brand on mobile while
       keeping the existing padding/gaps untouched. */
    order: 2;
    /* Generous vertical padding so the headline + sub stand clearly apart */
    padding: 64px var(--pad-x) 56px;
    max-width: none;
    /* Centre the headline + sub-text horizontally across the mobile screen. */
    text-align: center;
  }

  .cta-brand {
    /* R5: order:1 places .cta-brand ABOVE .cta-copy on mobile. */
    order: 1;
    position: static;
    display: flex;
    /* Centre the brand logo horizontally across the mobile screen. */
    justify-content: center;
    /* Larger bottom padding so there's a clear gap before the store badges. */
    padding: 24px var(--pad-x) 56px;
    top: auto;
    right: auto;
  }

  .cta-stores {
    order: 3;
    position: static;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: center;
    padding: 16px var(--pad-x) 56px;
    /* Wider gap between badges (20 → 30, +50%) for clearer tap separation. */
    gap: 30px;
    left: auto;
    bottom: auto;
  }

  .cta-store {
    width: auto;
    /* Badges reduced by ~15% (48% -> ~41%) to give the gap more room. */
    max-width: 41%;
    flex: 0 1 41%;
    min-width: 0;
  }

  .cta-store img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 12px;
  }

  /* 6. WHY — phone column first, text column second on mobile.
     The shared parent .why-pinned-grid uses flex so `order` controls
     visual sequence without touching the HTML. */
  .why-pinned-grid {
    display: flex;
    flex-direction: column;
  }

  .why-col-phone {
    order: 1;
  }

  .why-col-text {
    order: 2;
  }

  /* Soften the second-phone figure's bottom corners on mobile (88 → 48px). */
  .why-second-phone figure {
    border-bottom-right-radius: 48px;
    border-bottom-left-radius: 48px;
  }

  /* 7. PILLAR h3 — shrink heading by 4px (24 → 20). Card heights stay
     equal via the earlier grid-auto-rows: 1fr + height:100% rule. */
  .pillar-grid .pillar h3 {
    font-size: 20px;
    line-height: 1.2;
  }

  /* 8. HERO — move copy up + send the app badges below the phones.
     We "flatten" .hero-copy with display:contents so its children
     (h1, sub, badges) become direct flex items of .hero-inner alongside
     .hero-phones, and use order to put badges last. */
  /* Halve the navbar→headline gap: trim the section's top padding and the
     inner's top padding so the h1 + paragraph move up. min-height lets the
     badges sit near the bottom edge via margin-top:auto. */
  .hero {
    padding-top: 142px;
    /* doubled (was 18px) → with the inner's 20px, badges sit ~56px above the
       hero section's bottom edge (was ~28px). */
    padding-bottom: 36px;
  }

  .hero-inner {
    display: flex;
    flex-direction: column;
    padding-top: 16px;
    padding-bottom: 20px;
    min-height: calc(100svh - 170px);
  }

  .hero-copy {
    display: contents;
  }

  .hero-h1 {
    order: 1;
  }

  .hero-sub {
    order: 2;
    /* double the horizontal padding around the paragraph (inner already insets
       it by --pad-x; add another --pad-x left + right). */
    padding-left: var(--pad-x);
    padding-right: var(--pad-x);
  }

  .hero-phones {
    order: 3;
  }

  .hero-app-badges {
    order: 4;
    /* push the badges down to the bottom edge of the hero section */
    margin-top: auto;
    justify-content: center;
    gap: 24px;
  }

  /* SNAP — tighten the within-block stack. The base grid gap is 48px, which
     leaves big gaps copy→know-more and know-more→phone; shrink it on phones. */
  .snap-inner {
    gap: 14px;
  }

  /* Clearly separate consecutive blocks: a generous gap between one block's
     phone and the next block's heading (was 72px, +50%). */
  .snap-inner+.snap-inner {
    margin-top: 108px;
  }

}

/* ═══════════════════════════════════════════════════════════════════
   SNAP-CHECKS — collapse each list into a "Know more" pill on ALL
   breakpoints (was mobile-only; extended to tablet + desktop Jul 2026).
   The pill button is inserted by initSnapChecksToggle() in script.js.
   Tap the pill → list folds out. Scroll the page → list folds back in.
   ═══════════════════════════════════════════════════════════════════ */
.snap-checks {
  max-height: 0;
  overflow: hidden;
  margin-top: 0;
  opacity: 0;
  /* M3 audit fix: was max-height 600px which silently clipped any
     checklist content over 600 px. Bumped open state to 1500px
     (well above any realistic checklist — currently the longest is
     ~ 240 px). */
  transition:
    max-height 360ms cubic-bezier(0.22, 1, 0.36, 1),
    margin-top 280ms ease,
    opacity 240ms ease;
}

.snap-checks.is-open {
  max-height: 1500px;
  margin-top: 16px;
  opacity: 1;
}

.snap-checks-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  /* Shrink to its text + padding (not full width); on mobile/tablet the
     pill pins to the right edge of the copy block via margin-left:auto
     (desktop overrides to left-aligned in the pinned column). */
  margin-left: auto;
  width: fit-content;
  margin-top: 18px;
  margin-bottom: 0;
  min-height: 44px;
  padding: 10px 18px;
  /* Quiet lavender fill + purple-deep text — matches the site's accent
     scheme and clears WCAG AA on light backgrounds. */
  border: 1px solid rgba(145, 154, 254, 0.45);
  border-radius: 9999px;
  background: rgba(145, 154, 254, 0.10);
  color: var(--purple-deep);
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  appearance: none;
  transition: background 200ms ease, transform 200ms ease;
}

.snap-checks-toggle:hover,
.snap-checks-toggle:focus-visible {
  background: rgba(145, 154, 254, 0.20);
  outline: none;
}

.snap-checks-toggle .snap-checks-chevron {
  display: inline-flex;
  width: 12px;
  height: 12px;
  line-height: 1;
  transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

.snap-checks-toggle[aria-expanded="true"] .snap-checks-chevron {
  transform: rotate(180deg);
}

/* Desktop pinned columns: the TOGGLE carries the bottom-pinning
   (margin-top:auto) inside the fixed-height flex column. When the list
   expands, the column's flexible slack absorbs it — the toggle rises
   and the list fills the bottom band, its bottom edge staying on the
   phone-img bottom. Left-aligned with the copy on desktop. */
@media (min-width: 1024px) {
  .snap-checks-toggle {
    margin-left: 0;
    margin-top: auto;
    /* The pinned .snap-inner layers are pointer-events:none (six blocks
       stack absolutely over each other); that inherits onto the toggle,
       making it unclickable. Re-enable here — the inactive blocks stay
       click-transparent because visibility:hidden already removes them
       from hit-testing. */
    pointer-events: auto;
  }

  /* Collapsed rest position: the pill floats ⅓ of the phone's height
     above the phone's bottom edge. The collapsed (invisible: opacity 0,
     overflow hidden) list acts as the spacer — min-height beats the
     collapse's max-height:0 and resolves against the JS-set column
     height, which equals the phone-img height. On expand the list grows
     to max(content, ⅓): lists taller than the reserved third push the
     pill up; shorter lists leave it stationary. justify-content:
     flex-end stacks the items to the box's bottom, so the checklist's
     last row ALWAYS sits on the phone-img bottom edge — any spare space
     appears between the pill and the first item instead. */
  .snap-checks {
    min-height: 33.333%;
    justify-content: flex-end;
    /* Guaranteed ≥16px pill→checklist gap, factored into the rise: the
       padding sits at the top of the bottom-stacked box, so the box's
       natural height is content+16. Fits inside the reserved third →
       pill stays put (internal slack ≥ 16); taller → the box grows to
       content+16 and the pill rises exactly that much. */
    padding-top: 16px;
  }

  /* No extra open-state margin on desktop (the base rule adds 16px):
     with bottom-stacked items the pill→items spacing already lives
     inside the box, and zeroing it keeps the pill perfectly stationary
     when the list fits the reserved third. */
  .snap-checks.is-open {
    margin-top: 0;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   ABOUT PAGE — info-section blocks (mission / story / founders)
   Migrated layout from the R6 about.html design.
   ═══════════════════════════════════════════════════════════════════ */

/* V5 audit fix: about-page section token aliases now resolve to the
   GLOBAL TWH tokens defined in :root, instead of carrying their own
   hex values. Two new colors (--twh-surface-light-purple and
   --twh-fg-secondary) that don't yet exist in the system have been
   hoisted to :root (see top of this file). Net effect: the about-page
   stays visually identical, but any future global brand-color change
   propagates here automatically; --twh-deep-violet now points at
   --purple-deep so its links clear WCAG AA (was 4.08:1 at #5C6FFD,
   now 6.8:1 at #4F4FB0). */
.info-body {
  --twh-purple: var(--purple);
  --twh-deep-violet: var(--purple-deep);
  --twh-midnight: var(--navy);
  --twh-eerie-black: var(--ink);
  --twh-lime: var(--lime);
  --twh-white: var(--white);
  --twh-surface-light-purple: var(--surface-light-purple);
  --twh-fg-secondary: var(--fg-secondary);
  --twh-fw-medium: 500;
  --twh-fw-bold: 700;
  --twh-tracking-tight: -0.03em;
  --twh-r-lg: 24px;
  --twh-r-xl: 32px;
  --twh-r-pill: 9999px;
}

.info-body {
  max-width: 1080px;
  margin: 0 auto;
  padding: 72px 80px 96px;
}

.info-section {
  margin-bottom: 96px;
}

.info-section:last-child {
  margin-bottom: 0;
}

.info-section .info-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: 14px;
  /* X4 audit fix: 12 → 14 (mobile readability) */
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--purple);
  /* AA: was --twh-deep-violet (#5C6FFD ≈ 4.08:1) */
  margin-bottom: 18px;
}

.info-section .info-eyebrow::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--twh-lime);
  border-radius: var(--twh-r-pill);
  flex-shrink: 0;
}

.info-section h2 {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: clamp(30px, 4vw, 52px);
  line-height: 1.05;
  letter-spacing: var(--twh-tracking-tight);
  color: var(--twh-eerie-black);
  margin: 0 0 28px;
  text-wrap: balance;
}

.info-section h3 {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: 22px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--twh-eerie-black);
  margin: 28px 0 14px;
}

.info-section p {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-medium);
  font-size: 17px;
  line-height: 1.7;
  color: var(--twh-fg-secondary);
  margin: 0 0 14px;
  text-wrap: pretty;
  max-width: 65ch;
  /* X4: 840 → 65ch (~ 520 px at 16 px font; comfortable line) */
}

.info-section a {
  color: var(--twh-deep-violet);
  font-weight: var(--twh-fw-bold);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.info-section a:hover {
  color: var(--twh-purple);
}

/* MISSION GRID — 3-up icon cards in TWH tones */
.mission-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-top: 16px;
}

.mission-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--twh-r-xl);
  padding: 32px 28px;
  min-height: 220px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  color: #fff;
}

.mission-card.tone-purple {
  background: var(--twh-purple);
}

.mission-card.tone-violet {
  background: var(--twh-deep-violet);
}

.mission-card.tone-midnight {
  background: var(--twh-midnight);
}

.mission-card .ring-lg,
.mission-card .ring-sm {
  position: absolute;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.18);
  pointer-events: none;
}

.mission-card .ring-lg {
  width: 200px;
  height: 200px;
  right: -60px;
  bottom: -60px;
}

.mission-card .ring-sm {
  width: 130px;
  height: 130px;
  right: 30px;
  bottom: 30px;
}

.mission-card .mission-icon {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  display: grid;
  place-items: center;
  position: relative;
  z-index: 1;
  margin-bottom: 18px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
}

.mission-card .mission-icon::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--twh-lime);
}

.mission-card .mission-icon svg {
  width: 28px;
  height: 28px;
  stroke: #fff;
  fill: none;
}

.mission-card h3 {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: 22px;
  line-height: 1.25;
  letter-spacing: var(--twh-tracking-tight);
  color: #fff;
  margin: 0;
  position: relative;
  z-index: 1;
}

/* STORY — long-form prose */
.story-prose {
  max-width: 760px;
}

.story-prose p {
  margin-bottom: 16px;
}

.story-prose p .emphasis {
  font-weight: var(--twh-fw-bold);
  color: var(--twh-eerie-black);
}

.story-byline {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-medium);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--twh-deep-violet);
  margin: 0 0 24px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.story-byline::before {
  content: "";
  width: 22px;
  height: 2px;
  background: var(--twh-lime);
  border-radius: var(--twh-r-pill);
}

.story-signoff {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: 17px;
  color: var(--twh-eerie-black);
  margin-top: 24px;
}

/* FOUNDERS GRID — 2-up portrait cards */
.founders-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px;
  margin-top: 24px;
}

.founder-card {
  background: var(--twh-surface-light-purple);
  border-radius: var(--twh-r-xl);
  padding: 32px;
  display: flex;
  align-items: center;
  gap: 28px;
}

.founder-card img.founder-photo {
  width: 160px;
  height: 200px;
  border-radius: var(--twh-r-lg);
  object-fit: cover;
  flex-shrink: 0;
  background: var(--twh-white);
  display: block;
}

.founder-card .founder-meta h3 {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: 22px;
  letter-spacing: -0.01em;
  margin: 0 0 6px;
  color: var(--twh-eerie-black);
}

.founder-card .founder-meta p {
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-medium);
  font-size: 15px;
  color: var(--twh-fg-secondary);
  margin: 0 0 14px;
}

.founder-card .founder-linkedin {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Manrope', system-ui, -apple-system, sans-serif;
  font-weight: var(--twh-fw-bold);
  font-size: 14px;
  color: var(--twh-deep-violet);
  text-decoration: underline;
  text-underline-offset: 2px;
  padding: 6px 0;
}

.founder-card .founder-linkedin svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* Tablet adjustments */
@media (max-width: 1024px) {
  .info-body {
    padding: 56px 32px 80px;
  }

  .mission-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .founders-grid {
    grid-template-columns: 1fr;
  }

  .founder-card {
    padding: 24px;
  }
}

/* Mobile adjustments */
@media (max-width: 640px) {
  .info-body {
    padding: 36px 20px 48px;
  }

  .info-section {
    margin-bottom: 56px;
  }

  .info-section h2 {
    font-size: 26px;
  }

  .info-section p {
    font-size: 16px;
  }

  .mission-grid {
    grid-template-columns: 1fr;
  }

  .mission-card {
    min-height: 180px;
  }

  .founder-card {
    flex-direction: column;
    align-items: flex-start;
    padding: 22px;
  }

  .founder-card img.founder-photo {
    width: 100%;
    height: 240px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   X2 audit fix (Jun 2026): honour user's OS-level prefers-reduced-motion.

   - WCAG 2.3.3 (AAA) + best-practice accessibility for vestibular-sensitive
     users (parallax, scroll-jack, cross-fades can trigger nausea / vertigo).
   - JS scroll-jacks in script.js (initWhyPinned, initSnapFade) already check
     this media query and short-circuit, so the pinned phone sections stay
     static. This block sweeps every CSS-driven transition + global
     scroll-smooth that the JS doesn't cover.
   - Note: .pillar uses transform: rotate() as a static layout tilt, NOT
     as motion. We deliberately do NOT neutralise it — disabling pillar
     transforms would destroy the tilted-card design intent.
   ═══════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  html {
    scroll-behavior: auto !important;
  }

  /* Snap-checks mobile fold should appear instantly, not slide. */
  .snap-checks,
  .snap-checks.is-open {
    transition: none !important;
  }

  /* FAQ answer should appear / disappear instantly, not animate height. */
  .faq-container .faq-answer {
    transition: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   V3 audit fix: pricing.html h3 explicit TWH classes
   Both plan-price-h3 (₹0/month, etc.) and gift-plan-h3 (3 months, etc.)
   resolve to the same size at runtime today via the legacy stylesheet.
   These explicit rules make the type scale intentional and survive a
   future legacy CSS purge (X8).
   ═══════════════════════════════════════════════════════════════════ */
.plan-price-h3,
.gift-plan-h3 {
  font-family: var(--sans);
  font-size: var(--pricing-h3-size);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
}

@media (max-width: 768px) {

  .plan-price-h3,
  .gift-plan-h3 {
    font-size: var(--pricing-h3-size-mobile);
  }

  /* Apart carousel mobile: card frame fills the viewport width; one card
     stays in view at a time with snap scrolling. Softer corners + smaller
     glass arrows tuned for touch. */
  .apart-stage {
    max-width: 100%;
  }

  .apart-viewport {
    border-radius: 22px;
  }

  .apart-dots {
    margin-top: 0;
  }

  /* Mobile: halve the gap below the dots before the lgn section (100px → 50px).
     This is the section's bottom padding; top padding is unchanged. */
  .apart {
    padding-bottom: 50px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   FAMILY-BUDGET — User feedback + FAQ sections
   Migrated from legacy houzeguru-web/family-budget.html, restyled to
   the TWH index.html homepage design language: lavender band over
   white band, Manrope, brand purple + lime accents, pill radii.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Feedback band (lavender) ─────────────────────────────────────── */
.fb-feedback {
  background: var(--lavender-bg);
  padding: 96px 0 80px;
}

.fb-feedback-inner {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 var(--pad-x);
  text-align: center;
}

.fb-feedback-h2 {
  font-family: var(--sans);
  font-weight: 800;
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 14px 0 40px;
  text-wrap: balance;
}

.fb-feedback-h2 em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  color: var(--purple);
}

.fb-feedback-card {
  background: var(--white);
  border-radius: 24px;
  padding: 40px 32px;
  max-width: 600px;
  margin: 0 auto;
  box-shadow: 0 14px 40px -16px rgba(20, 30, 70, 0.10);
}

.fb-stars {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-bottom: 28px;
}

.fb-star {
  background: transparent;
  border: 0;
  padding: 4px;
  cursor: pointer;
  color: rgba(145, 154, 254, 0.32);
  transition: color 180ms ease, transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fb-star svg {
  width: 40px;
  height: 40px;
  display: block;
  fill: currentColor;
}

.fb-star:hover,
.fb-star:focus-visible,
.fb-star.is-active {
  color: var(--lime);
  outline: none;
  transform: translateY(-2px);
}

.fb-feedback-textarea {
  width: 100%;
  padding: 16px 18px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
  background: rgba(145, 154, 254, 0.05);
  border: 1px solid rgba(145, 154, 254, 0.30);
  border-radius: 16px;
  resize: vertical;
  margin-bottom: 20px;
  transition: border-color 180ms ease, background 180ms ease;
  box-sizing: border-box;
}

.fb-feedback-textarea::placeholder {
  color: var(--slate-2);
}

.fb-feedback-textarea:focus {
  outline: none;
  border-color: var(--purple-deep);
  background: var(--white);
}

.fb-feedback-submit {
  display: block;
  margin: 0 auto;
  padding: 14px 36px;
  background: var(--purple-deep);
  color: var(--white);
  border: 0;
  border-radius: 9999px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 180ms ease, transform 180ms ease;
}

.fb-feedback-submit:hover,
.fb-feedback-submit:focus-visible {
  background: var(--navy);
  outline: none;
  transform: translateY(-1px);
}

.fb-feedback-submit:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}

.fb-feedback-thanks {
  background: var(--white);
  border-radius: 24px;
  padding: 40px 32px;
  max-width: 600px;
  margin: 24px auto 0;
  text-align: center;
  box-shadow: 0 14px 40px -16px rgba(20, 30, 70, 0.10);
}

.fb-feedback-thanks h3 {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 28px;
  color: var(--purple-deep);
  margin: 0 0 12px;
}

.fb-feedback-thanks p {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  color: var(--slate);
  margin: 0;
}

/* ── FAQ band (white) ─────────────────────────────────────────────── */
.fb-faq {
  background: var(--white);
  padding: 96px 0 120px;
}

.fb-faq-inner {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 var(--pad-x);
  text-align: center;
}

.fb-faq-h2 {
  font-family: var(--sans);
  font-weight: 800;
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 14px 0 40px;
  text-wrap: balance;
}

.fb-faq-h2 em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  color: var(--purple);
}

.fb-faq-list {
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.fb-faq-list details {
  background: var(--lavender-bg);
  border: 1px solid rgba(145, 154, 254, 0.25);
  border-radius: 18px;
  overflow: hidden;
  transition: border-color 180ms ease, box-shadow 180ms ease;
}

.fb-faq-list details[open] {
  border-color: var(--purple);
  box-shadow: 0 10px 28px -16px rgba(145, 154, 254, 0.45);
}

.fb-faq-list summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 26px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 500;
  line-height: normal;
  color: #111827;
}

.fb-faq-list summary::-webkit-details-marker {
  display: none;
}

.fb-faq-list summary::after {
  content: '+';
  font-size: 26px;
  font-weight: 400;
  color: var(--purple-deep);
  flex-shrink: 0;
  line-height: 1;
  width: 24px;
  text-align: center;
  transition: transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fb-faq-list details[open] summary::after {
  content: '−';
}

.fb-faq-list details>div {
  padding: 0 26px 22px;
}

.fb-faq-list details p {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.6;
  color: #374151;
  margin: 0 0 12px;
}

.fb-faq-list details p:last-child {
  margin-bottom: 0;
}

.fb-faq-list details ol {
  /* Restore numbering — the global `ul, ol { list-style: none }` reset strips it.
     padding-left below gives the marker room to sit outside the text. */
  list-style: decimal outside;
  padding-left: 22px;
  margin: 8px 0 12px;
}

.fb-faq-list details ol li {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.6;
  color: #374151;
  margin-bottom: 8px;
}

.fb-faq-list details ol li:last-child {
  margin-bottom: 0;
}

.fb-faq-list details a {
  color: var(--purple-deep);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.fb-faq-list details a:hover {
  color: var(--navy);
}

/* Mobile tuning */
@media (max-width: 768px) {

  .fb-feedback,
  .fb-faq {
    padding: 64px 0;
  }

  .fb-feedback-h2,
  .fb-faq-h2 {
    font-size: clamp(28px, 7vw, 36px);
    margin: 12px 0 32px;
  }

  .fb-feedback-card,
  .fb-feedback-thanks {
    padding: 28px 20px;
  }

  .fb-star {
    padding: 2px;
  }

  .fb-star svg {
    width: 34px;
    height: 34px;
  }

  .fb-stars {
    gap: 6px;
  }

  .fb-faq-list summary {
    padding: 18px 20px;
    font-size: 16px;
  }

  .fb-faq-list summary::after {
    font-size: 22px;
  }

  .fb-faq-list details>div {
    padding: 0 20px 18px;
  }

  .fb-faq-list details p,
  .fb-faq-list details ol li {
    font-size: 12px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   BUILT FOR FAMILIES  (#built4families)
   Replicates Figma node 40017586:22870. Self-contained, .b4f-scoped —
   reuses existing :root tokens (--purple, --ink, --lime, --slate,
   --pale-lime, --sans, --serif, --max, --pad-x). Touches no other rules.
   ═══════════════════════════════════════════════════════════════════ */
.b4f {
  background: var(--white) url("assets/img/b4f-green-aura-bg.svg") center center / cover no-repeat;
  /* Rhythm pass (Jul 2026): top 80 → 48. With the hero's 80px bottom
     padding the white→white junction lands at ~128px (was 160). */
  padding: 48px 0 40px;
  overflow: hidden;
  /* clip the bleeding wordmark / orbit */
}

/* ── Centred lead ───────────────────────────────────────────────── */
.b4f-lead {
  max-width: 960px;
  margin: 0 auto;
  padding: 0 var(--pad-x);
  text-align: center;
}

.b4f-lead .eyebrow {
  color: var(--purple);
  margin-bottom: 18px;
}

.b4f-h2 {
  font-weight: 700;
  font-size: clamp(40px, 6vw, 56px);
  line-height: 1.15;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
}

.b4f-h2 em {
  font-size: 1em;
}

.b4f-sub {
  margin: 20px auto 0;
  max-width: 660px;
  font-size: 16px;
  font-weight: 500;
  color: var(--slate);
}

/* ── Visual stage ───────────────────────────────────────────────── */
.b4f-stage {
  position: relative;
  margin-top: 160px;
  display: flex;
  justify-content: center;
}

/* Giant faint wordmark behind everything (Figma "awise home", Eczar Bold) */
.b4f-watermark {
  position: absolute;
  top: 52%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: "Manrope", var(--serif);
  font-weight: 700;
  font-size: clamp(120px, 21vw, 296px);
  line-height: 0.84;
  letter-spacing: -0.04em;
  color: #F8F9F4;
  white-space: nowrap;
  pointer-events: none;
  z-index: 0;
}

/* Orbit wrapper — the Figma ellipse bounding box (588px). Avatars sit on
   its perimeter; the phone is centred within and overflows top/bottom. */
.b4f-orbit-wrap {
  position: relative;
  width: 520px;
  height: 520px;
  z-index: 1;
}

.b4f-orbit {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid #E7E9F6;
  background: radial-gradient(circle, rgba(145, 154, 254, 0.05) 0%, transparent 62%);
}

/* Avatar revolve layer — spins the whole 6-avatar formation around the orbit
   centre (its 520px box centre). Each avatar counter-rotates to stay upright.
   Pattern: ½ turn clockwise, then ⅓ turn anti-clockwise, repeated 6× per loop
   so it lands on a clean 360° (seamless, no jump). Medium speed. */
.b4f-avatar-orbit {
  position: absolute;
  inset: 0;
  z-index: 2;
  animation: b4f-orbit-revolve 66.67s linear infinite;
}

/* Family avatars. Positioned on the 520px orbit ring (see per-avatar angles). */
.b4f-avatar {
  position: absolute;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background-color: #EAECFF;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: 1px solid var(--white);
  box-shadow: 0 6px 18px rgba(14, 27, 77, 0.12);
  z-index: 2;
  /* counter-rotation (negative of the layer) keeps each photo upright */
  animation: b4f-orbit-upright 66.67s linear infinite;
}

@keyframes b4f-orbit-revolve {
  0% {
    transform: rotate(0deg);
  }

  10% {
    transform: rotate(180deg);
  }

  16.667% {
    transform: rotate(60deg);
  }

  26.667% {
    transform: rotate(240deg);
  }

  33.333% {
    transform: rotate(120deg);
  }

  43.333% {
    transform: rotate(300deg);
  }

  50% {
    transform: rotate(180deg);
  }

  60% {
    transform: rotate(360deg);
  }

  66.667% {
    transform: rotate(240deg);
  }

  76.667% {
    transform: rotate(420deg);
  }

  83.333% {
    transform: rotate(300deg);
  }

  93.333% {
    transform: rotate(480deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

@keyframes b4f-orbit-upright {
  0% {
    transform: rotate(0deg);
  }

  10% {
    transform: rotate(-180deg);
  }

  16.667% {
    transform: rotate(-60deg);
  }

  26.667% {
    transform: rotate(-240deg);
  }

  33.333% {
    transform: rotate(-120deg);
  }

  43.333% {
    transform: rotate(-300deg);
  }

  50% {
    transform: rotate(-180deg);
  }

  60% {
    transform: rotate(-360deg);
  }

  66.667% {
    transform: rotate(-240deg);
  }

  76.667% {
    transform: rotate(-420deg);
  }

  83.333% {
    transform: rotate(-300deg);
  }

  93.333% {
    transform: rotate(-480deg);
  }

  100% {
    transform: rotate(-360deg);
  }
}

@media (prefers-reduced-motion: reduce) {

  .b4f-avatar-orbit,
  .b4f-avatar {
    animation: none;
  }
}

/* Positions on the 520px orbit ring (centre 260,260; radius 260).
   Placed at irregular angles so the avatars read as random, not equispaced. */
.b4f-avatar--1 {
  /* 20° */
  left: 476px;
  top: 321px;
  background-image: url("assets/img/family-avatar-1.png");
  background-image: image-set(url("assets/img/family-avatar-1.webp") type("image/webp"), url("assets/img/family-avatar-1.png") type("image/png"));
}

.b4f-avatar--2 {
  /* 78° */
  left: 286px;
  top: 486px;
  background-image: url("assets/img/family-avatar-2.png");
  background-image: image-set(url("assets/img/family-avatar-2.webp") type("image/webp"), url("assets/img/family-avatar-2.png") type("image/png"));
}

.b4f-avatar--3 {
  /* 145° */
  left: 19px;
  top: 381px;
  background-image: url("assets/img/family-avatar-3.png");
  background-image: image-set(url("assets/img/family-avatar-3.webp") type("image/webp"), url("assets/img/family-avatar-3.png") type("image/png"));
}

.b4f-avatar--4 {
  /* 200° */
  left: -12px;
  top: 143px;
  background-image: url("assets/img/family-avatar-4.png");
  background-image: image-set(url("assets/img/family-avatar-4.webp") type("image/webp"), url("assets/img/family-avatar-4.png") type("image/png"));
}

.b4f-avatar--5 {
  /* 250° */
  left: 143px;
  top: -12px;
  background-image: url("assets/img/family-avatar-5.png");
  background-image: image-set(url("assets/img/family-avatar-5.webp") type("image/webp"), url("assets/img/family-avatar-5.png") type("image/png"));
}

.b4f-avatar--6 {
  /* 305° */
  left: 381px;
  top: 19px;
  background-image: url("assets/img/family-avatar-6.png");
  background-image: image-set(url("assets/img/family-avatar-6.webp") type("image/webp"), url("assets/img/family-avatar-6.png") type("image/png"));
}

/* Centred phone (Figma "Home" frame, 335×680) */
.b4f-phone {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 320px;
  /* Match the 4x screenshot aspect so the b4f phone shows the FULL screen — its
     bottom edge IS the image bottom, letting the hero phone continue it. */
  aspect-ratio: 1565 / 3320;
  z-index: 3;
}

/* ROUTE 1 — single hero phone (fixed; JS-driven width/height/top/left/img-crop).
   Unique class (.r10-hero) to avoid the existing .hero-phone in the top hero section. */
.r10-hero {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 5;
  opacity: 0;
  display: none;
  /* JS turns it on (desktop, no reduced-motion) */
  pointer-events: none;
  will-change: transform, width, height, top, left;
}

.r10-hero-frame {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 42px;
  /* JS interpolates toward the bottom-slice radius */
  background: var(--pale-lime);
  box-shadow: 0 30px 60px -20px rgba(20, 30, 70, 0.25);
}

.r10-hero-frame img {
  position: absolute;
  left: 0;
  top: 0;
  /* JS slides this to reveal the bottom as it pins */
  width: 100%;
  height: auto;
  display: block;
}

.b4f-phone-screen {
  position: relative;
  width: 110%;
  height: 110%;
  border-radius: 62px;
  overflow: hidden;
  /* background: var(--pale-lime); */
  transform: scale(1.0);
  /* border: 8px solid var(--Neutral-300, #D1D5DB); */
  /* background: url(<path-to-image>) lightgray 50% / cover no-repeat; */
  /* box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.08); */
}

.b4f-phone-screen img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}

.b4f-phone-island {
  display: none;
  position: absolute;
  top: 18px;
  left: 50%;
  transform: translateX(-50%);
  width: 86px;
  height: 25px;
  background: #000;
  border-radius: 99px;
  z-index: 4;
}

/* Desktop: the 1.1-scaled phone screen (~671px tall) overflows the orbit box
   and was being cut off at the bottom by the section's overflow clip. Give the
   stage enough height to hold the whole screen plus the section's bottom pad. */
@media (min-width: 961px) {
  .b4f-stage {
    min-height: 650px;
  }
}

/* Safety guard: the b4f→features zoom animation (initHeroPhone) runs only at
   ≥768px and drives the b4f phone's clip-path / opacity and the orbit's opacity
   via inline styles. Below 768px that animation never runs, so force these fully
   visible and unclipped — this overrides any stale inline styles left over from a
   desktop→mobile resize, guaranteeing the phone + orbit always show on phones. */
@media (max-width: 767px) {
  .b4f-phone {
    opacity: 1 !important;
    clip-path: none !important;
  }

  .b4f-orbit-wrap {
    opacity: 1 !important;
  }
}

/* ── Responsive: scale the fixed-geometry orbit down on smaller screens ── */
@media (max-width: 960px) {

  /* Larger gap below the lead: the scaled phone screen overhangs the stage top
     and was overlapping the lead text above it (applies to tablet and, by
     inheritance, mobile — the 600px block doesn't override margin-top). */
  .b4f-stage {
    margin-top: 72px;
  }

  .b4f-orbit-wrap {
    transform: scale(0.78);
  }

  .b4f-stage {
    height: 460px;
  }

  .b4f-orbit-wrap {
    position: relative;
    top: -65px;
  }
}

@media (max-width: 600px) {
  .b4f {
    padding: 64px 0 24px;
  }

  .b4f-sub {
    font-size: 16px;
  }

  .b4f-orbit-wrap {
    transform: scale(0.52);
  }

  .b4f-phone-screen {
    transform: scale(1.2);
  }

  /* Tall enough to hold the 1.2-scaled phone screen plus the section's
     bottom padding without the section's overflow clip cutting it. The extra
     margin-top pushes the whole stage down so the SCALED phone screen (which
     overhangs the .b4f-phone box upward) clears the lead paragraph. */
  .b4f-stage {
    height: 408px;
    margin-top: 108px;
  }

  /* Move the phone + orbit DOWN so the phone no longer overlaps the lead
     paragraph (was -140px, which pulled the phone up over the text). */
  .b4f-orbit-wrap {
    top: -100px;
  }

  .b4f-watermark {
    font-size: 24vw;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   R8 — FEATURES pinned-scroll choreography
   Phone (.why-second-phone) sticks at the top edge and enlarges; the four
   .feature cards reveal one by one; then the stage releases and SNAP scrolls
   up normally. Activated by JS (initFeaturesPinned) which adds .r8-active
   only on >=768px without prefers-reduced-motion. Without JS / on mobile the
   section falls back to a normal stacked block.
   ═════════════════════════════════════════════════════════════════ */
.features.r8-active {
  /* Sticky target: 120px below the navbar's bottom edge.
     Nav pill is top:12px and ~64px tall, so its bottom edge ≈ 76px. */
  --nav-bottom: 76px;
  --pin-top: calc(var(--nav-bottom) + 120px);
  /* = 196px */
  position: relative;
  height: 150vh;
  /* scroll budget that drives the choreography */
  background: var(--white);
  background-image: none;
  padding: 0;
}

.features.r8-active .features-pin {
  position: sticky;
  top: var(--pin-top);
  /* Fit the content (phone + 80px gaps + cards) so the stage's bottom edge IS the
     80px margin below the cards. The SNAP section, which follows in flow, then docks
     exactly at that edge and never rides up over the cards or their 80px margin. */
  height: auto;
  overflow: visible;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  /* The backdrop image lives on ::before so JS can fade JUST the image (not the
     phone/cards). It starts invisible (--bg-op:0) and JS ramps --bg-op in step
     with the why-second-phone fade, then holds it at 1 until the section exits. */
}

.features.r8-active .features-pin::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("assets/img/bg-why-home.png");
  background-image: image-set(url("assets/img/bg-why-home.webp") type("image/webp"), url("assets/img/bg-why-home.png") type("image/png"));
  background-size: 100% 100%;
  background-position: center bottom;
  background-repeat: no-repeat;
  opacity: var(--bg-op, 0);
}

.features.r8-active .why-second-phone {
  margin: 0;
  flex: 0 0 auto;
  opacity: 0;
  /* JS fades it in as the stage pins (handoff from the b4f phone) */
}

.features.r8-active .why-second-phone figure {
  transform-origin: top center;
  will-change: transform;
}

.features.r8-active .features-inner {
  flex: 0 0 auto;
  width: 100%;
  max-width: var(--max);
  /* Always 4 columns while pinned (the base 4-col rule only starts at 1024px,
     but the pin activates at 768px) so the 8 cards are a 4×2 grid — never a tall
     2×4 that would overflow the pinned viewport on 768–1023px. */
  grid-template-columns: repeat(4, 1fr);
  /* Two rows now live in the pinned stage, so margins + row-gap are tightened
     (was 80/120, gap 40) to keep the whole 4×2 grid inside the viewport while
     pinned. The snap-hold docks at the live stage bottom, so the smaller bottom
     gap just brings the snap panel a little closer under the cards. */
  margin: 40px auto 72px;
  gap: 28px;
  padding-top: 0;
}

.features.r8-active .feature {
  opacity: 0;
  transform: translateY(28px) scale(.98);
  transition: opacity .5s ease, transform .6s cubic-bezier(.2, .8, .2, 1);
}

.features.r8-active .feature.r8-in {
  opacity: 1;
  transform: none;
}

/* b4f phone is faded by JS during the scroll handoff */
.b4f-phone {
  will-change: opacity;
}

@media (prefers-reduced-motion: reduce) {
  .features.r8-active .feature {
    transition: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   LITTLE GAME NOTES  (#little-game)
   Imported from Claude Design ("Little Game Notes"). Self-contained,
   .lgn-scoped — a masonry wall of pastel sticky-notes with 3D push-pins.
   Per-card values (paper colour, ink, rotation, width, pin position) are
   applied inline by initLittleGame() in script.js using the original
   seeded layout. Touches no other rules.
   ═══════════════════════════════════════════════════════════════════ */
.lgn {
  /* background: var(--pale-lime); */
  background: var(--white);
  font-family: 'Manrope', -apple-system, sans-serif;
  color: #161616;
  /* Rhythm pass (Jul 2026): bottom 96 → 48. With .pillars' 80px top the
     white→white junction lands at ~128px (was 196 — the page's worst). */
  padding: 72px 36px 48px;
}

.lgn-head {
  max-width: var(--max);
  margin: 0 auto 52px;
  padding: 0 var(--pad-x);
  text-align: left;
}

.lgn-eyebrow {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--purple);
  margin-bottom: 18px;
}

.lgn-h2 {
  font-weight: 700;
  font-size: clamp(36px, 5.5vw, 60px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.lgn-h2 em {
  font-style: italic;
  color: #919AFE;
}

.lgn-sub {
  margin-top: 18px;
  max-width: 65ch;
  color: var(--slate);
  font-weight: 500;
  font-size: 16px;
}

/* Masonry wall — left edge aligned with .lgn-head via the shared --pad-x inset */
.lgn-wall {
  column-width: 212px;
  column-gap: 20px;
  max-width: var(--max);
  margin: 0 auto;
  padding: 12px var(--pad-x) 0;
}

.lgn-note {
  display: block;
  position: relative;
  margin: 0 0 16px;
  border-radius: 10px;
  padding: 38px 16px 17px;
  box-shadow: 0 11px 20px rgba(45, 30, 90, 0.13), 0 2px 5px rgba(45, 30, 90, 0.09);
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  /* --rot and --pin-x are set inline per note; the zoom on hover composes
     scale with the note's rotation and pivots on the pin head so the pin
     stays put while the card grows. */
  transform: rotate(var(--rot, 0deg));
  transform-origin: var(--pin-x, 50%) 16px;
  transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 280ms ease;
}

.lgn-cat {
  font-family: 'Kalam', cursive;
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.5;
  margin-bottom: 7px;
}

.lgn-text {
  font-family: 'Kalam', cursive;
  font-weight: 400;
  font-size: 16.5px;
  line-height: 1.3;
}

/* 3D push-pin */
.lgn-pin {
  position: absolute;
  top: 9px;
  margin-left: -9px;
  width: 34px;
  height: 34px;
}

.lgn-pin-shadow {
  position: absolute;
  top: 16px;
  left: 14px;
  width: 18px;
  height: 8px;
  border-radius: 50%;
  background: rgba(40, 28, 60, 0.30);
  filter: blur(3px);
}

.lgn-pin-stem {
  position: absolute;
  top: 9px;
  left: 8px;
  width: 3px;
  height: 17.5px;
  border-radius: 2px;
  background: linear-gradient(180deg, #eeeef2 0%, #b6b6be 38%, #74747e 100%);
  transform: rotate(40deg);
  transform-origin: top center;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.22);
}

.lgn-pin-head {
  position: absolute;
  top: 2.5px;
  left: 2.5px;
  width: 13.5px;
  height: 13.5px;
  border-radius: 50%;
  box-shadow:
    inset -2.4px -2.4px 4px rgba(0, 0, 0, 0.40),
    inset 1.6px 1.6px 2.4px rgba(255, 255, 255, 0.35),
    0 2px 3px rgba(0, 0, 0, 0.28);
}

.lgn-pin-hl1 {
  position: absolute;
  top: 2px;
  left: 2.4px;
  width: 4.8px;
  height: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  filter: blur(0.6px);
  transform: rotate(-22deg);
}

.lgn-pin-hl2 {
  position: absolute;
  bottom: 2.4px;
  right: 2.4px;
  width: 2.4px;
  height: 2.4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  filter: blur(0.5px);
}

/* ── Dislike control ─────────────────────────────────────────────── */
.lgn-dislike {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  padding: 0;
  display: grid;
  place-items: center;
  border: none;
  background: transparent;
  border-radius: 50%;
  color: #AEB1B6;
  cursor: pointer;
  z-index: 6;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 200ms ease, background-color 200ms ease, color 200ms ease, transform 150ms ease;
}

.lgn-dislike svg {
  width: 16px;
  height: 16px;
  display: block;
  pointer-events: none;
}

.lgn-tdown--solid {
  display: none;
}

.lgn-dislike:hover {
  transform: scale(1.08);
}

.lgn-dislike:focus-visible {
  outline: 2px solid #834DFB;
  outline-offset: 2px;
}

/* Marked state — filled red thumbs-down on a light-pink disc a few px
   larger than the glyph (24px disc around a 16px icon). */
.lgn-note.is-disliked .lgn-dislike {
  background: #FBD6DE;
  color: #E0335B;
}

.lgn-note.is-disliked .lgn-tdown--outline {
  display: none;
}

.lgn-note.is-disliked .lgn-tdown--solid {
  display: block;
}

/* Hover devices (desktop / tablet with a pointer): the card zooms 20%
   around its pin on hover and the icon fades in; once marked it un-zooms
   and the filled icon persists. */
@media (hover: hover) and (pointer: fine) {
  .lgn-dislike {
    opacity: 0;
  }

  .lgn-note:hover .lgn-dislike,
  .lgn-note.is-disliked .lgn-dislike {
    opacity: 1;
  }

  .lgn-note:not(.is-disliked):hover {
    transform: rotate(var(--rot, 0deg)) scale(1.2);
    z-index: 5;
    box-shadow: 0 22px 40px rgba(45, 30, 90, 0.22), 0 5px 12px rgba(45, 30, 90, 0.13);
  }
}

/* Touch devices (phones / touch tablets): icon always shown in light grey;
   a tap anywhere on the card toggles the marked state (handled in JS). */
@media (hover: none),
(pointer: coarse) {
  .lgn-dislike {
    opacity: 1;
  }

  .lgn-note {
    cursor: pointer;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lgn-note {
    transition: none;
  }
}

@media (max-width: 600px) {
  .lgn {
    padding: 56px 18px 64px;
  }

  /* Mobile: force a tidy 2-up grid instead of the masonry columns, and
     show only the first 12 notes (6 rows). The rest stay in the DOM but
     are removed from layout. Desktop is unaffected — this is scoped here. */
  .lgn-wall {
    column-count: 2;
    column-width: auto;
    column-gap: 14px;
  }

  .lgn-wall .lgn-note:nth-child(n+13) {
    display: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   TABLET + MOBILE polish (< 1024px only — desktop is untouched).
   Readability, touch-target and layout refinements for index.html.
   Kept at the end of the file so these later rules win the cascade
   against the base (mobile-first) declarations they refine.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {

  /* Anchor jumps (nav + footer links) land clear of the sticky floating
     nav pill instead of hiding the section heading underneath it. */
  #built4families,
  #features,
  #little-game,
  #privacy,
  #faq,
  #download {
    scroll-margin-top: 88px;
  }

  /* Hamburger: 40 → 44px square (WCAG 2.5.5 / platform touch-target floor).
     The button is transparent, so the pill's look doesn't change. */
  .nav-menu {
    width: 44px;
    height: 44px;
  }

  /* APART header: stack heading + sub left-aligned. The desktop two-ends
     row wraps here, leaving an 80px flex gap and a right-aligned paragraph
     floating oddly against the left-aligned heading. */
  .apart-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
  }

  .apart-sub {
    text-align: left;
  }

  /* Carousel controls: 44px arrows, and a ~24px tappable box around each
     8px pagination dot — the visual dot size is unchanged because the
     background clips to the content box; only the hit area grows. */
  .apart-arrow {
    width: 44px;
    height: 44px;
  }

  .apart-dot {
    box-sizing: content-box;
    padding: 8px;
    background-clip: content-box;
  }

  /* Testimonial cards: lift the smallest text to the handheld readability
     floor (body 13.5 → 15px, name 14 → 15px, city 12 → 13px). */
  .testi-card p {
    font-size: 15px;
  }

  .testi-card header strong {
    font-size: 15px;
  }

  .testi-card header span {
    font-size: 13px;
  }
}

/* Tablet only (640–1023px): with the desktop 24px pillar-h3 rule now
   correctly scoped, this range would fall back to the base 12px heading —
   smaller than the card body text. Restore a proper heading scale and a
   little more breathing room for the 2-up tablet pillar grid. (Mobile
   < 640px already has its own 20px h3 + tighter padding overrides.) */
@media (min-width: 640px) and (max-width: 1023px) {
  .pillar h3 {
    font-size: 22px;
  }

  .pillar {
    padding: 24px 24px 30px;
  }
}

/* (The former mobile-only 44px pill floor now lives in the base
   .snap-checks-toggle rule — the collapse pattern is all-breakpoint.) */

/* ═══════════════════════════════════════════════════════════════════
   MOBILE typography pass (< 640px only) — Jul 2026 review.
   Unifies the section-heading ramp under the 40px hero h1, quiets the
   uppercase eyebrows, and trims card/note text for proportion. Tablet
   and desktop sizes are unchanged.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 639px) {

  /* Section headings: 32px floor, 34px for the two statement sections —
     all clearly below the 40px hero h1 (the snap-h2 already sits at 32). */
  .b4f-h2,
  .testi-h2 {
    font-size: 34px;
  }

  .apart-h2,
  .lgn-h2,
  .pillars-h2,
  .faq-h2,
  .cta-h2 {
    font-size: 32px;
  }

  /* Eyebrows: 16px uppercase + tracking reads oversized on phones and
     competes with the sub-copy; 13px is the conventional lead-in size. */
  .eyebrow,
  .lgn-eyebrow {
    font-size: 13px;
  }

  /* Sticky-note wall: 16.5px Kalam wraps into tall ragged notes in the
     2-up mobile grid; 15px keeps the handwriting legible and tidier. */
  .lgn-text {
    font-size: 15px;
  }

  /* Pillar cards: widen the body→heading step (h3 is 20px on mobile). */
  .pillar p {
    font-size: 15px;
  }

  /* Testimonial cards: the name drops back to 14px so the 15px quote is
     the largest text in the card. */
  .testi-card header strong {
    font-size: 14px;
  }

  /* Footer group labels recede a step further beneath the 14px links. */
  .footer-col h4 {
    font-size: 12px;
  }

  /* Footer brand blurb: 14 → 12px. */
  .footer-brand p {
    font-size: 14px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   MOBILE icon & badge pass (< 640px only) — Jul 2026 review.
   Rebalances oversized marks and unifies the two store-badge rows.
   Tablet and desktop are unchanged.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 639px) {

  /* Footer socials: 72px dominated the footer next to the 28px logo and
     14px links; 48px keeps a ≥44px tap target and restores proportion. */
  .footer-socials a,
  .footer-socials img {
    width: 48px;
    height: 48px;
  }

  /* CTA store badges: match the hero badge row exactly (50px tall,
     natural width) instead of the width-drifting 41%-of-row sizing.
     flex-shrink stays on and object-fit:contain letterboxes the image,
     so ultra-narrow viewports (~320px) squeeze gracefully, never
     overflowing the nowrap row. */
  .cta-store {
    flex: 0 1 auto;
    max-width: none;
  }

  .cta-store img {
    width: auto;
    height: 50px;
    max-width: 100%;
    object-fit: contain;
  }

  /* CTA brand mark: 60px was desktop-corner sizing; centred above the
     copy it competed with the 32px section headline. */
  .cta-brand-mark img {
    height: 44px;
  }

  /* Feature icons: stronger row anchor in the single-column list. */
  .feature-ic {
    width: 36px;
    height: 36px;
  }

  /* Nav brand: keep the logo proportional inside the taller (~56px)
     mobile pill. */
  .nav-mark img {
    height: 48px;
  }

  /* Apart arrows: 20px chevron balances the 44px frosted disc. */
  .apart-arrow svg {
    width: 20px;
    height: 20px;
  }
}

/* b4f family avatars — scoped to the same < 600px range as the 0.52
   orbit scale: 56px CSS renders ≈ 29px effective (faces illegible).
   76px ≈ 40px effective; the negative margin re-centres each avatar on
   its original orbit spot (+20px growth → −10px top/left offset). */
@media (max-width: 600px) {
  .b4f-avatar {
    width: 76px;
    height: 76px;
    margin: -10px 0 0 -10px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   MOBILE vertical-rhythm pass (< 640px only) — Jul 2026 review.
   A) tighter FAQ cards  B) unified 64px section rhythm (and the
   features→snap ~180px dead gap)  C) heading-block internals matched
   to the new 13px eyebrows / 32px h2s  D) CTA stack  E) footer gaps.
   Tablet and desktop are unchanged.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 639px) {

  /* ── A. FAQ cards: ~62px closed rows → ~50px (still ≥44px tap). ── */
  .faq-list details {
    padding: 0 18px;
  }

  .faq-list summary {
    padding: 14px 0;
  }

  /* Answer: drop the 38px indent — full reading width on a phone. */
  .faq-list details>div {
    padding: 0 0 16px 0;
  }

  /* ── B. Section rhythm: one 64px beat (56px for the snap band). ── */
  .apart {
    padding-top: 64px;
  }

  .pillars {
    padding: 64px 0;
  }

  .testi {
    padding: 64px 0;
  }

  .faq {
    padding: 64px 0;
  }

  .snap {
    padding: 56px 0;
  }

  /* features→snap junction: was 80px inner margin + 100px section
     padding ≈ 180px of empty white (the bg image that justified it is
     removed on mobile). Now ≈ 88px total. */
  .features {
    padding-bottom: 40px;
  }

  .features-inner {
    margin: 48px auto;
  }

  /* ── C. Heading-block internals (proportion after the type pass). ── */
  .eyebrow,
  .lgn-eyebrow {
    margin-bottom: 12px;
  }

  .pillars-head {
    margin-bottom: 40px;
  }

  .lgn-head {
    margin-bottom: 40px;
  }

  .apart-carousel {
    margin-top: 48px;
  }

  .testi-sub,
  .snap-sub {
    margin-top: 18px;
  }

  .testi-inner {
    gap: 32px;
  }

  /* ── D. CTA stack: trim ~250px of pure padding to ~180px. ── */
  .cta-brand {
    padding: 24px var(--pad-x) 32px;
  }

  /* Copy→stores gap: doubled (56 → 112px), +20% (→ ≈134px), then a
     further +25% (96 → 120, 38.4 → 48; total 168px). The section grows
     with its content (min-height:auto on mobile) and the photo is
     background-size:cover, so it fills the taller band by cropping —
     never by stretching — keeping its aspect ratio intact. */
  .cta-copy {
    padding: 40px var(--pad-x) 120px;
  }

  .cta-stores {
    padding: 48px var(--pad-x) 48px;
  }

  /* ── E. Footer: tighter rows around the shrunk 48px socials. ── */
  .footer-inner {
    gap: 32px;
  }

  .footer-meta {
    margin-top: 32px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   MOBILE tweak pass (< 640px only) — Jul 2026.
   Store badges −10%, wider little-game notes, smaller snap sub-copy.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 639px) {

  /* 1. Store badges −10% (50 → 45px); hero row later reduced a further
     10% (45 → 40.5px). */
  .cta-store img {
    height: 45px;
  }

  .hero-app-badge img {
    height: 48px;
    border-radius: 12px;
  }

  /* 2. Little-game wall: minimal 4px side padding (was --pad-x = 24px)
     → each 2-up note gains ~20px of width. */
  .lgn-wall {
    padding-left: 4px;
    padding-right: 4px;
  }

  /* 3. Snap sub-copy: 16 → 14px. */
  .snap-sub {
    font-size: 14px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   DESKTOP polish pass (≥ 1024px only) — Jul 2026 review.
   1) Contrast fixes left over from the dark snap band  2) type-ramp
   consistency  3) icon/badge rebalance  4) FAQ + footer rhythm.
   Mobile and tablet are unchanged. Kept at the end of the file so
   these later rules win the cascade over earlier desktop blocks.
   ═══════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {

  /* ── 1. Contrast fixes ─────────────────────────────────────────── */

  /* Snap eyebrows: --purple #919AFE measured ~2.4:1 on the white snap
     stage (class dates from the dark-navy band). Scoped to .snap so the
     testimonials section keeps the lighter purple on its navy bg. */
  .snap .eyebrow--on-dark {
    color: var(--purple-deep);
  }

  /* Snap headline accents: lime #C7D983 on white was ~1.7:1 and the only
     non-purple headline accent on the page. Rejoin the default em purple. */
  .snap-h2 em {
    color: var(--purple);
  }

  /* Pillar body: --grey-text was ~3.4:1 on the pastel-lime cards;
     --slate clears AA (~6.8:1). */
  .pillar p {
    color: var(--slate);
  }

  /* ── 2. Type-ramp consistency ──────────────────────────────────── */

  /* Every other section h2 caps at 56px — close the two 60px outliers. */
  .testi-h2,
  .lgn-h2 {
    font-size: 56px;
  }

  /* Eyebrows: 16px uppercase competes with the sub-copy; 14px lead-in. */
  .eyebrow,
  .lgn-eyebrow {
    font-size: 14px;
  }

  /* The only 15px section sub — join the 16px siblings. */
  .faq-sub {
    font-size: 16px;
  }

  /* Testimonial quotes: 13.5px was the smallest body text on the page;
     matches the 15px already applied below 1024px. */
  .testi-card p {
    font-size: 15px;
  }

  /* FAQ answers: soften the 18px-question → 14px-answer drop. */
  .faq-list details p {
    font-size: 15px;
  }

  /* Footer group labels: at 16px uppercase they matched the links they
     label; 14px restores the label→link hierarchy. */
  .footer-col h4 {
    font-size: 14px;
  }

  /* ── 3. Icons & badges ─────────────────────────────────────────── */

  /* Footer socials: 72px dominated the footer (28px logo, 16px links). */
  .footer-socials a,
  .footer-socials img {
    width: 48px;
    height: 48px;
  }

  /* Nav brand: the base rule's own comment intends 44px on desktop but
     no override existed — the logo rendered at 32px in the 56px pill. */
  .nav-mark img {
    height: 60px;
  }

  /* Feature icons: stronger anchor for the 4-col cards (matches mobile). */
  .feature-ic {
    width: 36px;
    height: 36px;
  }

  /* Apart arrows: 20px chevron in the 42px disc (matches mobile). */
  .apart-arrow svg {
    width: 20px;
    height: 20px;
  }

  /* Apart dots: same ~24px hit-area trick as mobile — visual 8px dot
     unchanged, click target grows. */
  .apart-dot {
    box-sizing: content-box;
    padding: 8px;
    background-clip: content-box;
  }

  /* Store badges: CTA row at 56px; hero row 10% smaller (56 → 50.4px). */
  .cta-store img {
    height: 64px;
    border-radius: 16px;
  }

  .hero-app-badge img {
    height: 54px;
    border-radius: 14px;
  }

  /* ── 4. Rhythm: FAQ cards + footer rows ────────────────────────── */

  /* Closed FAQ rows ~67px → ~59px; open-state bottom 22 → 18px (the
     38px answer indent stays — desktop has the width). */
  .faq-list summary {
    padding: 16px 0;
  }

  .faq-list details>div {
    padding: 0 0 18px 38px;
  }

  /* Footer row gap was scaled to the old 72px social icons. */
  .footer-inner {
    gap: 36px;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   MOBILE (< 640px): apart carousel → vertical stack.
   The three cards stack with a 16px gap and the nav row (arrows + dots)
   is hidden; tablet (≥ 640px) and desktop keep the horizontal snap
   carousel with its nav.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 639px) {
  .apart-viewport {
    overflow-x: visible;
    scroll-snap-type: none;
  }

  .apart-track {
    flex-direction: column;
    gap: 16px;
  }

  .apart-card {
    flex: 0 0 auto;
    scroll-snap-align: none;
    scroll-snap-stop: normal;
  }

  /* Mobile serves the portrait -mob card assets (780×1464); reserve the
     matching pre-load height so the stack doesn't jump when they load. */
  .apart-card-img {
    aspect-ratio: auto 780 / 1464;
  }

  /* All three cards are stacked and always visible — the whole nav row
     (arrows + dots) is redundant here. */
  .apart-nav {
    display: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   DESKTOP + TABLET (≥ 640px): testimonials → horizontal carousel.
   Copy sits on top; all eight .testi-card elements form ONE row that
   scrolls horizontally, clipped edge-to-edge at the centred content
   grid (the .testi-inner container's --pad-x edges). Card design,
   colors and internals are untouched — only the flow direction
   changes. Mobile (< 640px) keeps its stacked column layout.
   ═══════════════════════════════════════════════════════════════════ */
@media (min-width: 640px) {

  /* Copy row above, carousel row below (overrides the desktop 1fr/1.4fr
     side-by-side split). minmax(0,1fr) — NOT bare 1fr — is load-bearing:
     1fr's auto minimum sizes the track to the nowrap card row's
     min-content (~2700px), blowing the grid past the 1280px frame to the
     screen edge AND making the scroller as wide as its content (nothing
     left to scroll, so the arrows no-op). A 0 minimum pins the track to
     the container width so the cards overflow INSIDE the scroller. */
  .testi-inner {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Belt-and-braces: the grid item wrapping the scroller must also be
     allowed to shrink below its content width. */
  .testi-carousel {
    min-width: 0;
  }

  /* The scroll viewport — spans the grid content width; overflowing
     cards are reachable by horizontal scroll (scrollbar hidden, gentle
     snap). */
  .testi-cols {
    display: flex;
    grid-template-columns: none;
    flex-wrap: nowrap;
    gap: 16px;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .testi-cols::-webkit-scrollbar {
    display: none;
  }

  /* The two former columns become inline segments of the same row. */
  .testi-col {
    flex-direction: row;
    flex: 0 0 auto;
    gap: 16px;
  }

  /* Fixed card basis (≈ the previous rendered column width) so the row
     scrolls. Every card is the same height: the body is a fixed 6-line
     box (see below), and the one-line header matches across cards. */
  .testi-card {
    flex: 0 0 320px;
    width: 320px;
    scroll-snap-align: start;
    align-self: flex-start;
  }

  /* Body copy: reserve exactly 6 lines on every card (equal heights)
     and ellipsis-clamp anything longer. */
  .testi-card p {
    display: -webkit-box;
    -webkit-line-clamp: 6;
    line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
    height: calc(6 * 1.55em);
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Testimonial carousel controls (≥ 640px): arrows + dots + edge-fades.
   Same design language as the apart carousel (frosted-glass arrows,
   8px dots with a 13px active pill and enlarged hit areas), tuned for
   the navy band. is-start / is-end classes (set by initTestiCarousel)
   dim the dead-end arrow and hide the fade on the exhausted side.
   ═══════════════════════════════════════════════════════════════════ */
.testi-carousel {
  position: relative;
}

/* Nav row below the carousel: [prev] dots [next], centred on the grid.
   Arrows never overlap the cards, so they're always clickable. */
.testi-nav {
  /* Span the FULL grid row of .testi-inner (immune to any multi-column
     template the section grid may carry) and centre the arrow–dots
     cluster on the page's view frame. */
  grid-column: 1 / -1;
  width: 100%;
  justify-self: stretch;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 18px;
  margin-top: 4px;
}

.testi-arrow {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 9999px;
  display: grid;
  place-items: center;
  cursor: pointer;
  color: #ffffff;
  background: rgba(255, 255, 255, 0.14);
  -webkit-backdrop-filter: blur(10px) saturate(150%);
  backdrop-filter: blur(10px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.30);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25), inset 0 1px 1px rgba(255, 255, 255, 0.35);
  transition: background 200ms ease, opacity 200ms ease, transform 200ms ease;
}

.testi-arrow:hover,
.testi-arrow:focus-visible {
  background: rgba(255, 255, 255, 0.26);
  transform: scale(1.07);
  outline: none;
}

.testi-arrow:active {
  transform: scale(0.96);
}

/* Dead-end arrow dims and stops catching clicks. The nav row is the
   carousel wrapper's next sibling, hence the + combinator. */
.testi-carousel.is-start+.testi-nav .testi-arrow--prev,
.testi-carousel.is-end+.testi-nav .testi-arrow--next {
  opacity: 0.35;
  pointer-events: none;
}

/* Subtle edge-fades over the clipped grid edges — visible only while
   more cards exist in that direction. */
.testi-carousel::before,
.testi-carousel::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 48px;
  z-index: 5;
  pointer-events: none;
  opacity: 1;
  transition: opacity 200ms ease;
}

.testi-carousel::before {
  left: 0;
  background: linear-gradient(90deg, var(--navy), transparent);
}

.testi-carousel::after {
  right: 0;
  background: linear-gradient(270deg, var(--navy), transparent);
}

.testi-carousel.is-start::before,
.testi-carousel.is-end::after {
  opacity: 0;
}

/* Dots — 8px idle, 13px active pill; 24px hit box via content-box
   padding (visual size unchanged); 4px margin + 8px hit padding = 12px
   visual gap below the cards. */
.testi-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}

.testi-dot {
  width: 8px;
  height: 8px;
  border: none;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.25);
  box-sizing: content-box;
  padding: 8px;
  background-clip: content-box;
  cursor: pointer;
  transition: width 240ms cubic-bezier(0.22, 1, 0.36, 1), background-color 240ms ease;
}

.testi-dot:hover {
  background-color: rgba(255, 255, 255, 0.45);
}

.testi-dot.is-active {
  width: 13px;
  background-color: var(--purple);
}

/* Mobile (< 640px): stacked list — controls and fades off. */
@media (max-width: 639px) {

  .testi-nav,
  .testi-carousel::before,
  .testi-carousel::after {
    display: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   DESKTOP + TABLET (≥ 640px): apart carousel — full-grid cards + nav.
   The stage's 980px cap is lifted so each .apart-card spans the whole
   content view-frame grid (img is width:100% height:auto → the
   2160×1360 aspect ratio is preserved). Arrows are normalised to the
   same 42px used by the testimonial nav. Mobile (< 640px) keeps the
   stacked cards with arrows hidden.
   ═══════════════════════════════════════════════════════════════════ */
@media (min-width: 640px) {
  .apart-stage {
    max-width: none;
  }

  .apart-arrow {
    width: 42px;
    height: 42px;
  }
}

/* ═══ MOBILE (< 640px): hide the CTA section's brand logo on ALL pages
   (shared stylesheet — index + subpages). Desktop/tablet keep it.
   Placed last so it wins over the earlier mobile `.cta-brand`
   display:flex reorder rule. ═══ */
@media (max-width: 639px) {
  .cta-brand {
    display: none;
  }
}

/* ═══ MOBILE (< 640px): snap checklist text 15 → 14px, weight 500 → 400.
   The .check bullet glyph itself is unchanged (20px circle). ═══ */
@media (max-width: 639px) {
  .snap-checks li {
    font-size: 14px;
    font-weight: 400;
  }
}