/* ==========================================================================
 * motion.css — movement, loaded after site.css.
 *
 * The brief was "more modern, with wow". The constraint nobody states but
 * everybody feels: this is a site about defensible evidence, sold to
 * compliance officers and auditors. Motion here has to read as precision —
 * things settling into place, figures being counted — never as decoration
 * competing with the text. So: slow easings, small distances, one idea per
 * screen, and the whole layer disappears under prefers-reduced-motion.
 *
 * Everything below is transform/opacity only, so nothing here can move the
 * layout or cost a reflow.
 * ========================================================================== */

/* ---- reveal -------------------------------------------------------------
   Only hidden when JS is running (html.js-motion), so a reader without it
   gets the whole page as written, instantly. */
html.js-motion [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
}
html.js-motion [data-reveal].is-in {
  opacity: 1;
  transform: none;
  /* long, with a late-settling curve: the eye should catch arrival, not travel */
  transition: opacity .7s cubic-bezier(.22,.61,.36,1) var(--reveal-delay, 0ms),
              transform .7s cubic-bezier(.22,.61,.36,1) var(--reveal-delay, 0ms);
}

/* ---- the hero -----------------------------------------------------------
   An aurora: two slow, very low-contrast fields drifting behind the
   headline. At this opacity it is barely a colour — it is the sense that the
   page is looking at something. */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* The aurora gets its own tints rather than borrowing --accent-soft, which
     on the institutional skin is a near-grey and disappeared entirely. Mixed
     from the skin's own accent, so the product pages (data-brand="ri") come
     out teal and the company pages deep blue, with no second palette. */
  --aurora-a: color-mix(in srgb, var(--accent) 26%, transparent);
  --aurora-b: color-mix(in srgb, var(--ai) 20%, transparent);
}
:root[data-brand="ri"] .hero {
  --aurora-a: color-mix(in srgb, var(--accent) 34%, transparent);
}
.hero::before,
.hero::after {
  content: "";
  position: absolute;
  z-index: -1;
  border-radius: 50%;
  filter: blur(80px);
  opacity: .85;
  pointer-events: none;
}
.hero::before {
  width: 46vw; height: 46vw; min-width: 420px; min-height: 420px;
  top: -24vw; right: -10vw;
  background: radial-gradient(circle at 30% 30%, var(--aurora-a), transparent 68%);
  animation: aurora-a 26s ease-in-out infinite alternate;
}
.hero::after {
  width: 34vw; height: 34vw; min-width: 320px; min-height: 320px;
  bottom: -20vw; left: -8vw;
  background: radial-gradient(circle at 60% 40%, var(--aurora-b), transparent 70%);
  animation: aurora-b 34s ease-in-out infinite alternate;
}
@keyframes aurora-a {
  from { transform: translate3d(0,0,0) scale(1); }
  to   { transform: translate3d(-4vw, 3vw, 0) scale(1.12); }
}
@keyframes aurora-b {
  from { transform: translate3d(0,0,0) scale(1.06); }
  to   { transform: translate3d(5vw, -3vw, 0) scale(1); }
}

/* The scanning rule under the headline: one pass on arrival, then still.
   It is the product's gesture — reading a line and judging it. */
.hero h1 { position: relative; }
.hero h1::after {
  content: "";
  position: absolute;
  left: 0; bottom: -.18em;
  height: 2px; width: 100%;
  background: linear-gradient(90deg, var(--accent), transparent);
  transform-origin: left;
  animation: scan 1.6s cubic-bezier(.22,.61,.36,1) .35s both;
}
@keyframes scan {
  from { transform: scaleX(0); opacity: .9; }
  60%  { transform: scaleX(1); opacity: .9; }
  to   { transform: scaleX(1); opacity: .35; }
}

/* The hero's own entrance, before any scrolling has happened. */
html.js-motion .hero > .wrap > * { animation: rise .8s cubic-bezier(.22,.61,.36,1) both; }
html.js-motion .hero > .wrap > :nth-child(1) { animation-delay: .05s; }
html.js-motion .hero > .wrap > :nth-child(2) { animation-delay: .15s; }
html.js-motion .hero > .wrap > :nth-child(3) { animation-delay: .25s; }
html.js-motion .hero > .wrap > :nth-child(4) { animation-delay: .35s; }
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* ---- chrome -------------------------------------------------------------
   The header earns its border only once you have left the top of the page. */
.site-header {
  transition: box-shadow .35s ease, backdrop-filter .35s ease, background-color .35s ease;
}
.site-header.is-scrolled {
  background: color-mix(in srgb, var(--bg-raised) 86%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  box-shadow: 0 1px 0 var(--border), 0 10px 30px -22px rgba(20,30,45,.45);
}
.scroll-progress {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 300;
  background: linear-gradient(90deg, var(--accent), var(--ai));
  transform: scaleX(0); transform-origin: left;
  will-change: transform;
}

/* ---- things you can point at -------------------------------------------
   One hover language for every card on the site: lift a little, take the
   accent on the hairline, and move the arrow that was already there. */
.cap, .stat, .product, .hcard, .pillar, .principle, .aud, .press-item, .pub-item, .team-card, .paper {
  transition: transform .35s cubic-bezier(.22,.61,.36,1),
              box-shadow .35s ease, border-color .35s ease;
}
.cap:hover, .stat:hover, .product:hover, .hcard:hover,
.pillar:hover, .principle:hover, .aud:hover,
.press-item:hover, .pub-item:hover, .team-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-line);
  box-shadow: 0 18px 40px -28px rgba(20,30,45,.55);
}
.press-item-offline:hover { transform: none; box-shadow: none; }

.more { transition: transform .3s cubic-bezier(.22,.61,.36,1); display: inline-block; }
.go { transition: transform .3s cubic-bezier(.22,.61,.36,1); display: inline-block; }
.press-item:hover .more, .pub-item:hover .more, .insight-item:hover .more,
.hcard:hover .go { transform: translateX(5px); }

/* The product plates catch the light once, as they arrive. */
.logo-plate { position: relative; overflow: hidden; }
.product.is-in .logo-plate::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.65) 50%, transparent 62%);
  transform: translateX(-120%);
  animation: shine 1.3s cubic-bezier(.22,.61,.36,1) .45s both;
}
@keyframes shine { to { transform: translateX(120%); } }

/* Buttons: the primary one leans toward the cursor (motion.js) and lifts. */
.btn { transition: transform .25s cubic-bezier(.22,.61,.36,1), box-shadow .25s ease, background-color .25s ease, color .25s ease; }
.btn-primary:hover { box-shadow: 0 14px 28px -18px var(--accent); }
.btn-secondary:hover { transform: translateY(-1px); }

/* Counted figures must not jitter while the digits change. */
.stat .num { font-variant-numeric: tabular-nums; }

/* Printing. A reveal that has not fired yet is opacity:0, and this site gets
   printed -- the whitepapers render to PDF through a browser. Nothing may be
   invisible on paper because of an animation that never ran. */
@media print {
  html.js-motion [data-reveal],
  html.js-motion .hero > .wrap > * { opacity: 1 !important; transform: none !important; animation: none !important; }
  .scroll-progress, .hero::before, .hero::after { display: none !important; }
}

/* ---- the one rule that outranks all of the above ------------------------ */
@media (prefers-reduced-motion: reduce) {
  html.js-motion [data-reveal],
  html.js-motion .hero > .wrap > * { opacity: 1 !important; transform: none !important; animation: none !important; }
  .hero::before, .hero::after, .hero h1::after,
  .product.is-in .logo-plate::after { animation: none !important; }
  .cap, .stat, .product, .press-item, .pub-item, .team-card, .btn, .more { transition: none !important; }
  .scroll-progress { display: none; }
}
