/* ============================================================ motion.css
 *
 * Movement, and only movement. A third layer after tamitos.css (the
 * system), public.css (the layout) and modern.css (the surfaces).
 *
 * It is its own file rather than more of modern.css because the two answer
 * different questions. modern.css decides what a card looks like; this
 * decides how a card arrives. Keeping them apart means the frosted
 * surfaces can be edited without touching a single animation, and this
 * whole file can be dropped from a `<link>` if it ever turns out to be a
 * mistake.
 *
 * Three rules hold it:
 *
 * 1. It never invents a colour. Everything here is a variable from
 *    tamitos.css or a gradient mixed out of those variables.
 * 2. Nothing is hidden unless JavaScript is running. Every rule that parks
 *    an element out of view is scoped to `html.js`, and motion.js sets that
 *    class as its first statement. A blocked file, a proxy that rewrites
 *    scripts, a parser on an old phone: the page renders exactly as it did
 *    before this file existed.
 * 3. `prefers-reduced-motion` turns the whole thing off, reveals included.
 *    modern.css already honours it in the four places it moves; this file
 *    does it once, at the end, for everything.
 *
 * It does not restyle anything modern.css already owns. The frost, the
 * questions, the live strip and the bar's own background all stay where
 * they are.
 * ==================================================================== */

:root {
  /* The thread. Blue into lilac into mint: the app's own three accents in
     the order a person meets them. Movement, conversion, arrival. */
  --energy: linear-gradient(103deg, #6fbaf7 0%, #b197fc 52%, #8fd9c4 100%);

  --glow-blue: rgba(111, 186, 247, 0.45);
  --glow-lilac: rgba(177, 151, 252, 0.42);
  --glow-mint: rgba(143, 217, 196, 0.42);

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ==================================================================== */
/* 1. The read line                                                     */
/*                                                                       */
/* Two pixels of gradient across the very top, filling as the page is    */
/* read. The cheapest possible progress indicator: one transform, driven */
/* by a scroll listener that does nothing but write a custom property.   */
/*                                                                       */
/* Not `.rail`: tamitos.css already has one, in the console.             */
/* ==================================================================== */

.readline {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  padding: 0;
  z-index: 60;
  background: var(--energy);
  transform: scaleX(var(--read, 0));
  transform-origin: 0 50%;
  pointer-events: none;
  will-change: transform;
}

/* ==================================================================== */
/* 2. The bar                                                           */
/*                                                                       */
/* modern.css owns the frost. This adds the one thing a sticky bar needs */
/* and did not have: an acknowledgement that the page has moved under    */
/* it. Padding and a shadow only, so the frost and the reduced           */
/* transparency rule above it are both left alone.                       */
/* ==================================================================== */

.page .nav {
  transition: padding 0.3s var(--ease-soft),
              box-shadow 0.3s var(--ease-soft);
}
html.is-scrolled .page .nav {
  padding-top: 11px;
  padding-bottom: 11px;
  box-shadow: 0 6px 26px rgba(38, 50, 66, 0.09);
}

/* The underline grows rather than blinks. */
.nav__links a {
  position: relative;
  border-bottom-color: transparent !important;
  transition: color 0.2s var(--ease-soft);
}
.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--energy);
  transform: scaleX(0);
  transition: transform 0.28s var(--ease-out);
}
.nav__links a:hover::after,
.nav__links a.is-on::after { transform: scaleX(1); }

/* ==================================================================== */
/* 3. Buttons                                                           */
/*                                                                       */
/* A sheen that crosses once on hover. The only piece of pure decoration */
/* in this file, which is why it is over in 0.55s.                       */
/* ==================================================================== */

.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.2s var(--ease-out),
              box-shadow 0.25s var(--ease-out);
}
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg,
              transparent 32%,
              rgba(255, 255, 255, 0.5) 50%,
              transparent 68%);
  transform: translateX(-120%);
}
.btn:hover { transform: translateY(-2px); }
.btn--primary:hover { box-shadow: 0 12px 26px rgba(74, 168, 224, 0.42); }
.btn:hover::after {
  transform: translateX(120%);
  transition: transform 0.55s var(--ease-soft);
}
.btn:active { transform: translateY(0); }

/* ==================================================================== */
/* 4. The reveal                                                        */
/*                                                                       */
/* Everything carrying data-rise starts a little low and a little dim,   */
/* and motion.js hands it is-in when it reaches the viewport. The --i    */
/* variable staggers siblings; 70ms reads as a sequence and finishes a   */
/* row of six inside half a second.                                      */
/*                                                                       */
/* The whole block is behind html.js. Without the script the page has no */
/* opacity rules at all and everything is simply there.                  */
/* ==================================================================== */

html.js [data-rise] {
  opacity: 0;
  transform: translateY(18px);
}
html.js [data-rise].is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.62s var(--ease-out),
              transform 0.62s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}

/* The hero does not wait for a scroll. It plays on load, top to bottom,
   so the first thing a visitor sees is the page assembling itself. */
html.js .hero__text > *,
html.js .hero__art {
  opacity: 0;
  transform: translateY(20px);
}
html.js.is-ready .hero__text > *,
html.js.is-ready .hero__art {
  opacity: 1;
  transform: none;
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}
html.js.is-ready .hero__text h1 { transition-delay: 0.06s; }
html.js.is-ready .hero__lede { transition-delay: 0.14s; }
html.js.is-ready .hero__cta { transition-delay: 0.22s; }
html.js.is-ready .hero__fine { transition-delay: 0.3s; }
html.js.is-ready .hero__art {
  transition-delay: 0.1s;
  transition-duration: 0.9s;
}

/* ==================================================================== */
/* 5. The hero                                                          */
/*                                                                       */
/* Two soft lights behind the picture on a 22 second loop. Slow enough   */
/* that nobody watches it and the corner is never quite still, which is  */
/* the difference between a rendered page and a printed one.             */
/* ==================================================================== */

.hero {
  position: relative;
  isolation: isolate;
}
.hero::before,
.hero::after {
  content: "";
  position: absolute;
  z-index: -1;
  aspect-ratio: 1;
  border-radius: 50%;
  pointer-events: none;
}
.hero::before {
  top: -18%;
  right: -6%;
  width: 46vw;
  max-width: 620px;
  background: radial-gradient(circle at 50% 50%,
              var(--glow-blue) 0%, rgba(111, 186, 247, 0) 68%);
  filter: blur(14px);
  animation: drift 22s var(--ease-soft) infinite alternate;
}
.hero::after {
  bottom: -22%;
  left: -10%;
  width: 40vw;
  max-width: 520px;
  background: radial-gradient(circle at 50% 50%,
              var(--glow-lilac) 0%, rgba(177, 151, 252, 0) 70%);
  filter: blur(16px);
  animation: drift 26s var(--ease-soft) infinite alternate-reverse;
}
@keyframes drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(-4%, 5%, 0) scale(1.12); }
}

.hero__text h1 {
  font-size: clamp(38px, 6.4vw, 62px);
  letter-spacing: -0.028em;
  text-wrap: balance;
}
/* The last two words of the headline carry the thread. Written by
   motion.js out of text nodes, so the markup stays a plain sentence for a
   screen reader and the words are still the words. */
.hero__text h1 .thread {
  background: var(--energy);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero__art img { animation: float 9s var(--ease-soft) infinite alternate; }
@keyframes float {
  from { transform: translateY(0); }
  to { transform: translateY(-12px); }
}

/* ==================================================================== */
/* 6. The three steps                                                   */
/*                                                                       */
/* The steps really are a sequence, so they get the one structural       */
/* device on the page that says so: a gradient thread drawn between the  */
/* numbers as the section arrives. Hidden where they stack, because a    */
/* horizontal line through a vertical list points at nothing.            */
/* ==================================================================== */

.steps {
  position: relative;
  /* Its own stacking context, so the thread below can be sent behind the
     three cards without disappearing behind the band as well. */
  isolation: isolate;
}
.steps::before {
  content: "";
  position: absolute;
  /* Level with the middle of the numbers, and stopping at the middle of the
     first and the last, so it runs between them rather than past them. */
  top: 38px;
  left: 39px;
  right: 39px;
  height: 2px;
  z-index: -1;
  border-radius: 2px;
  background: var(--energy);
  opacity: 0.55;
  transform: scaleX(0);
  transform-origin: 0 50%;
}
html.js .steps.is-in::before {
  transform: scaleX(1);
  transition: transform 1.1s var(--ease-out) 0.15s;
}
html:not(.js) .steps::before { transform: scaleX(1); }

.steps__n {
  position: relative;
  z-index: 1;
  background: var(--energy);
  color: #fff;
  box-shadow: 0 6px 18px rgba(111, 186, 247, 0.34);
}

@media (max-width: 760px) {
  .steps::before { display: none; }
}

/* ==================================================================== */
/* 7. Cards and tiles                                                   */
/*                                                                       */
/* The coloured edge and its halo are surfaces, so they live in          */
/* modern.css and are there whether this file loads or not. What is here */
/* is the one thing that is genuinely movement: a light that follows the */
/* pointer across the pane.                                              */
/*                                                                       */
/* motion.js writes --mx and --my on the card under the cursor. With no  */
/* script the variables are absent, the gradient falls back to its own   */
/* centre, and the layer is transparent anyway until somebody hovers.    */
/* ==================================================================== */

.card::after,
.post::after,
.ptile::after,
.tile::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 0%),
              rgba(255, 255, 255, 0.5), transparent 62%);
  opacity: 0;
  transition: opacity 0.3s var(--ease-soft);
  pointer-events: none;
}
.card:hover::after,
.post:hover::after,
.ptile:hover::after,
.tile:hover::after { opacity: 1; }

.voice {
  transition: transform 0.26s var(--ease-out);
}
.voice:hover { transform: translateY(-2px); }

/* The questions already open and close in modern.css. All this adds is the
   turn of the chevron being worth watching. */
.faq__q::after { transition: transform 0.28s var(--ease-out); }

/* ==================================================================== */
/* 8. Figures                                                           */
/*                                                                       */
/* The numbers count up once, when they arrive. Tabular figures so the   */
/* box does not twitch by a pixel while the digits change, which is the  */
/* thing that makes a counter look cheap.                                */
/* ==================================================================== */

.stat__value,
.ptile__sum {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.stat--big .stat__value {
  background: var(--energy);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat {
  transition: transform 0.24s var(--ease-out),
              box-shadow 0.24s var(--ease-out);
}
.stat:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 28px rgba(38, 50, 66, 0.1);
}

/* ==================================================================== */
/* 9. Section titles                                                    */
/*                                                                       */
/* A short gradient stroke above each one, drawn as the section lands.   */
/* The thread again, at the smallest size it appears in.                 */
/* ==================================================================== */

.section-title { position: relative; }
.band__inner > .section-title::before,
.section-head .section-title::before,
.stage__inner > .section-title::before {
  content: "";
  position: absolute;
  top: -14px;
  left: 0;
  width: 46px;
  height: 3px;
  border-radius: 3px;
  background: var(--energy);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
html.js .is-in .section-title::before,
html.js .section-title.is-in::before {
  transform: scaleX(1);
  transition: transform 0.6s var(--ease-out) 0.1s;
}
html:not(.js) .section-title::before { transform: scaleX(1); }

/* ==================================================================== */
/* 10. The two closing doors                                            */
/* ==================================================================== */

.end {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.26s var(--ease-out);
}
.end::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -60%;
  right: -30%;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle,
              var(--glow-mint) 0%, rgba(143, 217, 196, 0) 70%);
  opacity: 0;
  transition: opacity 0.4s var(--ease-soft);
}
.end--alt::before {
  background: radial-gradient(circle,
              var(--glow-lilac) 0%, rgba(177, 151, 252, 0) 70%);
}
.end:hover { transform: translateY(-3px); }
.end:hover::before { opacity: 1; }

/* ==================================================================== */
/* 11. The footer                                                       */
/* ==================================================================== */

.foot { position: relative; }
.foot::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--energy);
  opacity: 0.55;
}

/* ==================================================================== */
/* 12. Off                                                              */
/*                                                                       */
/* Not a partial reduction. Somebody who has asked their system for less */
/* movement gets a page with none: no drift, no float, no sheen, no      */
/* reveal, no counting. Everything is at its finished state on the first */
/* frame, which is also what the page looks like with no script at all.  */
/* The audience this product is written for is exactly the audience for  */
/* whom this setting is not a preference.                                */
/* ==================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
  html.js [data-rise],
  html.js .hero__text > *,
  html.js .hero__art {
    opacity: 1 !important;
    transform: none !important;
  }
  .steps::before,
  .section-title::before { transform: scaleX(1) !important; }
  .readline { display: none; }
}
