/* ===== CSS CUSTOM PROPERTIES =====
   Design tokens shared across the whole page — see CLAUDE.md for the
   color/usage table and font list. Change values here, not per-selector. */
:root {
  --color-primary: #e8834e;
  --color-peach: #f4a261;
  --color-sand: #fdf6ec;
  --color-beach-blue: #a8dadc;
  --color-terracotta: #9c4a2b;
  --color-dark-brown: #3d2b24;

  --font-heading: "Fraunces", Georgia, serif;
  --font-hand: "Caveat", cursive;
  --font-body: "Work Sans", sans-serif;
}

/* ===== RESET & BASE ===== */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Native smooth scroll is intentionally NOT set here: in-page anchor
   clicks are driven by a GSAP ScrollToPlugin tween (initSmoothScroll in
   js/script.js) for a slightly slower, more deliberate feel, and a native
   smooth-scroll would fight that programmatic tween. */

body {
  font-family: var(--font-body);
  color: var(--color-dark-brown);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a {
  text-decoration: none;
}

ul {
  list-style: none;
}

img {
  max-width: 100%;
  display: block;
}

/* ===== SHARED UTILITY =====
   Cross-section helpers: content-width wrappers, section headings, and
   the two button styles reused across the hero, packages, and CTAs. */
.section-container {
  max-width: 1100px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

.section-container-sm {
  max-width: 760px;
  margin: 0 auto;
}

.section-title {
  text-align: center;
  margin-bottom: 3.5rem;
}

.section-title h2 {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: clamp(2.688rem, 4vw, 3.584rem);
  color: var(--color-dark-brown);
}

.btn-primary {
  background: var(--color-primary);
  color: var(--color-sand);
  padding: 0.55rem 1.4rem;
  border-radius: 999px;
  font-size: 0.98rem;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.2s;
  display: inline-block;
}

.btn-primary:hover {
  background: #d4724a;
}

.btn-outline {
  border: 1.5px solid rgba(253, 246, 236, 0.6);
  color: var(--color-sand);
  padding: 0.85rem 2rem;
  border-radius: 999px;
  font-weight: 500;
  font-size: 1.12rem;
  transition: border-color 0.2s;
  display: inline-block;
}

.btn-outline:hover {
  border-color: rgba(253, 246, 236, 1);
}

/********** MOBILE-FIRST — base styles are for < 480px **********/

/* ===== HEADER =====
   Fixed/sticky bar, transparent over the hero photo and switching to a
   solid frosted background once .is-scrolled is toggled by JS on scroll. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  height: 64px;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition:
    background 0.35s ease,
    backdrop-filter 0.35s ease,
    box-shadow 0.35s ease;
}

.site-header.is-scrolled {
  background: rgba(253, 246, 236, 0.9);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 2px 20px rgba(61, 43, 36, 0.1);
}

/* Caps the header content to the same width as .section-container (used
   by every other section) so the header aligns with the page content
   instead of spanning full viewport width. The bar itself (.site-header)
   stays edge-to-edge so its background still fills the full width. */
.header-inner {
  max-width: 1100px;
  height: 100%;
  margin: 0 auto;
  padding: 0 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header-logo {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.logo-text {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.232rem;
  color: #fff;
  transition: color 0.35s ease;
}

.site-header.is-scrolled .logo-text {
  color: var(--color-dark-brown);
}

.header-nav {
  display: none;
}

.header-nav a {
  font-size: 1.008rem;
  font-weight: 500;
  color: #fff;
  opacity: 0.85;
  transition:
    opacity 0.2s,
    color 0.35s ease;
  position: relative;
  display: inline-block;
}

.header-nav a:hover {
  opacity: 1;
}

.site-header.is-scrolled .header-nav a {
  color: var(--color-dark-brown);
}

/* Hand-drawn underline SVG for nav links */
.header-nav a .nav-underline {
  position: absolute;
  left: -4px;
  right: -4px;
  bottom: -4px;
  height: 8px;
  width: calc(100% + 8px);
  pointer-events: none;
  overflow: visible;
}

.header-nav a .nav-underline path {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.header-cta {
  padding: 0.55rem 1rem;
}

/* ===== HERO =====
   Full-viewport photo with a text scrim (see .hero-content below) so the
   headline stays legible over whatever image gets dropped in. */
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: #2a1f1a;
}

.hero-bg {
  position: absolute;
  inset: 0;
  background: #2a1f1a;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero-bg-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.placeholder-text-sm {
  font-size: 0.784rem;
  color: rgba(156, 74, 43, 0.6);
  line-height: 1.5;
  max-width: 200px;
}

.placeholder-label {
  font-size: 0.672rem;
  color: var(--color-primary);
  display: block;
  margin-top: 0.25rem;
}

.hero-deco-circles {
  position: absolute;
  top: 15%;
  right: 15%;
  opacity: 0.4;
  display: none;
}

.hero-deco-notes {
  position: absolute;
  bottom: 20%;
  left: 10%;
  opacity: 0.35;
  display: none;
}

/* Slight uniform darkening over the whole photo — independent of the
   text-shadow on the title/subtext, just lowers the photo's overall
   brightness a touch. */
.hero-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.1);
  pointer-events: none;
}

.hero-content {
  position: relative;
  z-index: 10;
  padding: 6rem 1.5rem 3rem;
  max-width: 720px;
  margin-left: 0;
}

/* Legibility over the photo comes from text-shadow directly on the
   glyphs (layered blur, darkest closest to the letter) instead of a
   background scrim — this avoids any box/gradient edge behind the text
   while still lifting contrast on busy parts of the photo. */
.hero-content h1 {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: clamp(2.688rem, 6vw, 5.6rem);
  line-height: 1.08;
  color: var(--color-sand);
  margin-bottom: 1.5rem;
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.85),
    0 4px 14px rgba(0, 0, 0, 0.6),
    0 10px 30px rgba(0, 0, 0, 0.35);
}

.hero-content h1 em {
  color: var(--color-primary);
  font-style: italic;
}

.hero-content p {
  color: rgba(253, 246, 236, 0.9);
  font-size: 1.176rem;
  line-height: 1.65;
  max-width: 480px;
  margin-bottom: 2.5rem;
  font-weight: 400;
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.85),
    0 3px 10px rgba(0, 0, 0, 0.55);
}

.hero-buttons {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.hero-buttons .btn-primary {
  padding: 0.85rem 1.5rem;
  font-size: 1.064rem;
}

.hero-buttons .btn-outline {
  padding: 0.85rem 1.5rem;
  font-size: 1.064rem;
}

/* ===== ABOUT =====
   Bio + differentiators grid. Still in the "daylight" part of the day
   narrative, so stays on the light sand background. */
.about {
  background: var(--color-sand);
  padding: 3rem 1.5rem;
  position: relative;
  overflow: hidden;
}

.about-deco-notes {
  position: absolute;
  top: 1rem;
  right: 1rem;
  color: rgba(232, 131, 78, 0.1);
  font-size: 5.6rem;
  font-family: serif;
  user-select: none;
  line-height: 1;
}

.about-deco-staff {
  display: none;
}

.about-grid {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: center;
}

.about-photo-wrap {
  position: relative;
  /* Shrunk on mobile so the photo reads as an accent between the title and
     body text rather than a full-width block; restored to full column width
     at 768px where it moves back to the side-by-side layout. */
  max-width: 220px;
  margin: 0 auto;
}

.about-photo {
  width: 100%;
  aspect-ratio: 4/5;
  object-fit: cover;
  border-radius: 8px;
}

.about-accent-block {
  position: absolute;
  bottom: -1rem;
  right: -1rem;
  width: 80px;
  height: 80px;
  background: var(--color-primary);
  border-radius: 4px;
  z-index: -1;
}

.about-title {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: clamp(2.016rem, 3.5vw, 3.136rem);
  line-height: 1.15;
  margin-bottom: 1.25rem;
  color: var(--color-dark-brown);
}

.about-info > p {
  font-size: 1.12rem;
  line-height: 1.7;
  color: rgba(61, 43, 36, 0.8);
  margin-bottom: 2rem;
  max-width: 460px;
}

.differentiators {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

.diff-item {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.diff-icon {
  font-size: 1.68rem;
}

.diff-item strong {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.12rem;
  color: var(--color-dark-brown);
}

.diff-item p {
  font-size: 0.98rem;
  line-height: 1.55;
  color: rgba(61, 43, 36, 0.7);
  margin: 0;
}

/* ===== HOW IT WORKS =====
   Steps + pricing packages. The background gradient transitions the sky
   from beach-blue at the top into sandy tones at the bottom, handing off
   visually into the Repertoire section's sand background below it. */
.how-it-works {
  background: linear-gradient(
    180deg,
    var(--color-beach-blue) 0%,
    #c8ecee 45%,
    #dde8d5 70%,
    #eef2de 85%,
    #f7edd8 100%
  );
  padding: 3rem 1.5rem;
  position: relative;
  overflow: hidden;
}

.clouds-layer {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.cloud {
  position: absolute;
  /* SVGs are 220px wide intrinsically; shrunk on mobile so the clouds don't
     dominate the narrow column (restored to full size at 768px). */
  width: 150px;
}

/* Each cloud gets its own hand-picked position/opacity/scale so they read
   as scattered rather than a repeated tiled pattern. Opacities are pushed
   noticeably higher than the section's other decorative layers so the
   clouds stay a visible motif from top to bottom, not just a faint wash
   near the top. */
.cloud-1 {
  top: 2%;
  left: -2%;
  opacity: 0.85;
  transform: scale(1.25);
}
.cloud-2 {
  top: 1%;
  left: 30%;
  opacity: 0.75;
  transform: scale(0.95);
}
.cloud-3 {
  top: 3%;
  right: 0%;
  opacity: 0.8;
  transform: scale(1.35);
}
.cloud-4 {
  top: 28%;
  left: -3%;
  opacity: 0.55;
  transform: scale(0.9);
}
.cloud-5 {
  top: 32%;
  right: -1%;
  opacity: 0.5;
  transform: scale(0.95);
}
.cloud-6 {
  top: 38%;
  left: 55%;
  opacity: 0.42;
  transform: scale(0.8);
}
.cloud-7 {
  bottom: 8%;
  left: 2%;
  opacity: 0.5;
  transform: scale(0.85);
}
.cloud-8 {
  bottom: 5%;
  right: 3%;
  opacity: 0.45;
  transform: scale(1.05);
}
.cloud-9 {
  bottom: 12%;
  left: 38%;
  opacity: 0.4;
  transform: scale(0.75);
}
.cloud-10 {
  top: 12%;
  left: 15%;
  opacity: 0.6;
  transform: scale(0.7);
}
.cloud-11 {
  top: 50%;
  left: 20%;
  opacity: 0.38;
  transform: scale(0.65);
}
.cloud-12 {
  bottom: 2%;
  right: 20%;
  opacity: 0.48;
  transform: scale(0.9);
}
/* Extra low clouds so the motif keeps showing up further down the
   section, near/behind the pricing cards, instead of thinning out. */
.cloud-13 {
  bottom: -3%;
  left: 10%;
  opacity: 0.4;
  transform: scale(1.15);
}
.cloud-14 {
  bottom: -1%;
  right: 25%;
  opacity: 0.35;
  transform: scale(0.85);
}
.cloud-15 {
  bottom: 20%;
  left: 72%;
  opacity: 0.35;
  transform: scale(0.7);
}
.cloud-16 {
  bottom: 40%;
  right: 45%;
  opacity: 0.3;
  transform: scale(0.6);
}

/* Fill clouds: target the mid-section band around the "Choose your
   package" heading and the strips just outside the pricing cards, which
   the first 16 leave sparse. */
.cloud-17 {
  top: 55%;
  left: -2%;
  opacity: 0.55;
  transform: scale(1.1);
}
.cloud-18 {
  top: 58%;
  right: -3%;
  opacity: 0.5;
  transform: scale(1.2);
}
/* Flanking the "Choose your package" heading */
.cloud-19 {
  top: 44%;
  left: 6%;
  opacity: 0.42;
  transform: scale(0.8);
}
.cloud-20 {
  top: 46%;
  right: 8%;
  opacity: 0.45;
  transform: scale(0.9);
}
/* Low strips beside the pricing cards */
.cloud-21 {
  bottom: 16%;
  left: -3%;
  opacity: 0.4;
  transform: scale(1);
}
.cloud-22 {
  bottom: 24%;
  right: -3%;
  opacity: 0.42;
  transform: scale(1.15);
}
.cloud-23 {
  top: 20%;
  right: 10%;
  opacity: 0.45;
  transform: scale(0.7);
}
.cloud-24 {
  top: 62%;
  left: 44%;
  opacity: 0.32;
  transform: scale(0.75);
}

/* Mobile thins the sky out: 24 clouds packed into a phone-width column read as
   a solid white blur, so only ~12 well-spread ones survive here and the rest
   come back at 768px. initCloudDrift() skips whatever is display:none, so the
   hidden ones cost no animation either. cloud-4 (top:28%) and cloud-10
   (top:12%) are kept visible here (unlike >=768px, which hides nothing) to
   fill the gap between the top cluster and cloud-5 (32%) — otherwise that
   whole span lands right on the "Book online"/"Schedule a time" step cards
   with nothing showing. */
.cloud-6,
.cloud-9,
.cloud-12,
.cloud-14,
.cloud-15,
.cloud-16,
.cloud-17,
.cloud-19,
.cloud-20,
.cloud-21,
.cloud-23,
.cloud-24 {
  display: none;
}

/* Steps */
.steps-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-bottom: 3rem;
}

.step-card {
  text-align: center;
}

.step-num {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-sand);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.232rem;
  margin: 0 auto 1.25rem;
}

.step-card h3 {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.904rem;
  color: var(--color-dark-brown);
  margin-bottom: 0.6rem;
}

.step-card p {
  font-size: 1.008rem;
  line-height: 1.65;
  color: rgba(61, 43, 36, 0.75);
  max-width: 260px;
  margin: 0 auto;
}

/* Packages */
.packages-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

.package-card {
  background: var(--color-sand);
  border-radius: 12px;
  padding: 2rem;
  position: relative;
  box-shadow: 0 2px 16px rgba(61, 43, 36, 0.08);
  transition: transform 0.2s;
}

.package-card:hover {
  transform: translateY(-4px);
}

.package-card.popular {
  background: var(--color-primary);
  box-shadow: 0 8px 32px rgba(232, 131, 78, 0.35);
}

.popular-badge {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-terracotta);
  color: var(--color-sand);
  font-size: 0.784rem;
  font-weight: 600;
  padding: 3px 14px;
  border-radius: 999px;
  white-space: nowrap;
}

.package-card h3 {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.4rem;
  color: var(--color-dark-brown);
  margin-bottom: 0.5rem;
}

.package-card.popular h3 {
  color: var(--color-sand);
}

.package-price {
  margin-bottom: 1.5rem;
}

.package-price .price {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 2.24rem;
  color: var(--color-dark-brown);
}

.package-card.popular .price {
  color: var(--color-sand);
}

.package-price .per {
  font-size: 0.896rem;
  color: rgba(61, 43, 36, 0.55);
  margin-left: 0.4rem;
}

.package-card.popular .per {
  color: rgba(253, 246, 236, 0.75);
}

.package-features {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 2rem;
  padding: 0;
}

.package-features li {
  font-size: 0.98rem;
  color: rgba(61, 43, 36, 0.75);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.package-card.popular .package-features li {
  color: rgba(253, 246, 236, 0.9);
}

.package-features .check {
  color: var(--color-primary);
  font-weight: 700;
}

.package-card.popular .check {
  color: var(--color-sand);
}

.btn-package {
  display: block;
  text-align: center;
  padding: 0.75rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 1.008rem;
  background: var(--color-primary);
  color: var(--color-sand);
  transition: opacity 0.2s;
}

.btn-package:hover {
  opacity: 0.85;
}

.package-card.popular .btn-package {
  background: var(--color-sand);
  color: var(--color-terracotta);
}

/* ===== REPERTOIRE =====
   Song tabs/cards, centered, with a palm tree photo flanking each side
   on wider viewports. Audio playback and tab switching logic live in
   js/script.js (initTabs / renderSongs). */
.repertoire {
  background: #f7edd8;
  padding: 3rem 1.5rem;
  position: relative;
  overflow: hidden;
}

.repertoire-songs {
  max-width: 640px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

/* Palm tree photos: decorative, hidden on mobile where there's no room
   beside the centered song list without crowding it. */
.repertoire-palm {
  display: none;
  position: absolute;
  bottom: 0;
  height: 100%;
  width: auto;
  object-fit: contain;
  pointer-events: none;
}

/* Pulled in from the viewport edge toward the (max 1100px) content
   container, so the gap to the centered song list doesn't balloon on
   very wide screens; max() keeps them flush at 0 below that width. */
.repertoire-palm--left {
  left: max(0px, calc(50% - 680px));
}

.repertoire-palm--right {
  right: max(0px, calc(50% - 680px));
}

.tabs-bar {
  display: flex;
  background: var(--color-sand);
  border-radius: 8px;
  padding: 4px;
  margin-bottom: 1.5rem;
  box-shadow: 0 1px 4px rgba(61, 43, 36, 0.1);
}

.tab-btn {
  flex: 1;
  padding: 0.5rem;
  border-radius: 6px;
  border: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.952rem;
  transition: all 0.2s;
  background: transparent;
  color: rgba(61, 43, 36, 0.65);
}

.tab-btn.active {
  background: var(--color-primary);
  color: var(--color-sand);
}

.song-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.song-card {
  background: var(--color-sand);
  border-radius: 10px;
  padding: 1rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  box-shadow: 0 1px 8px rgba(61, 43, 36, 0.07);
}

.song-play-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  transition: transform 0.2s;
}

.song-play-btn:hover {
  transform: scale(1.1);
}

.song-info {
  flex: 1;
  min-width: 0;
}

.song-info .song-title {
  font-weight: 600;
  font-size: 1.008rem;
  color: var(--color-dark-brown);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
}

.song-info .song-artist {
  font-size: 0.874rem;
  color: rgba(61, 43, 36, 0.6);
  margin: 2px 0 6px;
}

.waveform {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 20px;
}

.waveform-bar {
  width: 3px;
  background: rgba(232, 131, 78, 0.5);
  border-radius: 2px;
}

/* Applied by js/script.js while a preview is playing, so the bars
   pulse like a live equalizer instead of sitting static. */
.waveform.is-playing .waveform-bar {
  background: var(--color-primary);
  animation: waveform-pulse 0.9s ease-in-out infinite;
}

.waveform.is-playing .waveform-bar:nth-child(3n + 1) {
  animation-delay: 0.15s;
}

.waveform.is-playing .waveform-bar:nth-child(3n + 2) {
  animation-delay: 0.3s;
}

@keyframes waveform-pulse {
  0%,
  100% {
    transform: scaleY(0.6);
  }
  50% {
    transform: scaleY(1);
  }
}

.song-style-badge {
  background: rgba(232, 131, 78, 0.12);
  color: var(--color-terracotta);
  font-size: 0.762rem;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ===== TESTIMONIALS =====
   First section in the "golden hour" half of the day narrative — the
   background gradient shifts from peach into a warmer, deeper tone. */
.testimonials {
  background: linear-gradient(
    180deg,
    var(--color-peach) 0%,
    #f0c090 55%,
    #f2b5a0 100%
  );
  /* Bottom padding is smaller than the top: this section hands off
     directly into .faq below, so the shared boundary shouldn't get
     double the breathing room of the section's other edges. */
  padding: 3rem 1.5rem 1.5rem;
}

.testimonials .section-container-sm {
  max-width: 920px;
}

.testimonials-list {
  display: flex;
  flex-direction: column;
  gap: 2.75rem;
}

.testimonial-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
}

/* On mobile (stacked column layout) .right rows mirror to the opposite
   side so the brown avatar sits on the right, matching the alternating
   left/right pattern that only kicks in via flex-direction at 768px
   otherwise. Reset back to flex-start there since align-items maps to
   the vertical axis once the row becomes horizontal. */
.testimonial-row.right {
  align-items: flex-end;
}

.testimonial-avatar {
  flex-shrink: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

.avatar-circle {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  color: var(--color-sand);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.456rem;
  box-shadow: 0 2px 8px rgba(61, 43, 36, 0.2);
}

.avatar-circle.dark {
  background: var(--color-dark-brown);
}

.avatar-circle.brown {
  background: var(--color-terracotta);
}

.testimonial-bubble-wrap {
  position: relative;
  max-width: 100%;
}

/* On mobile the avatar sits above the bubble (stacked layout, both
   left-aligned via .testimonial-row's align-items: flex-start), so the
   tail points straight up out of the gap between them instead of
   sideways. left: 32px centers it under the avatar-circle (64px wide).
   The sideways version (pointing at the avatar from beside the bubble)
   takes over once the row layout kicks in at 768px, see below. */
.bubble-tail {
  display: block;
  position: absolute;
  top: -8px;
  left: 32px;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
}

/* Colors match each row's bubble (cream for .left rows, orange for
   .right rows) — same pairing the sideways desktop tail uses via inline
   style, just expressed as a border-bottom here instead of a side. */
.bubble-tail.left {
  border-bottom: 8px solid var(--color-sand);
}

.bubble-tail.right {
  left: auto;
  right: 32px;
  transform: translateX(50%);
  border-bottom: 8px solid var(--color-primary);
}

.bubble {
  border-radius: 18px;
  padding: 1rem 1.25rem;
  box-shadow: 0 2px 12px rgba(61, 43, 36, 0.12);
}

/* The 4px corner (vs 18px elsewhere) is what points toward the avatar,
   simulating a chat-bubble tail alongside .bubble-tail. */
.bubble.cream {
  background: var(--color-sand);
  border-radius: 18px 18px 18px 4px;
}

.bubble.orange {
  background: var(--color-primary);
  border-radius: 18px 18px 4px 18px;
}

.bubble-name {
  margin: 0 0 0.5rem;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1.12rem;
  color: var(--color-terracotta);
}

.bubble-name.light {
  color: var(--color-sand);
}

.bubble .quote {
  margin: 0 0 0.75rem;
  font-size: 1.064rem;
  line-height: 1.65;
  color: var(--color-dark-brown);
  font-style: italic;
}

.bubble .quote.light {
  color: var(--color-sand);
}

.bubble .role {
  margin: 0;
  font-size: 0.84rem;
  color: rgba(61, 43, 36, 0.5);
  font-weight: 500;
  text-align: left;
}

.bubble .role.light {
  color: rgba(253, 246, 236, 0.65);
}

/* WhatsApp-style "typing" indicator shown briefly before each bubble is
   revealed by initTestimonialChat(). It's created in JS and never lives in
   the HTML, so with JavaScript disabled the real bubbles simply show from
   the start (static-first). Shaped and coloured to match the bubble that
   will replace it: cream + bottom-left corner for .left rows, orange +
   bottom-right corner for .right rows.
   position:absolute (pinned to the top corner of the bubble's slot) keeps
   it OUT of the flow: the real bubble stays in the flow the whole time and
   reserves the section's final height from the start, so nothing jumps as
   the messages arrive — and the bubble-tail, measured from the wrap's top,
   lines up with the bubble instead of with the (now flow-less) dots.
   display:flex + fit-content so it hugs the avatar side rather than
   stretching to the wrap's full width like the real bubble does. */
.typing-indicator {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 5px;
  padding: 0.95rem 1.15rem;
  border-radius: 18px 18px 18px 4px;
  background: var(--color-sand);
  box-shadow: 0 2px 12px rgba(61, 43, 36, 0.12);
}

/* .right rows send from the right edge, so pin the dots there instead. */
.testimonial-row.right .typing-indicator {
  left: auto;
  right: 0;
  background: var(--color-primary);
  border-radius: 18px 18px 4px 18px;
}

/* The three bouncing dots. Each is offset in time (delays below) so the
   bounce ripples left-to-right like the real chat app. */
.typing-indicator .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-terracotta);
  animation: typing-bounce 1.2s infinite ease-in-out;
}

.testimonial-row.right .typing-indicator .dot {
  background: var(--color-sand);
}

.typing-indicator .dot:nth-child(2) {
  animation-delay: 0.18s;
}

.typing-indicator .dot:nth-child(3) {
  animation-delay: 0.36s;
}

@keyframes typing-bounce {
  0%,
  60%,
  100% {
    transform: translateY(0);
    opacity: 0.45;
  }
  30% {
    transform: translateY(-5px);
    opacity: 1;
  }
}

/* ===== FAQ =====
   Accordion list; open/close state is toggled by initFAQ() in
   js/script.js via the .faq-item.open class (only one open at a time). */
.faq {
  background: linear-gradient(180deg, #f2b5a0 0%, #f7d5b0 100%);
  /* Top padding is smaller than the bottom to match the reduced bottom
     padding on .testimonials above it — see comment there. */
  padding: 1.5rem 1.5rem 3rem;
}

.faq-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.faq-item {
  background: rgba(253, 246, 236, 0.75);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 8px rgba(61, 43, 36, 0.07);
}

.faq-question {
  width: 100%;
  text-align: left;
  padding: 1.25rem 1.5rem;
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  font-family: var(--font-body);
}

.faq-question span:first-child {
  font-weight: 500;
  font-size: 1.12rem;
  color: var(--color-dark-brown);
  line-height: 1.4;
}

.faq-icon {
  color: var(--color-primary);
  font-size: 1.344rem;
  flex-shrink: 0;
  transition: transform 0.2s;
  display: inline-block;
}

.faq-item.open .faq-icon {
  transform: rotate(45deg);
}

/* Padding lives on the inner <p>, not on .faq-answer itself, so the
   answer can collapse to a true height: 0 with no leftover padding gap
   when the GSAP height tween closes it (see initFAQ). display: none is the
   no-JS fallback — with JS active, initFAQ switches closed answers to a
   collapsed display: block it can animate. */
.faq-answer {
  padding: 0;
  display: none;
}

.faq-item.open .faq-answer {
  display: block;
}

.faq-answer p {
  margin: 0;
  padding: 0 1.5rem 1.25rem;
  font-size: 1.008rem;
  line-height: 1.7;
  color: rgba(61, 43, 36, 0.8);
}

/* ===== FINAL CTA =====
   Most saturated orange of the page — the peak of the "golden hour"
   narrative, right before the intentionally dark/cold footer. */
.final-cta {
  background: var(--color-primary);
  padding: 4rem 1.5rem;
  text-align: center;
  position: relative;
  overflow: hidden;
}

/* Musical notes: small brand-identity accents that echo the illustration
   style used elsewhere (e.g. the clouds in "How it works"). Kept low-
   opacity and off to the sides so they never compete with the headline
   or button, which stay above them via .cta-content's z-index. */
.cta-note {
  position: absolute;
  width: 52px;
  height: auto;
  opacity: 0.4;
}

/* Pulled into the section's corners on mobile — the centered text column
   fills nearly the full width there, so anything closer to center would
   sit right on top of the headline/button; pushed back out toward the
   original values at 480px once there's more room to spare. */
.cta-note-1 {
  top: 5%;
  left: 4%;
  width: 40px;
  transform: rotate(-8deg);
}

.cta-note-2 {
  bottom: 6%;
  right: 4%;
  width: 34px;
  transform: rotate(10deg);
}

.cta-content {
  position: relative;
  z-index: 1;
  max-width: 600px;
  margin: 0 auto;
}

.cta-content h2 {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: clamp(2.24rem, 5vw, 4.256rem);
  line-height: 1.1;
  color: var(--color-sand);
  margin-bottom: 1.25rem;
}

.cta-content p {
  color: rgba(253, 246, 236, 0.82);
  font-size: 1.176rem;
  line-height: 1.65;
  max-width: 440px;
  margin: 0 auto 2.5rem;
}

.btn-cta-final {
  display: inline-block;
  background: var(--color-sand);
  color: var(--color-terracotta);
  padding: 1rem 2rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 1.176rem;
  box-shadow: 0 4px 20px rgba(61, 43, 36, 0.2);
  transition:
    transform 0.2s,
    box-shadow 0.2s;
}

.btn-cta-final:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 28px rgba(61, 43, 36, 0.25);
}

/* ===== FOOTER =====
   Intentional exception to the "always warm/light" rule (see CLAUDE.md)
   — a dark, utilitarian close rather than part of the day narrative. */
.site-footer {
  background: var(--color-dark-brown);
  padding: 2rem 1.5rem;
}

.footer-grid {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1.5rem;
}

.footer-logo {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.footer-logo span {
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.232rem;
  color: var(--color-sand);
}

.footer-brand p {
  font-size: 0.896rem;
  color: rgba(253, 246, 236, 0.5);
  max-width: 200px;
  line-height: 1.5;
  margin: 0;
}

.footer-heading {
  font-weight: 600;
  font-size: 0.952rem;
  color: var(--color-sand);
  margin-bottom: 0.5rem;
  margin-top: 0;
}

.footer-contact a,
.footer-social a {
  display: block;
  font-size: 0.93rem;
  color: rgba(253, 246, 236, 0.55);
  text-decoration: none;
  margin-bottom: 0.3rem;
  transition: color 0.2s;
}

.footer-contact a:first-of-type {
  color: var(--color-primary);
}

.footer-contact a:hover,
.footer-social a:hover {
  color: var(--color-primary);
}

.footer-sub {
  font-size: 0.896rem;
  color: rgba(253, 246, 236, 0.4);
  margin-top: 0.3rem;
  margin-bottom: 0;
}

.footer-social {
  display: flex;
  flex-direction: column;
}

.footer-social-icons {
  display: flex;
  gap: 0.75rem;
}

.footer-social-icons a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-bottom: 0;
  border-radius: 50%;
  color: rgba(253, 246, 236, 0.55);
  border: 1px solid rgba(253, 246, 236, 0.2);
  transition:
    color 0.2s,
    border-color 0.2s;
}

.footer-social-icons a:hover {
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.footer-bottom {
  max-width: 1100px;
  margin: 1.5rem auto 0;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(253, 246, 236, 0.1);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  text-align: center;
}

.footer-bottom p {
  font-size: 0.84rem;
  color: rgba(253, 246, 236, 0.3);
  margin: 0;
}

/* ================================================================
   RESPONSIVE BREAKPOINTS (mobile-first, min-width)
   ================================================================ */

/* >= 480px — large mobile
   Mostly padding/font-size bumps across header, hero, about, and the
   golden-hour sections; no layout/grid changes happen until 768px. */
@media (min-width: 480px) {
  .header-cta {
    padding: 0.55rem 1.4rem;
  }

  .hero-content {
    padding: 7rem 2rem 3rem;
  }

  .hero-buttons .btn-primary,
  .hero-buttons .btn-outline {
    padding: 0.85rem 2rem;
    font-size: 1.12rem;
  }

  .about {
    padding: 4rem 2rem;
  }

  .how-it-works,
  .repertoire {
    padding: 4rem 2rem;
  }

  .testimonials {
    padding: 4rem 2rem 2rem;
  }

  .faq {
    padding: 2rem 2rem 4rem;
  }

  .final-cta {
    padding: 5rem 2rem;
  }

  .site-footer {
    padding: 3rem 2rem;
  }

  /* Final CTA notes get a little more room and size once the section
     itself gains extra padding at this breakpoint — still corner-anchored,
     just scaled up along with everything else. */
  .cta-note-1 {
    width: 56px;
    top: 6%;
    left: 6%;
  }

  .cta-note-2 {
    width: 44px;
    bottom: 7%;
    right: 6%;
  }

  .btn-cta-final {
    padding: 1rem 2.5rem;
  }
}

/* >= 768px — tablet
   Layout shift point: nav becomes visible, single-column grids (about,
   packages, repertoire) switch to multi-column, testimonials go
   side-by-side with alternating left/right alignment. */
@media (min-width: 768px) {
  /* How it works: the full sky comes back — every cloud at its intrinsic
     220px, including the ones the mobile base rules hide. */
  .cloud {
    width: 220px;
  }

  .cloud-4,
  .cloud-6,
  .cloud-9,
  .cloud-10,
  .cloud-12,
  .cloud-14,
  .cloud-15,
  .cloud-16,
  .cloud-17,
  .cloud-19,
  .cloud-20,
  .cloud-21,
  .cloud-23,
  .cloud-24 {
    display: block;
  }

  .header-inner {
    padding: 0 2rem;
  }

  .header-nav {
    display: flex;
    gap: 2rem;
  }

  .header-cta {
    display: inline-block;
  }

  .hero-content {
    margin-left: clamp(1rem, 8vw, 6rem);
    padding: 8rem 2.5rem 4rem;
  }

  .hero-deco-circles,
  .hero-deco-notes {
    display: block;
  }

  .about {
    padding: clamp(4rem, 8vw, 7rem) clamp(1.5rem, 6vw, 5rem);
  }

  .about-deco-staff {
    display: block;
    position: absolute;
    bottom: 1rem;
    left: 1.5rem;
    opacity: 0.12;
  }

  .about-deco-notes {
    top: 2rem;
    right: 2rem;
    font-size: 8.96rem;
  }

  /* Mobile stacks title -> photo -> info by source order (see HTML); desktop
     instead pins the photo beside both via named areas, independent of
     source order. */
  .about-grid {
    grid-template-columns: minmax(280px, 380px) 1fr;
    grid-template-areas: "photo title" "photo info";
    gap: 1.25rem 4rem;
  }

  .about-photo-wrap {
    grid-area: photo;
    max-width: none;
    margin: 0;
  }

  .about-title {
    grid-area: title;
  }

  .about-info {
    grid-area: info;
  }

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

  .steps-grid {
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    margin-bottom: 5rem;
  }

  .packages-grid {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  }

  .testimonial-row.left {
    flex-direction: row;
  }

  .testimonial-row.right {
    flex-direction: row-reverse;
  }

  /* Top-align avatar with bubble so the circle sits higher than the
     bubble instead of floating at its vertical center; the tail (fixed
     at 32px, half the avatar-circle height) tracks the avatar's middle
     regardless of how tall a given quote makes the bubble. Also resets
     .testimonial-row.right's mobile flex-end (a horizontal mirror there)
     back to flex-start, since align-items now maps to the vertical axis
     once flex-direction switches to row/row-reverse. */
  .testimonial-row,
  .testimonial-row.right {
    align-items: flex-start;
    gap: 1.75rem;
  }

  /* Back to the sideways tail pointing at the avatar beside the bubble
     (top fixed at half the avatar-circle height, 64px / 2, so it tracks
     the avatar's middle regardless of bubble height), replacing the
     mobile upward tail set above. */
  .bubble-tail {
    display: block;
    top: 32px;
    left: auto;
    transform: translateY(-50%);
    border-left: 0;
    border-right: 0;
    border-bottom: 0;
  }

  .bubble-tail.left {
    left: -7px;
    border-right: 8px solid;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
  }

  .bubble-tail.right {
    right: -7px;
    border-left: 8px solid;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
  }

  .testimonial-avatar {
    flex-direction: column;
  }

  /* Narrower bubbles shrink from the edge farther from the avatar:
     .left rows lay out avatar->bubble (row), so the bubble's right edge
     moves in; .right rows use row-reverse (bubble->avatar), so the
     bubble's left edge moves in. Either way the edge next to the
     avatar (and its tail) stays put. */
  .testimonial-bubble-wrap {
    max-width: 62%;
  }

  .testimonials {
    padding: clamp(4rem, 8vw, 7rem) clamp(1.5rem, 6vw, 5rem)
      clamp(2rem, 4vw, 3rem);
  }

  .faq {
    padding: clamp(2rem, 4vw, 3rem) clamp(1.5rem, 6vw, 5rem)
      clamp(4rem, 8vw, 7rem);
  }

  .final-cta {
    padding: clamp(5rem, 10vw, 8rem) clamp(1.5rem, 6vw, 5rem);
  }

  .footer-grid {
    flex-direction: row;
    gap: 2rem;
  }

  .footer-bottom {
    flex-direction: row;
    text-align: left;
  }
}

/* >= 1024px — desktop
   Footer gets a wider gutter now there's room, and the repertoire palm
   trees appear now the viewport is wide enough to fit them without
   crowding the centered song list. */
@media (min-width: 1024px) {
  .site-footer {
    padding: 3rem clamp(1.5rem, 6vw, 5rem);
  }

  .repertoire-palm {
    display: block;
  }
}
