/* ==========================================================================
   Angel Aussies — Design Tokens
   Theme: "Angel Puppies" — soft, airy, a little celestial. Warm, not
   saccharine; elegant, not corporate.
   ========================================================================== */

:root {
  /* ---- Color: warm whites, cream, pale gold, muted sky, deep ink ---- */
  --color-bg: #fdfbf6;         /* warm white — base page background */
  --color-bg-alt: #f6eedd;     /* soft cream — alternate section background */
  --color-gold: #e3c68c;       /* pale gold — accents, dividers, glows */
  --color-gold-soft: #f3e6c8;  /* light gold tint — subtle washes */
  --color-sky: #a8c5d6;        /* muted sky blue — secondary accent */
  --color-sky-soft: #dfebf1;   /* light sky tint — subtle washes */
  --color-ink: #333a4d;        /* deep accent — text, buttons, headings */
  --color-ink-soft: #62697c;   /* muted ink — secondary text */
  --color-white: #ffffff;

  /* ---- Type families ---- */
  --font-display: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  --font-body: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    sans-serif;

  /* ---- Type scale (mobile-first base; enhanced at min-width below) ---- */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;
  --text-4xl: 2.75rem;
  --text-5xl: 3.25rem;
  --text-hero: 3.25rem;

  /* ---- Spacing scale ---- */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2rem;
  --space-xl: 3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;

  /* ---- Radii ---- */
  --radius-sm: 6px;
  --radius-md: 14px;
  --radius-lg: 28px;
  --radius-full: 999px;

  /* ---- Shadows (soft, ink-tinted for an airy feel — never pure black) --- */
  --shadow-sm: 0 2px 8px rgba(51, 58, 77, 0.06);
  --shadow-md: 0 8px 24px rgba(51, 58, 77, 0.1);
  --shadow-lg: 0 20px 48px rgba(51, 58, 77, 0.14);
  --shadow-glow-gold: 0 0 32px rgba(227, 198, 140, 0.4);

  /* ---- Layout ---- */
  --content-max-width: 1100px;
  --side-padding: 1.25rem;

  /* ---- Motion ---- */
  --transition-base: 0.25s ease;
  --transition-slow: 0.5s ease;
  /* Shared reveal curve — every fade/drift-up across the site (hero
     entrance, Section 2's scroll sequence, Section 3's fade-up, the
     Section 4-7 .reveal-up utility) uses this same easing so the whole
     page feels like one hand made it. */
  --ease-reveal: cubic-bezier(0.16, 0.6, 0.24, 1);
}

/* Small tablets and up */
@media (min-width: 640px) {
  :root {
    --side-padding: 2rem;
  }
}

/* Desktop and up */
@media (min-width: 768px) {
  :root {
    --text-base: 1.0625rem;
    --text-lg: 1.25rem;
    --text-xl: 1.625rem;
    --text-2xl: 2.25rem;
    --text-3xl: 3rem;
    --text-4xl: 3.75rem;
    --text-5xl: 4.5rem;
    --text-hero: 5.5rem;
  }
}

/* Large desktop and up */
@media (min-width: 1024px) {
  :root {
    --side-padding: 3rem;
    --text-hero: 6.5rem;
  }
}

/* Wide desktop/laptop screens — the hero title in particular reads small
   on a wide, short window otherwise, since --text-hero stops growing
   past the 1024px tier. */
@media (min-width: 1440px) {
  :root {
    --text-hero: 7.75rem;
    --text-xl: 1.875rem;
  }
}

/* ==========================================================================
   Reset
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
  margin: 0;
}

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

button {
  font: inherit;
  color: inherit;
}

/* ==========================================================================
   Base
   ========================================================================== */

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.65;
  color: var(--color-ink-soft);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.15;
  color: var(--color-ink);
  letter-spacing: -0.01em;
}

h1 {
  font-size: var(--text-5xl);
}

h2 {
  font-size: var(--text-4xl);
}

h3 {
  font-size: var(--text-3xl);
}

h4 {
  font-size: var(--text-2xl);
  font-weight: 500;
}

p {
  max-width: 65ch;
}

a {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-color: var(--color-gold);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.2em;
  transition: color var(--transition-base);
}

a:hover,
a:focus-visible {
  color: var(--color-sky);
}

:focus-visible {
  outline: 2px solid var(--color-sky);
  outline-offset: 3px;
}

.container {
  width: 100%;
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding-inline: var(--side-padding);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  padding: var(--space-xs) var(--space-lg);
  border-radius: var(--radius-full);
  border: 2px solid transparent;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--transition-base), box-shadow var(--transition-base),
    background-color var(--transition-base), color var(--transition-base);
}

.btn--primary {
  background: var(--color-ink);
  color: var(--color-bg);
  box-shadow: var(--shadow-sm);
}

.btn--primary:hover,
.btn--primary:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md), var(--shadow-glow-gold);
  color: var(--color-bg);
}

.btn--secondary {
  background: transparent;
  border-color: var(--color-ink);
  color: var(--color-ink);
}

.btn--secondary:hover,
.btn--secondary:focus-visible {
  background: var(--color-ink);
  color: var(--color-bg);
}

/* ==========================================================================
   Hero (section 1)
   ========================================================================== */

.hero {
  position: relative;
  display: flex;
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  color: var(--color-white);
  background: var(--color-ink); /* shows briefly before the image paints */
}

@media (min-width: 768px) {
  .hero {
    aspect-ratio: 16 / 9;
    /* On wide, short windows (common on laptops — a wide display with
       the browser chrome eating vertical space), a pure 16:9 box can
       compute taller than the actual viewport, pushing the badge below
       the fold. Capping height means the whole hero always fits in one
       frame; object-position below compensates for the wider effective
       crop that results. */
    max-height: 100vh;
    max-height: 100svh;
  }
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Mobile (4:5) crop is much taller than its target frame; bias the
     visible window down so her eyes land in the upper third instead of
     the vertical center, and so the frame's very bottom edge is cropped
     away. */
  object-position: center 0%;
}

@media (min-width: 768px) {
  .hero__image {
    /* Right-biased: when the capped height (above) makes the box wider
       than a plain 16:9, cover reveals more width rather than cropping
       it — this keeps that extra width coming from the empty beach on
       the left rather than diluting how prominent she looks. Also
       scaled up slightly so she reads larger in the frame generally,
       not just on the wide/short windows this is compensating for. */
    object-position: 68% 15%;
    transform: scale(1.12);
  }
}

/* Strong enough directly behind the title/subtitle that the gradient
   text's darker gold stop still clears 3:1 against the photo — verified
   by sampling actual rendered pixels under the text and computing
   contrast, not just eyeballed. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    to bottom,
    rgba(51, 58, 77, 0.75) 0%,
    rgba(51, 58, 77, 0.65) 25%,
    rgba(51, 58, 77, 0.55) 45%,
    rgba(51, 58, 77, 0.2) 55%,
    rgba(51, 58, 77, 0.07) 80%,
    rgba(51, 58, 77, 0.32) 100%
  );
}

@media (min-width: 768px) {
  .hero__scrim {
    background: linear-gradient(
      100deg,
      rgba(51, 58, 77, 0.8) 0%,
      rgba(51, 58, 77, 0.65) 38%,
      rgba(51, 58, 77, 0.18) 60%,
      rgba(51, 58, 77, 0.02) 78%
    );
  }
}

.hero__badge {
  position: absolute;
  z-index: 3;
  left: var(--space-md);
  bottom: var(--space-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  padding: 0.6em 1.1em 0.65em;
  min-width: 6.25rem;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: radial-gradient(
    circle at 32% 28%,
    #fffdf3 0%,
    var(--color-gold-soft) 55%,
    var(--color-gold) 100%
  );
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.8),
    inset 0 -3px 6px rgba(51, 58, 77, 0.18), 0 0 0 3px var(--color-bg),
    0 0 0 4px var(--color-gold), var(--shadow-md);
  color: var(--color-ink);
  animation: hero-fade-up 0.9s var(--ease-reveal) 0.1s both;
}

.hero__badge-main {
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  padding-bottom: 0.2rem;
  border-bottom: 1px solid rgba(51, 58, 77, 0.25);
}

.hero__badge-sub {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0.85;
  white-space: nowrap;
}

/* Shine sweep — a light band travels across the medallion on a slow
   loop. transform-only so it stays cheap, and it's caught by the global
   reduced-motion rule like everything else. */
.hero__badge::after {
  content: "";
  position: absolute;
  top: -25%;
  left: -30%;
  width: 55%;
  height: 150%;
  background: linear-gradient(
    100deg,
    transparent,
    rgba(255, 255, 255, 0.95),
    transparent
  );
  transform: translateX(-280%) rotate(8deg);
  animation: hero-badge-shine 5s ease-in-out infinite;
  animation-delay: 1.4s;
  pointer-events: none;
}

@keyframes hero-badge-shine {
  0%,
  45% {
    transform: translateX(-280%) rotate(8deg);
  }
  65%,
  100% {
    transform: translateX(280%) rotate(8deg);
  }
}

@media (min-width: 768px) {
  .hero__badge {
    left: var(--space-lg);
    bottom: var(--space-lg);
    min-width: 7rem;
    padding: 0.7em 1.3em 0.75em;
  }

  .hero__badge-main {
    font-size: 1.2rem;
  }

  .hero__badge-sub {
    font-size: 0.8rem;
  }
}

.hero__content {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-sm);
  width: 100%;
  text-align: center;
  padding-top: var(--space-xl);
}

@media (min-width: 768px) {
  .hero__content {
    align-items: flex-start;
    /* Centered rather than a fixed padding-top — the hero's height now
       varies with the viewport (capped at one screen, see .hero above),
       so centering keeps the text sitting comfortably mid-frame, clear
       of the badge, regardless of exactly how tall that ends up being. */
    justify-content: center;
    max-width: 56%;
    text-align: left;
  }
}

.hero__title {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 600;
  font-size: var(--text-hero);
  line-height: 1.05;
  letter-spacing: 0.005em;
  margin: 0;
  background-image: linear-gradient(
    120deg,
    var(--color-gold) 0%,
    #fff8e8 35%,
    var(--color-gold) 60%,
    #fff2cf 100%
  );
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  text-shadow: 0 0 40px rgba(227, 198, 140, 0.5), 0 0 90px rgba(227, 198, 140, 0.25);
  animation: hero-fade-up 1s var(--ease-reveal) 0.35s both;
}

.hero__subtitle {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: var(--text-xl);
  color: var(--color-white);
  text-shadow: 0 2px 14px rgba(51, 58, 77, 0.5);
  max-width: 32ch;
  margin: 0;
  animation: hero-fade-up 1s var(--ease-reveal) 0.75s both;
}

.hero__scroll-cue {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: var(--space-lg);
  transform: translateX(-50%);
  width: 1.5rem;
  height: 2.4rem;
  border: 2px solid rgba(255, 255, 255, 0.7);
  border-radius: var(--radius-full);
  animation: hero-fade-up 1s var(--ease-reveal) 1.1s both;
}

.hero__scroll-cue::before {
  content: "";
  position: absolute;
  top: 0.4rem;
  left: 50%;
  width: 4px;
  height: 8px;
  background: var(--color-white);
  border-radius: var(--radius-full);
  transform: translateX(-50%);
  animation: hero-scroll-dot 1.8s ease-in-out infinite;
}

@keyframes hero-fade-up {
  from {
    opacity: 0;
    transform: translateY(1.5rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes hero-scroll-dot {
  0% {
    opacity: 1;
    transform: translate(-50%, 0);
  }
  60% {
    opacity: 0;
    transform: translate(-50%, 0.7rem);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, 0.7rem);
  }
}

/* ==========================================================================
   Story (section 2) — scroll-driven sequence
   ========================================================================== */

.story {
  position: relative;
  background: var(--color-bg-alt);
  padding-block: var(--space-3xl) 0;
  /* Deliberately no overflow value here — position: sticky below sticks
     to the viewport, and any non-visible overflow on this ancestor would
     break that. */
}

.story__lede {
  max-width: 40ch;
  margin-inline: auto;
  padding-bottom: var(--space-2xl);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: var(--text-3xl);
  text-align: center;
  color: var(--color-ink);
}

.story__sequence {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Each panel is a plain scroll-distance track — height only, no visual
   styling — so its sticky stage below has room to stay pinned while the
   user scrolls through it. This is what turns "stacked blocks scrolling
   past" into "one scene fading into the next in the same spot." */
.story__panel {
  position: relative;
  /* Taller than the sticky stage below on purpose — that extra scroll
     distance is what lets the stage actually hold in place (pinned)
     before the next panel's stage covers it, instead of the pin having
     zero duration. Kept fairly tight so the whole sequence moves at a
     brisk pace rather than feeling like a long scroll. */
  height: 130vh;
  height: 130svh;
  /* Named view-timeline sourced from the panel itself (not the sticky
     stage or image) — the panel is what actually travels through the
     viewport in the normal way. Descendants can then reference this
     timeline by name for scroll-driven animation even while visually
     pinned. */
  view-timeline-name: --story-panel-scroll;
  view-timeline-axis: block;
}

.story__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
  padding-block: var(--space-2xl);
}

/* Soft, slow-drifting haze — the "dream" atmosphere. Purely decorative,
   sits behind the content, animates only transform/opacity so it stays
   cheap even though several panels are stacked in the DOM. */
.story__stage::before,
.story__stage::after {
  content: "";
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  filter: blur(48px);
  opacity: 0.55;
  pointer-events: none;
}

.story__stage::before {
  width: 16rem;
  height: 16rem;
  top: -4rem;
  left: -4rem;
  background: radial-gradient(circle, var(--color-gold-soft), transparent 70%);
  animation: story-haze-drift-a 16s ease-in-out infinite;
}

.story__stage::after {
  width: 20rem;
  height: 20rem;
  bottom: -6rem;
  right: -5rem;
  background: radial-gradient(circle, var(--color-sky-soft), transparent 70%);
  animation: story-haze-drift-b 20s ease-in-out infinite;
}

@keyframes story-haze-drift-a {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
    opacity: 0.5;
  }
  50% {
    transform: translate(2rem, 1.5rem) scale(1.12);
    opacity: 0.7;
  }
}

@keyframes story-haze-drift-b {
  0%,
  100% {
    transform: translate(0, 0) scale(1);
    opacity: 0.45;
  }
  50% {
    transform: translate(-2rem, -1.5rem) scale(1.08);
    opacity: 0.65;
  }
}

.story__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  align-items: center;
}

@media (min-width: 768px) {
  .story__inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2xl);
  }

  /* Alternate image/text sides for visual rhythm as the sequence unfolds */
  .story__panel:nth-child(even) .story__figure {
    order: 2;
  }

  .story__panel:nth-child(even) .story__text {
    order: 1;
  }
}

.story__figure {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  background: var(--color-bg);
}

/* Hidden-until-revealed state only applies once JS confirms
   IntersectionObserver is available (see js-story class in script.js) —
   without it, panels render fully visible instead of stuck at opacity: 0.
   transform + opacity only (no animated filter/blur) so this stays
   compositor-only even with several panels stacked in the DOM. */
.js-story .story__figure {
  opacity: 0;
  transform: translateY(2.5rem) scale(0.96);
  transition: opacity 1.3s var(--ease-reveal), transform 1.3s var(--ease-reveal);
  transition-delay: 0.12s;
}

.story__image {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.story__text {
  margin: 0;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-2xl);
  line-height: 1.4;
  color: var(--color-ink);
}

.js-story .story__text {
  opacity: 0;
  transform: translateY(1.75rem);
  transition: opacity 1.1s var(--ease-reveal), transform 1.1s var(--ease-reveal);
}

.story__panel.is-visible .story__figure,
.story__panel.is-visible .story__text {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* Parallax: the image drifts against the pinned frame as its panel
   scrolls by — a light touch on mobile, more pronounced on desktop.
   Pure CSS scroll-driven animation (animation-timeline: view()) — no
   scroll listener — and only active where supported and motion is
   welcome. scale() keeps the drift from ever revealing an edge. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .story__image {
      animation: story-parallax linear both;
      animation-timeline: --story-panel-scroll;
      animation-range: cover 0% cover 100%;
    }

    @keyframes story-parallax {
      from {
        transform: translateY(-1.5rem) scale(1.08);
      }
      to {
        transform: translateY(1.5rem) scale(1.08);
      }
    }

    @media (min-width: 768px) {
      @keyframes story-parallax {
        from {
          transform: translateY(-5rem) scale(1.16);
        }
        to {
          transform: translateY(5rem) scale(1.16);
        }
      }
    }
  }
}

/* ==========================================================================
   Flint (section 3)
   ========================================================================== */

.flint {
  background: var(--color-bg);
  padding-block: var(--space-3xl);
}

.js-flint {
  opacity: 0;
  transform: translateY(2rem);
  transition: opacity 1.1s var(--ease-reveal), transform 1.1s var(--ease-reveal);
}

.js-flint.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.flint__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2xl);
  align-items: center;
}

@media (min-width: 768px) {
  .flint__inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3xl);
  }
}

.flint__text p {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: 1.65;
  color: var(--color-ink);
  max-width: 42ch;
  margin-inline: auto;
}

@media (min-width: 768px) {
  .flint__text p {
    margin-inline: 0;
  }
}

/* Staggered, overlapping trio rather than a plain grid — a profile shot
   peeking in behind, the full figure as the anchor, and a romantic-lead
   close-up cascading in front. */
.flint__gallery {
  position: relative;
  max-width: 26rem;
  margin-inline: auto;
  padding: 10% 4% 18% 0;
}

@media (min-width: 768px) {
  .flint__gallery {
    margin-inline: 0;
  }
}

.flint__frame {
  margin: 0;
  background: var(--color-bg);
  padding: var(--space-2xs);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

.flint__frame img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: calc(var(--radius-md) - 4px);
}

.flint__photo--primary {
  position: relative;
  z-index: 2;
  width: 68%;
  transform: rotate(-2.5deg);
}

.flint__photo--primary img {
  object-position: center 25%;
}

.flint__photo--back {
  position: absolute;
  z-index: 1;
  top: 0;
  right: 0;
  width: 42%;
  transform: rotate(6deg);
}

.flint__photo--back img {
  /* Source is a wide landscape profile shot with his head toward the
     left third — a centered crop was slicing through his face/mane. */
  object-position: 25% 20%;
}

.flint__photo--front {
  position: absolute;
  z-index: 3;
  right: 2%;
  bottom: 0;
  width: 47%;
  transform: rotate(3deg);
}

.flint__photo--front img {
  object-position: center 30%;
}

/* ==========================================================================
   Upbringing (section 4) — "heavenly" CSS/SVG background, no images
   ========================================================================== */

.upbringing {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 140vh;
  min-height: 140svh;
  padding-block: var(--space-3xl);
  background: linear-gradient(
    180deg,
    var(--color-bg) 0%,
    var(--color-gold-soft) 45%,
    var(--color-sky-soft) 100%
  );
}

/* Purely decorative — gradients and soft-edged blobs rather than sharp
   shapes with animated blur, so the only thing ever animating is
   transform/opacity. Cheap to composite, however tall the section is. */
.upbringing__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.upbringing__glow {
  position: absolute;
  top: -12%;
  left: 50%;
  width: 56rem;
  height: 56rem;
  margin-left: -28rem;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(255, 253, 244, 0.95) 0%,
    rgba(255, 253, 244, 0) 68%
  );
  animation: upbringing-glow-pulse 15s ease-in-out infinite;
}

.upbringing__cloud {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.75) 0%,
    rgba(255, 255, 255, 0) 72%
  );
}

.upbringing__cloud--1 {
  top: 14%;
  left: -12%;
  width: 28rem;
  height: 15rem;
  animation: upbringing-drift-a 52s ease-in-out infinite;
}

.upbringing__cloud--2 {
  top: 48%;
  right: -10%;
  width: 22rem;
  height: 12rem;
  background: radial-gradient(
    circle,
    rgba(223, 235, 241, 0.75) 0%,
    rgba(223, 235, 241, 0) 72%
  );
  animation: upbringing-drift-b 64s ease-in-out infinite;
}

.upbringing__cloud--3 {
  top: 78%;
  left: 2%;
  width: 20rem;
  height: 11rem;
  animation: upbringing-drift-a 46s ease-in-out infinite reverse;
}

/* A faint diagonal light sweep — much slower and dimmer than the hero
   badge's shine, meant to read as ambient rather than a designed glint. */
.upbringing__shimmer {
  position: absolute;
  inset: -20% -60%;
  background: linear-gradient(
    100deg,
    transparent 42%,
    rgba(255, 255, 255, 0.3) 50%,
    transparent 58%
  );
  animation: upbringing-shimmer 18s ease-in-out infinite;
}

@keyframes upbringing-glow-pulse {
  0%,
  100% {
    opacity: 0.7;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.06);
  }
}

@keyframes upbringing-drift-a {
  0%,
  100% {
    transform: translateX(0) translateY(0);
  }
  50% {
    transform: translateX(3.5rem) translateY(-1rem);
  }
}

@keyframes upbringing-drift-b {
  0%,
  100% {
    transform: translateX(0) translateY(0);
  }
  50% {
    transform: translateX(-4rem) translateY(1rem);
  }
}

@keyframes upbringing-shimmer {
  0%,
  55% {
    transform: translateX(-35%);
  }
  100% {
    transform: translateX(35%);
  }
}

.upbringing__content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
}

.upbringing__main {
  max-width: 46ch;
  margin-inline: auto;
  padding-top: var(--space-xl);
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: 1.65;
  text-align: center;
  color: var(--color-ink);
}

.upbringing__aside {
  max-width: 34ch;
  margin: var(--space-2xl) auto var(--space-3xl);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: var(--text-2xl);
  line-height: 1.5;
  text-align: center;
  color: var(--color-ink);
}

@media (min-width: 768px) {
  .upbringing__aside {
    font-size: var(--text-3xl);
  }
}

/* Reveal-once utility: fade + drift up the first time an element scrolls
   into view, then stay. Shared by both beats in this section.
   Hidden-until-revealed only applies once JS confirms IntersectionObserver
   is available (script.js adds .js-reveal) — without it, elements render
   fully visible instead of stuck at opacity: 0. */
.reveal-up.js-reveal {
  opacity: 0;
  transform: translateY(2rem);
  transition: opacity 1.1s var(--ease-reveal), transform 1.1s var(--ease-reveal);
}

.reveal-up.js-reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ==========================================================================
   Puppies (section 5) — placeholder cards
   ========================================================================== */

/* Background pinned in place while the card grid scrolls up through it:
   .puppies is a single-column grid, and .puppies__bg + .puppies__content
   both occupy that same cell (grid-row/column: 1) so they overlap. The
   grid's own height comes from .puppies__content (tall — a full card
   grid); .puppies__bg is sticky within that tall row, so it holds at
   the top of the viewport for as long as the section is being scrolled
   through, then releases normally once the section ends. This is the
   same sticky-in-a-taller-parent technique Section 2 uses, just with
   one shared background instead of one sticky stage per panel.

   Deliberately no overflow value on .puppies itself — any non-visible
   overflow on an ancestor of a position: sticky element breaks the
   stickiness. */
.puppies {
  display: grid;
}

.puppies__bg {
  grid-row: 1;
  grid-column: 1;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    var(--color-ink) 0%,
    var(--color-ink-soft) 100%
  );
}

.puppies__content {
  grid-row: 1;
  grid-column: 1;
  position: relative;
  z-index: 1;
  padding-block: var(--space-3xl);
}

/* A proper starry-night field — enough stars, spread and sized
   unevenly, that it reads as a sky rather than a sprinkle. Each on its
   own timing so they twinkle independently; transform/opacity only. */
.puppies__star {
  position: absolute;
  width: 0.2rem;
  height: 0.2rem;
  border-radius: 50%;
  background: var(--color-white);
  box-shadow: 0 0 6px 1px rgba(255, 255, 255, 0.75);
  animation: puppies-twinkle 3.2s ease-in-out infinite;
}

.puppies__star--lg {
  width: 0.35rem;
  height: 0.35rem;
  background: var(--color-gold-soft);
  box-shadow: 0 0 10px 2px rgba(243, 230, 200, 0.8);
}

.puppies__star:nth-child(1) { top: 6%; left: 8%; animation-duration: 3.6s; }
.puppies__star:nth-child(2) { top: 14%; left: 80%; animation-delay: 0.6s; animation-duration: 4.2s; }
.puppies__star:nth-child(3) { top: 4%; left: 42%; animation-delay: 1.1s; animation-duration: 2.8s; }
.puppies__star:nth-child(4) { top: 22%; left: 22%; animation-delay: 1.6s; animation-duration: 3.8s; }
.puppies__star:nth-child(5) { top: 18%; left: 62%; animation-delay: 0.3s; animation-duration: 3.1s; }
.puppies__star:nth-child(6) { top: 30%; left: 92%; animation-delay: 2s; animation-duration: 4.5s; }
.puppies__star:nth-child(7) { top: 2%; left: 68%; animation-delay: 1.4s; animation-duration: 3.3s; }
.puppies__star:nth-child(8) { top: 27%; left: 4%; animation-delay: 0.9s; animation-duration: 3.9s; }
.puppies__star:nth-child(9) { top: 11%; left: 33%; animation-delay: 2.4s; animation-duration: 3s; }
.puppies__star:nth-child(10) { top: 34%; left: 52%; animation-delay: 1.8s; animation-duration: 4s; }
.puppies__star:nth-child(11) { top: 42%; left: 15%; animation-delay: 0.4s; animation-duration: 3.4s; }
.puppies__star:nth-child(12) { top: 48%; left: 74%; animation-delay: 1.2s; animation-duration: 4.1s; }
.puppies__star:nth-child(13) { top: 56%; left: 36%; animation-delay: 2.2s; animation-duration: 2.9s; }
.puppies__star:nth-child(14) { top: 62%; left: 88%; animation-delay: 0.7s; animation-duration: 3.7s; }
.puppies__star:nth-child(15) { top: 39%; left: 58%; animation-delay: 1.9s; animation-duration: 3.2s; }
.puppies__star:nth-child(16) { top: 68%; left: 10%; animation-delay: 0.2s; animation-duration: 4.3s; }
.puppies__star:nth-child(17) { top: 71%; left: 47%; animation-delay: 1.5s; animation-duration: 3.5s; }
.puppies__star:nth-child(18) { top: 8%; left: 96%; animation-delay: 2.6s; animation-duration: 3s; }
.puppies__star:nth-child(19) { top: 78%; left: 66%; animation-delay: 0.5s; animation-duration: 4s; }
.puppies__star:nth-child(20) { top: 83%; left: 28%; animation-delay: 1.3s; animation-duration: 3.6s; }
.puppies__star:nth-child(21) { top: 52%; left: 4%; animation-delay: 2.1s; animation-duration: 3.3s; }
.puppies__star:nth-child(22) { top: 16%; left: 12%; animation-delay: 0.8s; animation-duration: 2.7s; }
.puppies__star:nth-child(23) { top: 89%; left: 82%; animation-delay: 1.7s; animation-duration: 4.4s; }
.puppies__star:nth-child(24) { top: 60%; left: 60%; animation-delay: 0.1s; animation-duration: 3.1s; }
.puppies__star:nth-child(25) { top: 92%; left: 40%; animation-delay: 2.3s; animation-duration: 3.8s; }
.puppies__star:nth-child(26) { top: 45%; left: 96%; animation-delay: 1s; animation-duration: 3.4s; }
.puppies__star:nth-child(27) { top: 25%; left: 55%; animation-delay: 1.85s; animation-duration: 2.9s; }
.puppies__star:nth-child(28) { top: 75%; left: 92%; animation-delay: 0.35s; animation-duration: 4.2s; }

@keyframes puppies-twinkle {
  0%,
  100% {
    opacity: 0.25;
    transform: scale(0.85);
  }
  50% {
    opacity: 1;
    transform: scale(1.15);
  }
}

.puppies__heading {
  text-align: center;
  margin-bottom: var(--space-2xl);
  color: var(--color-bg);
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.3);
}

.puppies__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
}

@media (min-width: 480px) {
  .puppies__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .puppies__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 1280px) {
  .puppies__grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Gentle stagger — each card's own reveal transition starts a beat
   later than the one before it. */
.puppies__grid > :nth-child(1) {
  transition-delay: 0s;
}
.puppies__grid > :nth-child(2) {
  transition-delay: 0.08s;
}
.puppies__grid > :nth-child(3) {
  transition-delay: 0.16s;
}
.puppies__grid > :nth-child(4) {
  transition-delay: 0.24s;
}
.puppies__grid > :nth-child(5) {
  transition-delay: 0.32s;
}
.puppies__grid > :nth-child(6) {
  transition-delay: 0.4s;
}
.puppies__grid > :nth-child(7) {
  transition-delay: 0.48s;
}

/* The hover lift lives on this inner wrapper rather than .puppy-card
   itself — .puppy-card also carries .reveal-up, which sets its own
   (much slower) transition on transform for the scroll reveal. Keeping
   them on different elements means the two never fight over the same
   transition-duration. */
.puppy-card__inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  transition: transform 0.3s ease;
}

@media (hover: hover) and (pointer: fine) {
  .puppy-card:hover .puppy-card__inner {
    transform: translateY(-6px);
  }

  .puppy-card:hover .puppy-card__photo {
    box-shadow: 0 0 0 4px var(--color-bg), 0 0 0 5px var(--color-gold),
      0 16px 32px rgba(227, 198, 140, 0.4), var(--shadow-md);
  }
}

/* Arched, halo-suggesting frame — an elliptical top radius (the "/"
   splits horizontal/vertical radii) rather than a literal ring, so it
   reads as a gentle window/dome shape instead of a cliché halo icon. */
.puppy-card__photo {
  aspect-ratio: 4 / 5;
  border: 2px solid var(--color-gold);
  border-radius: 50% 50% var(--radius-md) var(--radius-md) / 30% 30%
    var(--radius-md) var(--radius-md);
  box-shadow: 0 0 0 4px var(--color-bg), 0 0 0 5px var(--color-gold-soft),
    0 10px 24px rgba(227, 198, 140, 0.3), var(--shadow-sm);
  overflow: hidden;
  transition: box-shadow 0.3s ease;
}

.puppy-card__photo-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.puppy-card__placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  background: radial-gradient(
    circle at 50% 38%,
    var(--color-gold-soft) 0%,
    var(--color-bg-alt) 75%
  );
}

.puppy-card__placeholder-icon {
  font-size: var(--text-xl);
  color: var(--color-gold);
}

.puppy-card__placeholder-text {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.puppy-card__name {
  margin-top: var(--space-md);
  text-align: center;
  font-size: var(--text-xl);
  /* Sits directly on the section's night-sky background, not inside
     the card's own light frame, so it needs the light-on-dark pairing
     the rest of that background uses. */
  color: var(--color-bg);
}

.puppy-card__details {
  margin: var(--space-sm) 0 0;
  padding-top: var(--space-sm);
  border-top: 1px solid rgba(227, 198, 140, 0.4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.puppy-card__detail {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  font-size: var(--text-sm);
}

.puppy-card__detail dt {
  /* Solid, not translucent — against the lighter (ink-soft) end of the
     section's gradient, rgba(...,0.65) measured under 4.5:1 contrast.
     Differentiated from dd by weight, not by dimming the color. */
  color: var(--color-bg);
}

.puppy-card__detail dd {
  margin: 0;
  font-weight: 700;
  /* Brighter than --color-gold-soft, which measured under 4.5:1 against
     the lighter end of the section's gradient. */
  color: #fff3d9;
  letter-spacing: 0.04em;
}

/* ==========================================================================
   Family (section 6)
   ========================================================================== */

.family {
  background: var(--color-bg-alt);
  padding-block: var(--space-3xl);
}

.family__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
  align-items: center;
}

@media (min-width: 768px) {
  .family__inner {
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--space-2xl);
  }
}

.family__text p {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: 1.65;
  color: var(--color-ink);
  max-width: 44ch;
  margin-inline: auto;
  text-align: center;
}

@media (min-width: 768px) {
  .family__text p {
    margin-inline: 0;
    text-align: left;
  }
}

.family__figure img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* ==========================================================================
   Contact (section 7) — the conversion point
   ========================================================================== */

.contact {
  background: var(--color-bg);
  padding-block: var(--space-3xl);
  text-align: center;
}

.contact__inner {
  max-width: 40rem;
}

.contact__lead {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-2xl);
  color: var(--color-ink);
  margin: 0 auto var(--space-xl);
  max-width: 30ch;
}

.contact__cta {
  margin-bottom: var(--space-2xl);
}

.contact__cta-label {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-ink-soft);
  margin: 0 0 var(--space-sm);
}

.contact__phone-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-md) var(--space-2xl);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 600;
  font-size: var(--text-3xl);
  color: var(--color-ink);
  background: linear-gradient(135deg, var(--color-gold-soft), var(--color-gold));
  border-radius: var(--radius-full);
  text-decoration: none;
  box-shadow: var(--shadow-md);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
  animation: contact-glow-pulse 3.5s ease-in-out infinite;
}

.contact__phone-btn:hover,
.contact__phone-btn:focus-visible {
  color: var(--color-ink);
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg), 0 0 32px rgba(227, 198, 140, 0.55);
}

@keyframes contact-glow-pulse {
  0%,
  100% {
    box-shadow: var(--shadow-md), 0 0 0 0 rgba(227, 198, 140, 0.3);
  }
  50% {
    box-shadow: var(--shadow-md), 0 0 24px 4px rgba(227, 198, 140, 0.4);
  }
}

.contact__cta-caption {
  margin: var(--space-md) auto 0;
  max-width: 40ch;
  color: var(--color-ink-soft);
}

.contact__note {
  max-width: 48ch;
  margin: 0 auto var(--space-xl);
  color: var(--color-ink-soft);
}

.contact__signoff {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-2xl);
  color: var(--color-ink);
}

.contact__social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  margin-top: var(--space-lg);
  border-radius: 50%;
  border: 2px solid var(--color-gold);
  background: var(--color-bg-alt);
  color: var(--color-ink);
  text-decoration: none;
  transition: transform var(--transition-base), box-shadow var(--transition-base),
    background-color var(--transition-base);
}

.contact__social:hover,
.contact__social:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md), var(--shadow-glow-gold);
  background: var(--color-gold-soft);
  color: var(--color-ink);
}

.contact__social svg {
  width: 1.4rem;
  height: 1.4rem;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
  padding: var(--space-lg) var(--side-padding);
  background: var(--color-bg-alt);
  text-align: center;
}

.site-footer p {
  /* The global `p { max-width: 65ch }` reset constrains this paragraph's
     own box width — without margin-inline: auto to center that box,
     text-align: center on .site-footer only centers text *within* an
     already left-positioned box, which does nothing for a single short
     line. */
  margin-inline: auto;
  margin-block: 0;
  font-size: var(--text-sm);
  color: var(--color-ink-soft);
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */

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

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}
