/* ZB Digital Solutions — animated splash intro
   Loaded on the homepage only. Markup lives at the top of <body> in index.html,
   timeline lives in intro.js. Tweak the knobs below first. */

:root {
  --zb-intro-bg: #0C1116;          /* field colour (graphite). Try #0A2A4A for a bluer field */
  --zb-intro-blue: #2DA4F4;
  --zb-intro-orange: #FF6A13;
  --zb-intro-red: #FF2E4C;         /* RGB-split fringe colours */
  --zb-intro-cyan: #2CF2FF;
  --zb-intro-width: min(78vw, 640px);
  --zb-intro-ease-out: cubic-bezier(.7, 0, .2, 1);
}

/* Hidden unless the inline gate script in index.html marks it active
   (once per session, or ?intro in the URL). The gate runs right after the
   overlay markup, before first paint, so nothing flashes underneath. */
.zb-intro { display: none; }

.zb-intro[data-active] {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--zb-intro-bg);
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  font-family: 'Barlow Condensed', 'Barlow', sans-serif;
}
.zb-intro.is-exit { background: transparent; pointer-events: none; }

/* ---------- field: haze, bands, scanlines, grain, vignette ---------- */
.zb-intro__bg {
  position: absolute;
  inset: 0;
  background: var(--zb-intro-bg);
  clip-path: polygon(-40% 0, 100% 0, 100% 100%, -60% 100%);
  transition: clip-path 620ms var(--zb-intro-ease-out);
}
.zb-intro.is-exit .zb-intro__bg {
  clip-path: polygon(118% 0, 100% 0, 100% 100%, 100% 100%);
}

.zb-intro__field {
  position: absolute;
  inset: -10%;
  opacity: 0;
  background:
    radial-gradient(60% 46% at 50% 50%, rgba(45,164,244,.46), rgba(45,164,244,.12) 55%, transparent 76%),
    linear-gradient(180deg, transparent 40%, rgba(45,164,244,.18) 50%, transparent 60%),
    var(--zb-intro-bg);
  animation: zbFieldIn 700ms ease-out forwards;
}

.zb-intro__bands {
  position: absolute;
  inset: -30% 0;
  filter: blur(1px);
  mix-blend-mode: screen;
  background: linear-gradient(180deg,
    transparent 0 18%, rgba(255,255,255,.07) 20%, transparent 24%,
    transparent 55%, rgba(0,0,0,.28) 57%, transparent 60%,
    transparent 78%, rgba(255,255,255,.05) 80%, transparent 83%);
  animation: zbBands 4.5s linear infinite;
}

.zb-intro__scan {
  position: absolute;
  inset: -20% 0;
  mix-blend-mode: screen;
  background: repeating-linear-gradient(180deg, transparent 0 2px, rgba(255,255,255,.05) 2px 3px);
  animation: zbScanDrift 7s linear infinite;
}

/* the bright "tracking" band that rolls down once behind the title */
.zb-intro__track {
  position: absolute;
  left: 0; right: 0;
  top: -140px;
  height: 110px;
  filter: blur(5px);
  mix-blend-mode: screen;
  background: linear-gradient(180deg, transparent, rgba(255,255,255,.14) 45%, rgba(45,164,244,.30) 55%, transparent);
  animation: zbTrack 1500ms cubic-bezier(.6, 0, .4, 1) 300ms 1 forwards;
}

.zb-intro__grain {
  position: absolute;
  inset: 0;
  opacity: .16;
  mix-blend-mode: screen;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.7 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 260px 260px;
  animation: zbGrain 560ms steps(7) infinite;
}

.zb-intro__vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 50%, transparent 52%, rgba(0,0,0,.72));
}

/* hairline that cuts through the title for a couple of frames */
.zb-intro__hair {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  height: 1px;
  opacity: 0;
  background: rgba(255,255,255,.8);
  box-shadow: 0 0 6px rgba(45,164,244,.9);
  animation: zbHair 380ms steps(2) 980ms 1;
}

/* ---------- lockup ---------- */
.zb-intro__stage {
  position: relative;
  width: var(--zb-intro-width);
  transform-origin: 0 0;
  will-change: transform;
}

.zb-intro__lockup {
  position: relative;
  aspect-ratio: 386 / 64;
  opacity: 0;
}
.zb-intro__ch,
.zb-intro__echo {
  position: absolute;
  inset: 0;
}
.zb-intro__ch svg,
.zb-intro__echo svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.zb-intro__ch--r { mix-blend-mode: screen; opacity: 0; }
.zb-intro__ch--c { mix-blend-mode: screen; opacity: 0; }
.zb-intro__ch--r svg * { fill: var(--zb-intro-red); }
.zb-intro__ch--c svg * { fill: var(--zb-intro-cyan); }

/* ghosted echoes above and below, like the displaced top line in the reference */
.zb-intro__echo {
  opacity: 0;
  filter: blur(2.5px);
}
.zb-intro__echo svg * { fill: rgba(255,255,255,.9); }
.zb-intro__echo--up   { transform: translateY(-135%); }
.zb-intro__echo--down { transform: translateY(135%) scaleX(1.04); }

/* glitch-in */
.zb-intro.is-in .zb-intro__lockup { animation: zbMainIn 900ms steps(1, end) forwards; }
.zb-intro.is-in .zb-intro__ch--main { animation: zbSliceMain 900ms steps(1, end) forwards; }
.zb-intro.is-in .zb-intro__ch--r   { animation: zbSliceR 900ms steps(1, end) forwards; }
.zb-intro.is-in .zb-intro__ch--c   { animation: zbSliceC 900ms steps(1, end) forwards; }
.zb-intro.is-in .zb-intro__echo--up   { animation: zbEcho 900ms steps(1, end) forwards; }
.zb-intro.is-in .zb-intro__echo--down { animation: zbEcho 900ms steps(1, end) 60ms forwards; }

/* micro-glitches during the hold are driven from intro.js with the Web
   Animations API, so the CSS animations above are never swapped (swapping
   animation-name would restart the whole glitch-in). */

/* exit: drop the fringes, pin the main copy, fly it to the header */
.zb-intro.is-exit .zb-intro__ch--r,
.zb-intro.is-exit .zb-intro__ch--c,
.zb-intro.is-exit .zb-intro__echo { opacity: 0 !important; animation: none; }
.zb-intro.is-exit .zb-intro__lockup,
.zb-intro.is-exit .zb-intro__ch--main { animation: none; opacity: 1; clip-path: none; transform: none; }

/* ---------- skip ---------- */
.zb-intro__skip {
  position: absolute;
  right: clamp(16px, 4vw, 48px);
  bottom: clamp(16px, 4vw, 40px);
  padding: 10px 14px;
  border: 1px solid rgba(154,160,166,.35);
  background: transparent;
  color: #9AA0A6;
  font: 600 13px/1 'Barlow Condensed', sans-serif;
  letter-spacing: 4px;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transition: opacity 300ms ease, color 160ms ease, border-color 160ms ease;
}
.zb-intro.is-in .zb-intro__skip { opacity: 1; transition-delay: 500ms; }
.zb-intro.is-exit .zb-intro__skip { opacity: 0; transition-delay: 0ms; }
.zb-intro__skip:hover,
.zb-intro__skip:focus-visible { color: #FFFFFF; border-color: var(--zb-intro-orange); outline: none; }

/* ---------- reduced motion: quiet crossfade, no glitch, no flight ---------- */
.zb-intro.is-rm .zb-intro__bands,
.zb-intro.is-rm .zb-intro__scan,
.zb-intro.is-rm .zb-intro__grain,
.zb-intro.is-rm .zb-intro__track,
.zb-intro.is-rm .zb-intro__hair,
.zb-intro.is-rm .zb-intro__echo,
.zb-intro.is-rm .zb-intro__ch--r,
.zb-intro.is-rm .zb-intro__ch--c { display: none; }
.zb-intro.is-rm .zb-intro__bg { clip-path: none; transition: none; }
.zb-intro.is-rm .zb-intro__lockup { transition: opacity 500ms ease; }
.zb-intro.is-rm.is-in .zb-intro__lockup { animation: none; opacity: 1; }
.zb-intro.is-rm { transition: opacity 450ms ease; }
.zb-intro.is-rm.is-exit { opacity: 0; background: var(--zb-intro-bg); }

/* ---------- keyframes ---------- */
@keyframes zbFieldIn { to { opacity: 1; } }
@keyframes zbBands { from { transform: translateY(0); } to { transform: translateY(-22%); } }
@keyframes zbScanDrift { from { transform: translateY(0); } to { transform: translateY(12%); } }
@keyframes zbTrack { to { top: 110%; } }
@keyframes zbGrain {
  0%   { background-position: 0 0; }
  20%  { background-position: -80px 40px; }
  40%  { background-position: 120px -60px; }
  60%  { background-position: -40px 130px; }
  80%  { background-position: 60px 90px; }
  100% { background-position: -130px -20px; }
}
@keyframes zbHair { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: .8; } }

/* overall flicker of the whole lockup */
@keyframes zbMainIn {
  0%   { opacity: 0; }
  6%   { opacity: 1; }
  10%  { opacity: 0; }
  14%  { opacity: .55; }
  20%  { opacity: 1; }
  27%  { opacity: .25; }
  31%  { opacity: 1; }
  44%  { opacity: 1; }
  47%  { opacity: .4; }
  50%  { opacity: 1; }
  100% { opacity: 1; }
}

/* main copy: sliced horizontal displacement */
@keyframes zbSliceMain {
  0%   { clip-path: inset(0 0 0 0); transform: translateX(0); }
  8%   { clip-path: inset(10% 0 55% 0); transform: translateX(-18px); }
  13%  { clip-path: inset(62% 0 8% 0); transform: translateX(14px); }
  18%  { clip-path: inset(0 0 0 0); transform: translateX(0); }
  26%  { clip-path: inset(30% 0 40% 0); transform: translateX(22px) skewX(-8deg); }
  31%  { clip-path: inset(0 0 0 0); transform: translateX(0); }
  40%  { clip-path: inset(48% 0 20% 0); transform: translateX(-10px); }
  45%  { clip-path: inset(0 0 0 0); transform: translateX(0); }
  58%  { clip-path: inset(0 0 0 0); transform: translateX(3px); }
  62%  { clip-path: inset(0 0 0 0); transform: translateX(0); }
  100% { clip-path: inset(0 0 0 0); transform: translateX(0); }
}
@keyframes zbSliceR {
  0%   { opacity: 1; transform: translateX(-16px); clip-path: inset(0 0 0 0); }
  8%   { transform: translateX(-26px); clip-path: inset(0 0 45% 0); }
  13%  { transform: translateX(-8px);  clip-path: inset(40% 0 0 0); }
  18%  { transform: translateX(-14px); clip-path: inset(0 0 0 0); }
  26%  { transform: translateX(-30px) skewX(6deg); clip-path: inset(20% 0 30% 0); }
  31%  { transform: translateX(-10px); clip-path: inset(0 0 0 0); }
  45%  { transform: translateX(-6px); }
  58%  { transform: translateX(-3px); }
  70%  { transform: translateX(-1px); opacity: 1; }
  100% { transform: translateX(0); opacity: 0; clip-path: inset(0 0 0 0); }
}
@keyframes zbSliceC {
  0%   { opacity: 1; transform: translateX(16px); clip-path: inset(0 0 0 0); }
  8%   { transform: translateX(28px); clip-path: inset(50% 0 0 0); }
  13%  { transform: translateX(10px); clip-path: inset(0 0 55% 0); }
  18%  { transform: translateX(14px); clip-path: inset(0 0 0 0); }
  26%  { transform: translateX(32px) skewX(-6deg); clip-path: inset(0 0 60% 0); }
  31%  { transform: translateX(10px); clip-path: inset(0 0 0 0); }
  45%  { transform: translateX(6px); }
  58%  { transform: translateX(3px); }
  70%  { transform: translateX(1px); opacity: 1; }
  100% { transform: translateX(0); opacity: 0; clip-path: inset(0 0 0 0); }
}
@keyframes zbEcho {
  0%   { opacity: 0; }
  6%   { opacity: .32; }
  14%  { opacity: .12; }
  20%  { opacity: .30; }
  34%  { opacity: .18; }
  50%  { opacity: .22; }
  100% { opacity: 0; }
}
