/* ==========================================================================
   Cascade transition — pinned wipe between the clients section and the
   portfolio grid.

   Ported from animation_options/sample_v2 (assets/css/cascade.css) for
   index.html. Kept as its own file — rather than folded into the shared
   assets/css/style.css — because style.css is used by every page in this
   folder (careers.html, news.html, ...) and this transition only applies
   to the homepage.

   Loaded after assets/css/style.css, so the two overrides at the bottom
   (.clients / .portfolio) layer on top of that file's rules instead of
   duplicating them.

   The overlay holds one masked layer filling the screen: the burgundy /
   light-blue tile, masked to a travelling band. Each band has a leading and
   a trailing edge, both sweeping right to left, so along any band the
   screen reads, left to right:

     [0 .. lead)       transparent  -> not yet reached; the page shows through
     [lead .. trail)   pattern      -> the wipe itself
     [trail .. width]  transparent  -> already passed; the page shows again

   Nothing is left behind. The transition from navy to cream is done by the
   page itself scrolling — clients leaving at the top, portfolio arriving
   from the bottom — and the band simply travels across that boundary while
   it happens, so it reads as the pattern revealing the section below.

   Bands fire bottom-first, so the front climbs the screen at roughly the
   rate the boundary does. The two lead variables buy empty colour either
   side, so the band passes over plain navy and plain cream rather than
   over names and cards.
   ========================================================================== */

:root {
  /* History: 40vh each at first, cut to 24vh / 17vh to claw back
     vertical space, which read as crowded, so now 36vh / 30vh. The wipe's
     scroll window is measured from .clients' bottom edge in viewport
     units (cascade.js), so these change the empty ground either side, not
     how long the wipe takes. */

  /* Empty ground added below the client list, so the wipe starts over
     plain section rather than mid-name. Added to .clients' height below. */
  --cascade-lead-in: 36vh;

  /* Empty cream above the portfolio grid, so the band passes over plain
     colour rather than over the first row of cards. */
  --cascade-lead-out: 30vh;
}

.cascade {
  position: fixed;
  inset: 0;
  z-index: 3;            /* over the page, under the navbar/mobile menu (90, 100) */
  pointer-events: none;  /* never intercept clicks, even mid-wipe */
  visibility: hidden;    /* cascade.js shows it only inside the scroll window */
}

.cascade__stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.cascade__svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* No viewBox on the SVG, so one user unit is one CSS pixel. The pattern
   itself is drawn to the stage by cascade.js (drawPattern), one pair per
   band, so it has no fixed tile size. */

/* The tile's two tones: cream and pink, from the Figma pattern (node
   2275:11242). Swap these two to recolour the whole wipe. */
.cascade__tile-a { fill: var(--bb-cream); }
.cascade__tile-b { fill: var(--bb-pink); }

/* White is opaque in an SVG mask: these rects are the visible window. */
.cascade__svg mask rect {
  fill: var(--bb-white);
}

/* --------------------------------------------------------------------------
   Space either side of the transition — layered on top of style.css's own
   .clients/.portfolio sizing (510/380/170px and 120px top padding there,
   dropped to 80px below).
   -------------------------------------------------------------------------- */

.clients {
  height: calc(510px + var(--cascade-lead-in, 0px));
}

.clients__inner {
  bottom: var(--cascade-lead-in, 0px);
}

.portfolio {
  padding-top: calc(80px + var(--cascade-lead-out, 0px));
}

@media (max-width: 1200px) {
  .clients { height: calc(380px + var(--cascade-lead-in, 0px)); }
  .clients__inner { bottom: var(--cascade-lead-in, 0px); }
}

@media (max-width: 640px) {
  :root {
    --cascade-lead-in: 44vh;  /* was 36vh */
    --cascade-lead-out: 24vh; /* was 16vh */
  }
  .clients { height: calc(170px + var(--cascade-lead-in, 0px)); }
  .clients__inner { bottom: calc(-20vh + var(--cascade-lead-in, 0px)); }
}

/* --------------------------------------------------------------------------
   Client list — v2 tuning, ported from sample_v2's style.css.

   The list's reverse-parallax (assets/javascript/main.js) races the names
   past faster than the page scrolls, so it freezes with the last name near
   the top of the viewport well before the section itself finishes
   scrolling by. With the old 320px bottom padding that freeze happened
   early, clearing the names by ~34% of the cascade transition below. At 0
   padding the list travels further before freezing, so the names stay
   readable through ~60% of the transition instead of fading right as it
   starts. The travel itself is unchanged by the mask below — the mask
   only decides how much of it is visible at once.
   -------------------------------------------------------------------------- */

/* The names are bounded by a mask rather than by clipping, so the band's
   top and bottom edges fade into the ground instead of cutting the type on
   a hard line — the treatment mobile already had on its top edge alone,
   now at every breakpoint and on both edges.

   `overflow` stays visible on purpose: the mask (sized to exactly this
   box, no-repeat) is what bounds the names now, and leaving the box
   unclipped keeps `.clients`' own overflow out of it. The box is sized to
   about five names, so that is what is legible at any moment; the reverse-
   parallax in main.js reads viewport.clientHeight, so a shorter band also
   means a longer travel, i.e. the list races past faster. */
.clients__viewport {
  overflow: visible;
  --clients-fade-edge: 60px;
  -webkit-mask-image: linear-gradient(to bottom,
    transparent 0,
    var(--bb-black) var(--clients-fade-edge),
    var(--bb-black) calc(100% - var(--clients-fade-edge)),
    transparent 100%);
  mask-image: linear-gradient(to bottom,
    transparent 0,
    var(--bb-black) var(--clients-fade-edge),
    var(--bb-black) calc(100% - var(--clients-fade-edge)),
    transparent 100%);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

@media (max-width: 1200px) {
  .clients__viewport { --clients-fade-edge: 48px; }
}

@media (max-width: 640px) {
  .clients__viewport { --clients-fade-edge: 34px; }
}

.clients__list {
  padding-bottom: 0;
}

@media (max-width: 640px) {
  /* Mobile: bottom padding matches the top (style.css), rather than the 0
     used above for the desktop/tablet reverse-parallax tuning. */
  .clients__list {
    padding-bottom: 10vh;
  }
}

/* --------------------------------------------------------------------------
   Reduced motion — no wipe at all, a background cross-fade instead.

   The transition's job is to carry the eye from the clients section's dark
   ground to the portfolio's Off-White one. The wipe does that with travelling
   pattern bands, which is exactly the kind of independent movement
   prefers-reduced-motion asks us to drop — so here the overlay is removed
   from the document outright (not merely hidden, as cascade.js does for its
   own bookkeeping) and .clients' ground simply fades to Off-White as the seam
   between the two sections crosses the screen.

   Only the ground fades. Text colours — .clients__label and .clients__name,
   both var(--clients-fg) — are left exactly as they are, so the layer sits
   BEHIND .clients__inner rather than washing over the names.

   The opacity is driven by --clients-fade, which cascade.js scrubs 0 -> 1
   against scroll position. Unset, it defaults to 0, so a browser that never
   runs the JS just gets the plain hard section edge.

   The lead-in/lead-out space above is deliberately kept: it is what puts
   plain, empty ground either side of the seam, which the fade wants just as
   much as the wipe did.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .cascade {
    display: none;
  }

  .clients::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background: var(--bb-off-white);
    opacity: var(--clients-fade, 0);
    pointer-events: none;
  }

  /* .clients__inner is positioned but has no z-index of its own, so without
     this the ::before layer — generated last — would paint over the names. */
  .clients__inner {
    z-index: 1;
  }
}
