/* ==========================================================================
   Blue Lily — Intelligent Flow: the home hero.
   Loaded on the home page only. Nothing here reaches another section.

   Motion budget: every moving thing is a transform or an opacity on its own
   element, so the compositor moves it without repainting the hero. The one
   exception is the three points of light, which are tiny.
   ========================================================================== */

:root {
  /* Blue Lily palette (brief). Prefixed so they sit beside the site's existing
     tokens without redefining any of them. */
  --bl-midnight: #0B1630;
  --bl-deep-navy: #10264A;
  --bl-royal: #2563EB;
  --bl-electric: #4DA8FF;
  --bl-soft: #93C5FD;
  --bl-teal: #14B8A6;
  --bl-violet: #8B5CF6;
  --bl-coral: #F28B82;
  --bl-off-white: #F8FAFC;
  --bl-slate: #475569;
}

/* ------------------------------------------------------------ section --- */
.hero-flow {
  position: relative;
  isolation: isolate;
  overflow: clip;
  color: #FFFFFF;
  background-color: var(--bl-midnight);
  background-image: linear-gradient(160deg, var(--bl-midnight) 0%, var(--bl-deep-navy) 58%, #13305C 100%);
}

/* Light, not fog: layered radial gradients cost one paint, where a blurred
   element would cost a filter pass on every frame it moves. */
.hf-sky {
  position: absolute;
  inset: 0;
  z-index: -3;
  background:
    radial-gradient(46% 60% at 82% 18%, rgba(139, 92, 246, .30), transparent 70%),
    radial-gradient(40% 55% at 12% 30%, rgba(37, 99, 235, .28), transparent 72%),
    radial-gradient(38% 40% at 62% 96%, rgba(20, 184, 166, .16), transparent 70%),
    radial-gradient(30% 30% at 70% 52%, rgba(77, 168, 255, .16), transparent 70%);
}

/* ---------------------------------------------------------------- art --- */
.hf-art-wrap { position: absolute; inset: 0; z-index: -2; pointer-events: none; }
.hf-layer {
  position: absolute;
  inset: -24px;               /* room for parallax without exposing an edge */
  /* pointer parallax is written by hero-flow.js, per layer, by depth */
  will-change: transform;
}
.hf-art {
  display: block;
  width: 100%;
  height: 100%;
}
/* The three layers no longer drift. Under THE DRAWN LINE a background that
   moves on its own is exactly what the law forbids: nothing is being drawn
   and nothing is going anywhere. The art stands still; the line draws, and
   the light travels it. */

/* ------------------------------------------------------------- layout --- */
.hf-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(32px, 5vw, 80px);
  min-height: clamp(600px, calc(100svh - 118px), 840px);
  padding-block: clamp(56px, 7vw, 96px);
}
.hf-copy { position: relative; z-index: 2; max-width: 640px; }

.hf-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: var(--space-5);
  font-family: var(--font-label);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  /* Pale blue: 13:1 on midnight. The worst case it has to survive is the
     cursor light and a peak petal behind it at the same moment -- 4.7:1. */
  color: #BFDBFE;
}
.hf-eyebrow::before {
  content: '';
  width: 28px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--bl-electric), var(--bl-violet));
}

.hero-flow h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-hero);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -.035em;
  color: #FFFFFF;
}
.hero-flow h1 em {
  display: block;
  font-style: normal;
  /* `color` is the fallback and the value contrast tools read; the gradient
     runs soft blue to pale violet, and its darkest stop still clears 9:1. */
  color: var(--bl-soft);
  background: linear-gradient(95deg, #93C5FD 0%, #BFDBFE 42%, #C4B5FD 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.hf-lead {
  margin-top: var(--space-6);
  max-width: 34em;
  font-size: var(--text-lg);
  line-height: 1.65;
  color: #C9D8EE;                       /* 11:1 on midnight */
}

.hf-actions { margin-top: var(--space-8); }
.hf-btn-primary {
  background: var(--bl-royal);          /* white text 5.2:1 */
  color: #FFFFFF;
  border: 1px solid rgba(147, 197, 253, .5);
  box-shadow: 0 10px 30px -10px rgba(37, 99, 235, .8), 0 0 0 1px rgba(77, 168, 255, .15);
}
.hf-btn-primary,
.hero-flow .btn--outline-dark { transition: box-shadow .45s ease, background-color .3s ease, border-color .3s ease; }
.hf-btn-primary:hover,
.hf-btn-primary:focus-visible {
  background: #1D4ED8;
  color: #FFFFFF;
  box-shadow: 0 14px 38px -10px rgba(37, 99, 235, .95), 0 0 0 1px rgba(147, 197, 253, .5),
              0 0 34px rgba(77, 168, 255, .45);
}
.hero-flow .btn--outline-dark:hover,
.hero-flow .btn--outline-dark:focus-visible {
  border-color: rgba(147, 197, 253, .85);
  box-shadow: 0 0 28px rgba(77, 168, 255, .32), inset 0 0 18px rgba(77, 168, 255, .12);
}
.hf-btn-primary:focus-visible,
.hero-flow .btn--outline-dark:focus-visible { outline: 3px solid var(--bl-soft); outline-offset: 3px; }

.hf-facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  margin-top: clamp(32px, 4vw, 48px);
  padding-top: var(--space-5);
  border-top: 1px solid rgba(147, 197, 253, .2);
}
.hf-facts dt {
  font-family: var(--font-label);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--bl-soft);
  margin-bottom: 6px;
}
.hf-facts dd { margin: 0; font-size: var(--text-sm); color: #C9D8EE; line-height: 1.5; }

/* -------------------------------------------------------------- stage --- */
.hf-stage {
  position: relative;
  z-index: 1;
  /* leans against the pointer (hero-flow.js), a little less than the near art */
  will-change: transform;
}
.hf-stage__halo {
  position: absolute;
  inset: -14% -10%;
  z-index: -1;
  background:
    /* both sized to closest-side, so each fades out inside the box instead of
       being cut off by its edge */
    radial-gradient(closest-side, rgba(77, 168, 255, .34), transparent),
    radial-gradient(closest-side at 74% 26%, rgba(139, 92, 246, .32), transparent);
}
.hf-window {
  position: relative;
  margin: 0;
  aspect-ratio: 5 / 6;
  /* the hero fits a 900px-tall screen: the window gives way, not the copy */
  max-height: clamp(440px, calc(100svh - 300px), 660px);
  width: 100%;
  border-radius: 32px;
  overflow: hidden;
  border: 1px solid rgba(147, 197, 253, .38);
  box-shadow:
    0 0 0 8px rgba(147, 197, 253, .06),
    0 30px 80px -24px rgba(4, 10, 26, .85),
    0 0 60px rgba(77, 168, 255, .22);
}
.hf-window picture,
.hf-window img { display: block; width: 100%; height: 100%; }
.hf-window img { object-fit: cover; object-position: 62% 50%; }
/* a thin inner light along the top edge -- glass, not a filter */
.hf-window::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, .16), transparent 22%),
              linear-gradient(0deg, rgba(11, 22, 48, .35), transparent 30%);
}

.hf-stage__links {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  z-index: 2;
  pointer-events: none;
}
.hf-stage__links path {
  fill: none;
  stroke: rgba(147, 197, 253, .55);
  stroke-width: 1.2;
  stroke-dasharray: 3 4;
  vector-effect: non-scaling-stroke;
}

.hf-chip {
  position: absolute;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 18px;
  color: var(--bl-soft);
  background: linear-gradient(160deg, rgba(16, 38, 74, .94), rgba(11, 22, 48, .94));
  border: 1px solid rgba(147, 197, 253, .42);
  box-shadow: 0 12px 30px -10px rgba(4, 10, 26, .8), 0 0 22px rgba(77, 168, 255, .25);
  /* chips sit nearest the viewer; their parallax is set by hero-flow.js */
}
.hf-chip--a { left: -22px; top: 12%; }
.hf-chip--b { right: -22px; top: 52%; color: #C4B5FD; }
.hf-chip--c { left: 4%; bottom: -20px; color: #5EEAD4; }

/* ------------------------------------------------------------ petals --- */
/* On navy the petals are the brightest thing behind white type; the ceiling
   is set in petals.py (tone "dark"), and the glow is cooled here. */
/* Glow as a painted halo, not a filter. A drop-shadow on twelve moving petals
   measured 44fps against 60 without it; a radial gradient behind each petal is
   rasterised once with the petal and then only moved. */
.hero-flow .petal__drift::before {
  inset: -45% -110%;
  background: radial-gradient(closest-side, rgba(96, 165, 250, .42), rgba(96, 165, 250, .12) 55%, transparent);
}
.hero-flow .petal__drift::before { opacity: .8; transition: opacity .6s ease; }
/* the heading's hover brightens the halo; it must not bring the filter back */
.hero-flow .petal-heading:hover .petal__drift { filter: none; }
.hero-flow .petal-heading:hover .petal__drift::before { opacity: 1; }
/* The cluster frames the heading and stops short of the paragraph below. */
.hf-heading > .petal-field { inset: -46% -16% -8%; }

/* -------------------------------------------------- load choreography --- */
/* Brief §6: navigation, eyebrow, headline, text, buttons, then the petals.
   Complete inside about a second. With motion reduced, or animations not
   supported, everything is simply present. */
@media (prefers-reduced-motion: no-preference) {
  body:has(.hero-flow) .site-header { animation: hf-fade-down .6s var(--ease-out, ease-out) both; }
  .hf-eyebrow, .hero-flow h1, .hf-lead, .hf-actions, .hf-facts {
    animation: hf-rise .85s var(--ease-out, ease-out) both;
  }
  .hf-eyebrow  { animation-delay: .12s; }
  .hero-flow h1 { animation-delay: .22s; }
  .hf-lead     { animation-delay: .38s; }
  .hf-actions  { animation-delay: .5s; }
  .hf-facts    { animation-delay: .62s; }
  /* The stage carries the pointer parallax as a transform, and an animation
     with fill-mode holds its end transform forever -- which would switch the
     parallax off. So the stage only fades; the window inside it does the
     rise-and-settle. */
  .hf-stage    { animation: hf-fade 1.2s var(--ease-out, ease-out) .25s both; }
  .hf-window   { animation: hf-bloom 1.2s var(--ease-out, ease-out) .25s both; }
  .hf-art-wrap { animation: hf-fade 1.6s ease-out both; }
  .hero-flow .petal-field { transition-delay: .85s; }
}
@keyframes hf-rise { from { opacity: 0; transform: translate3d(0, 20px, 0); } to { opacity: 1; transform: none; } }
@keyframes hf-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes hf-fade-down { from { opacity: 0; transform: translate3d(0, -10px, 0); } to { opacity: 1; transform: none; } }
@keyframes hf-bloom { from { opacity: 0; transform: translate3d(0, 24px, 0) scale(.97); } to { opacity: 1; transform: none; } }

/* -------------------------------------------------------- cursor light --- */
/* A soft pool of blue light that follows the pointer across the hero, behind
   the photo and the copy. One element, moved by transform from
   hero-flow.js; it never exists on touch or under reduced motion. */
.hf-cursor-light {
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  width: 620px;
  height: 620px;
  margin: -310px 0 0 -310px;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(77, 168, 255, .16),
                              rgba(139, 92, 246, .07) 55%, transparent);
  opacity: 0;
  transition: opacity .9s ease;
  will-change: transform;
}
.hero-flow.has-pointer .hf-cursor-light { opacity: 1; }

/* ------------------------------------------------------ petals emerge --- */
/* "Knowledge blossoms": the cluster opens out from the heading rather than
   simply appearing -- a slow scale-up of the whole field, with each petal
   arriving a beat after the one before. */
@media (prefers-reduced-motion: no-preference) {
  .hero-flow .petal-field {
    transform: scale(.82);
    transition: opacity 2.2s var(--petal-ease), transform 2.8s var(--petal-ease);
  }
  .hero-flow .petal-field.is-blooming { transform: none; }
  .hero-flow .petal__drift::before,
  .hero-flow .petal svg { opacity: 0; transition: opacity 1.6s ease; }
  .hero-flow .is-blooming .petal__drift::before { opacity: .8; }
  .hero-flow .is-blooming .petal svg { opacity: 1; }
  .hero-flow .petal:nth-child(2)  svg, .hero-flow .petal:nth-child(2)  .petal__drift::before { transition-delay: .9s; }
  .hero-flow .petal:nth-child(3)  svg, .hero-flow .petal:nth-child(3)  .petal__drift::before { transition-delay: 1.05s; }
  .hero-flow .petal:nth-child(4)  svg, .hero-flow .petal:nth-child(4)  .petal__drift::before { transition-delay: 1.2s; }
  .hero-flow .petal:nth-child(5)  svg, .hero-flow .petal:nth-child(5)  .petal__drift::before { transition-delay: 1.35s; }
  .hero-flow .petal:nth-child(6)  svg, .hero-flow .petal:nth-child(6)  .petal__drift::before { transition-delay: 1.5s; }
  .hero-flow .petal:nth-child(7)  svg, .hero-flow .petal:nth-child(7)  .petal__drift::before { transition-delay: 1.65s; }
  .hero-flow .petal:nth-child(8)  svg, .hero-flow .petal:nth-child(8)  .petal__drift::before { transition-delay: 1.8s; }
  .hero-flow .petal:nth-child(9)  svg, .hero-flow .petal:nth-child(9)  .petal__drift::before { transition-delay: 1.95s; }
  .hero-flow .petal:nth-child(10) svg, .hero-flow .petal:nth-child(10) .petal__drift::before { transition-delay: 2.1s; }
  .hero-flow .petal:nth-child(11) svg, .hero-flow .petal:nth-child(11) .petal__drift::before { transition-delay: 2.25s; }
  .hero-flow .petal:nth-child(12) svg, .hero-flow .petal:nth-child(12) .petal__drift::before { transition-delay: 2.4s; }
  .hero-flow .petal:nth-child(1)  svg, .hero-flow .petal:nth-child(1)  .petal__drift::before { transition-delay: .75s; }
}
/* Without JS nothing adds .is-blooming, so the petals are shown outright. */
html:not(.js) .hero-flow .petal svg { opacity: 1 !important; }
html:not(.js) .hero-flow .petal-field { transform: none !important; }

/* ---------------------------------------------------------- responsive --- */
@media (max-width: 1024px) {
  .hf-inner {
    grid-template-columns: 1fr;
    min-height: 0;
    gap: clamp(40px, 6vw, 56px);
  }
  .hf-copy { max-width: 680px; }
  .hf-stage { max-width: 680px; }
  .hf-window { aspect-ratio: 16 / 10; max-height: none; }
  /* The art is drawn for a landscape hero; on a tall one it scales up and the
     node lines become long diagonals. Ribbons and strands carry it alone. */
  .hf-layer--near { display: none; }
  /* The upper current goes with them, and for the same reason. One SVG on a
     1440x820 viewBox drawn `slice` means a tall hero scales the art up and
     crops the sides, so a line that lives in the sky on a wide screen is
     dragged down into the copy on a narrow one: measured at 768 it ran at
     y 246-265 through a headline occupying 231-320, and at 390 it crossed the
     top of "Technology for". It cannot be moved out of the way, because its
     position is the viewBox's, not the layout's -- so it stands down, and the
     lead line keeps the hero's motion by itself. */
  .hf-strand--upper, .hf-pulse--upper { display: none; }
  .hf-stage, .hf-chip { transform: none; }
}
@media (max-width: 720px) {
  /* the step already shrinks on narrow screens; no override needed */
  .hf-lead { font-size: var(--text-base); }
  .hf-facts { grid-template-columns: 1fr 1fr; }
  .hf-window { aspect-ratio: 16 / 10; border-radius: 24px; }
  .hf-chip { width: 46px; height: 46px; border-radius: 14px; }
  .hf-chip svg { width: 20px; height: 20px; }
  .hf-chip--a { left: -8px; }
  .hf-chip--b { right: -8px; }
  /* simpler art on phones: the node layer goes, the ribbons stay */
  .hf-layer--near { display: none; }
  .hf-actions .btn { flex: 1 1 100%; justify-content: center; }
}
@media (hover: none), (pointer: coarse) {
  .hf-layer, .hf-stage, .hf-chip { transform: none; }
  .hf-cursor-light { display: none; }
}

/* ------------------------------------------------------ reduced motion --- */
@media (prefers-reduced-motion: reduce) {
  .hf-art, .hf-layer, .hf-stage, .hf-chip { animation: none !important; transform: none !important; }
  .hf-pulse, .hf-cursor-light { display: none; }
}

/* THE DRAW. The strand is dashed to its own full length and the dash is
   pulled back to zero, which is a path drawing itself. It runs once, on load,
   with `forwards`, so it cannot restart, jump or stick halfway -- and because
   the base state here is the finished line, anything that stops the animation
   (reduced motion, an old browser) shows the drawn result.

   This block sits at the TOP LEVEL. It spent one release nested inside the
   reduced-motion query above, where the no-preference query below could never
   match and the draw never ran for anybody. */
.hf-strand { stroke-dasharray: 1; stroke-dashoffset: 0; }
/* the lead carries a glow of its own, so the line reads as light rather than
   as a hairline drawn on the sky */
.hf-strand--lead { filter: drop-shadow(0 0 9px rgba(96, 165, 250, .55)); }
@media (prefers-reduced-motion: no-preference) {
  .hf-strand {
    stroke-dashoffset: 1;
    animation: hf-draw 2.2s cubic-bezier(.22, .61, .36, 1) forwards;
    animation-delay: calc(.25s + var(--i) * .13s);
  }
}
@keyframes hf-draw { to { stroke-dashoffset: 0; } }

/* the travelling light waits for its line to exist */
.hf-layer--lights { opacity: 0; animation: hf-lights-in 1.2s ease 1.5s forwards; }
@keyframes hf-lights-in { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .hf-layer--lights { opacity: 1; animation: none; } }
/* paused off screen / hidden tab (class set by hero-flow.js) */
.hero-flow.is-paused .hf-art { animation-play-state: paused; }
