/* ──────────────────────────────────────────────────────────────────────────
   BlueHous campaign pages — motion layer.

   The kit already animates the pieces an author opts in by hand: `.reveal`
   grids, the hero's staggered entrance, the stat count-up, the photo-band
   drift. What it never covered is everything around them — section headings,
   trust strips, notes, sources, tables — so a section would arrive with its
   cards rising and its heading already sitting there, which reads as a bug
   rather than a choice.

   This file closes that gap without touching a single HTML file: it selects
   the wrappers the kit already gives every page, and it deliberately does NOT
   select anything `.reveal` already drives, so nothing animates twice.

   Everything here is scroll-driven (`animation-timeline: view()`), which means
   no JavaScript, no observers, and no work at all on the main thread. Browsers
   without scroll-driven animations — Firefox stable, at the time of writing —
   fall through to the finished state, exactly the way `.reveal` already does.

   The vocabulary is one movement (up, 18px) and one duration family, borrowed
   from the kit's own `rise`. Restraint is the point: a landing page that moves
   in four different ways reads as a template.
   ────────────────────────────────────────────────────────────────────────── */

/* Finished state is the default, so a browser that cannot animate on scroll,
   and a visitor who asked for less motion, both see a complete page. */
.sec .head,
.sec > .wrap > h2,
.sec .note,
.sec .src,
.strip,
.band > .wrap,
.quote-band-in {
  opacity: 1;
  transform: none;
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Section furniture. The heading leads, then the aside under it, so a
       section resolves top to bottom in the reading order rather than all at
       once. */
    .sec .head,
    .sec > .wrap > h2,
    .strip,
    .band > .wrap,
    .quote-band-in {
      animation: lift 640ms var(--ease-out) both;
      animation-timeline: view();
      animation-range: entry 2% cover 22%;
    }

    /* Closing notes and source lines land last, once the content they qualify
       has already arrived. */
    .sec .note,
    .sec .src {
      animation: lift 640ms var(--ease-out) both;
      animation-timeline: view();
      animation-range: entry 6% cover 34%;
    }

    /* The kit staggers a `.reveal` grid's first four children and stops. A
       five- or six-item grid then had its tail arrive in one lump, which is
       the one place the existing stagger is visible as incomplete. */
    .reveal > *:nth-child(5) {
      animation: rise 700ms var(--ease-out) both;
      animation-timeline: view();
      animation-range: entry 4% cover 50%;
    }
    .reveal > *:nth-child(6) {
      animation: rise 700ms var(--ease-out) both;
      animation-timeline: view();
      animation-range: entry 4% cover 56%;
    }
  }
}

@keyframes lift {
  from {
    opacity: 0;
    /* translateY only. translateX runs the wrong way under dir="rtl". */
    transform: translate3d(0, 18px, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── The page chrome's own entrance ─────────────────────────────────────────
   Three pieces arrive with the page rather than on scroll, so they use the
   kit's `enter` keyframes and its delay ladder rather than a timeline.

   Finished state first, for reduced motion and for anything that cannot run
   these — the bar and the rail must never be missing, only late. */
.nav,
.hero .badge {
  opacity: 1;
  transform: none;
}

/* The rail is centred with its own translateY(-50%), so it only ever gets its
   opacity reset — never `transform: none`, which would drop it half a rail
   height down the screen. Its keyframes below animate opacity alone for the
   same reason. */
.dots {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  /* The fixed bar. Down from -10px rather than up: it belongs to the top edge,
     so it should read as settling onto it. */
  .nav {
    animation: drop var(--t-enter) var(--ease-out) both;
  }

  /* The launch badge moved out of the header and into the hero copy, which
     left it as the one thing in that column already sitting there while the
     eyebrow, headline and lead rose past it. It leads the ladder now, because
     it sits above the eyebrow. */
  .hero .badge {
    animation: enter var(--t-enter) var(--ease-out) both;
    animation-delay: 20ms;
  }

  /* The rail is a wayfinding aid, not content: it waits until the hero has
     finished arriving, then fades in without moving. */
  .dots {
    animation: fade 520ms var(--ease-out) both;
    animation-delay: 620ms;
  }
}

@keyframes drop {
  from {
    opacity: 0;
    transform: translate3d(0, -10px, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ── Hover, everywhere it was missing ───────────────────────────────────────
   The kit gives `.card` a hover already. These are the surfaces that had a
   pointer state in the design but no transition to get there. */

.stat {
  transition: transform var(--t-hover) var(--ease);
}

@media (any-hover: hover) {
  /* A whole millimetre. Enough to feel like the row responded, far too little
     to look like a card lifting off the page. */
  .stat:hover {
    transform: translateY(-2px);
  }
}

.steps li h3,
.steps li h4 {
  transition: color var(--t-hover) var(--ease);
}

@media (any-hover: hover) {
  .steps li:hover h3,
  .steps li:hover h4 {
    color: var(--blue);
  }
  .sec-navy .steps li:hover h3,
  .sec-navy .steps li:hover h4 {
    color: var(--cyan);
  }
}

/* Table rows are read across, so the cue runs across the row rather than on
   the cell the pointer happens to be over. */
.tbl tbody tr {
  transition: background var(--t-hover) var(--ease);
}

@media (any-hover: hover) {
  .tbl tbody tr:hover {
    background: color-mix(in srgb, var(--blue) 4%, transparent);
  }
}

/* Pills and footer links move under the pointer instead of only changing
   colour, which is what makes a row of them feel like controls. */
.pill,
.foot-links a {
  transition: transform var(--t-hover) var(--ease), color var(--t-hover) var(--ease),
    border-color var(--t-hover) var(--ease), background var(--t-hover) var(--ease);
}

@media (any-hover: hover) {
  .pill:hover {
    transform: translateY(-2px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .stat,
  .pill,
  .foot-links a,
  .tbl tbody tr,
  .steps li h3,
  .steps li h4 {
    transition: none;
  }
  .stat:hover,
  .pill:hover {
    transform: none;
  }
}
