/* Pamelys motion layer.

   Nothing here hides content unless motion.js has confirmed it is running: the
   .js prefix comes from that script, and index.html gates its own .reveal rule
   the same way, so a blocked or failing script leaves the page fully visible.

   Every class added by this layer carries a mo- prefix. The bare names collide
   with the site's own utilities (.up is already the up-arrow modifier on
   .arr, which silently disappeared the first time round). */

:root { --mo: cubic-bezier(.22, 1, .36, 1); }

.js .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .7s var(--mo), transform .7s var(--mo);
  transition-delay: var(--d, 0s);
}
.js .reveal.show { opacity: 1; transform: none; }

/* headings, split into words by motion.js */
.js .mo-split .mo-wd {
  display: inline-block;
  opacity: 0;
  transform: translateY(.3em);
  transition: opacity .55s var(--mo), transform .55s var(--mo);
  transition-delay: calc(var(--i, 0) * .045s);
}
.js .mo-split.mo-in .mo-wd { opacity: 1; transform: none; }

/* hero and page intro, sequenced on load */
.js .mo-up {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .6s var(--mo), transform .6s var(--mo);
  transition-delay: var(--d, 0s);
}
.js .mo-up.mo-in { opacity: 1; transform: none; }

/* rows inside .rows, sequenced as each enters */
.js .mo-rw {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .6s var(--mo), transform .6s var(--mo);
  transition-delay: var(--d, 0s);
}
.js .mo-rw.show { opacity: 1; transform: none; }

/* ---------------------------------------------------------------------------
   The service-to-product threshold.

   The old sliding panel is gone: a panel has an edge, and an edge cannot read
   as a dissolve no matter what colour it is. The warm world is a full-bleed
   layer that cross-fades instead, so there is no boundary anywhere on screen.

   The threshold is the whole passage, not the two centred phrases: the cream
   layer and the arrival of the Creative System band are driven by the same
   scroll progress as the copy, so the band is not sitting there finished while
   the sentence above it is still changing. One continuous sequence.

   The copy carries the change rather than describing it: one phrase defocuses
   away and another forms in its place. Defocus is also deliberately not the
   mechanic used anywhere else on the site, which reveals words by translateY.

   Every custom property defaults to the readable end state, so a script that
   stalls mid-way leaves text legible rather than blurred out.
   --------------------------------------------------------------------------- */

/* the centred block was floating in far more empty height than it needs;
   outside .js because spacing is not something that should depend on a script */
.transition { height: 320px; }
.community-band { padding-top: 44px; }
@media (max-width: 560px) {
  .transition { height: 268px; }
  .community-band { padding-top: 30px; }
}

/* the rule between the two worlds is replaced by the dissolve itself */
.js .transition { isolation: isolate; overflow: hidden; border-top: 0; }
.js .transition .wipe { display: none !important; }

/* Both sections paint the warm world from the same variable, so the two can
   never disagree at the join no matter where the scroll stops. */
.js .transition,
.js .community-band { background: #fff; position: relative; }
.js .transition::before,
.js .community-band::before {
  content: '';
  position: absolute;
  inset: -1px;
  background: var(--cream);
  opacity: var(--tw, 1);
  pointer-events: none;
}
/* Entering the warm world has to be a gradient in space as well as in time.
   Fading the whole section together only moved the hard line from the bottom
   of the passage to the top of it: cream against the white services section.
   So the cream is born out of the white rather than meeting it at an edge. */
.js .transition::before {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 48%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 48%);
}
.js .community-band > * { position: relative; z-index: 1; }
/* The bloom is an ellipse contained inside the section instead of a circle
   wider than the viewport: the circle was still carrying colour at the section
   edges, which is what put a tinted band against the neutral cream next to it. */
.js .transition::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: scale(var(--tg-s, 1));
  background: radial-gradient(ellipse 68% 42% at 50% 50%,
    rgba(241, 90, 50, .20) 0%,
    rgba(241, 90, 50, .07) 45%,
    rgba(241, 90, 50, 0) 74%);
  opacity: var(--tg, 0);
  filter: blur(10px);
  pointer-events: none;
}

.js .transition .transition-inner { opacity: 1 !important; transform: none !important; z-index: 1; }
.js .transition .transition-inner > div { position: relative; }

.js .tstack { position: relative; display: block; min-height: var(--tstack-h, 1px); }
.js .tphrase {
  position: absolute;
  left: 0; right: 0; top: 0;
  margin: 0;
  letter-spacing: -.02em;
  will-change: opacity, filter, transform;
}
.js .tphrase.a {
  opacity: var(--ta, 1);
  filter: blur(var(--ta-b, 0px));
  transform: scale(var(--ta-s, 1));
}
.js .tphrase.b {
  opacity: var(--tb, 0);
  filter: blur(var(--tb-b, 0px));
  transform: scale(var(--tb-s, 1));
}
.js .tphrase.b em { font-style: italic; color: var(--orange); }
.js .transition p { opacity: var(--tp, 1); filter: blur(var(--tp-b, 0px)); }

/* The band's own copy finishes the same sequence, and arrives by the same
   defocus, so the passage reads as one move instead of a transition followed
   by a block that was already waiting. No scale here: .btn owns its transform
   for the hover lift, and a scale() from this layer would silently kill it. */
.js .community-band .reveal { opacity: 1; transform: none; transition: none; }
.js .tband > * {
  opacity: var(--cb, 1);
  filter: blur(var(--cb-b, 0px));
  will-change: opacity, filter;
}

/* full sentence for assistive tech; the two animated phrases are aria-hidden */
.tsr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* cross-document navigation: unsupported browsers ignore the rule */
@view-transition { navigation: auto; }

/* The base sheet already kills transitions under reduced motion, but the .js
   rules outrank its .reveal reset, so the visible state is forced here. The
   threshold keeps its original markup in that mode, so nothing to undo. */
@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .mo-up,
  .js .mo-rw,
  .js .mo-split .mo-wd {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  /* no movement, but still land on the destination colour so the passage
     joins without a hard step */
  .js .transition::before,
  .js .community-band::before { opacity: 1; }
  .js .transition::after { opacity: 0; }
  .js .tband > * { opacity: 1 !important; filter: none !important; }
  @view-transition { navigation: none; }
}
