/* The heartbeat intro from the live site, carried over as it is.
   Adapted for the sample: the percentage uses the display type, labels use the mono type, and the reveal eases the page (main and top bar) into focus. */
/* ========== Intro screen (3.6 seconds, Home page only, once per visit) ==========
   A vital-signs monitor. Timeline:
   0.2-2.4s  the heartbeat trace sweeps across, the percentage counts to 100, three skills change underneath (about 0.73s each)
   2.45s     the percentage lifts away, the skill drops away
   2.55s     the trace collapses into one glowing point in the center
   2.7s      that point pulses once, like a last heartbeat
   2.9s      a circle bursts open from it with a glowing green edge and reveals the site, which eases into focus
   3.6s      the screen hides itself with CSS alone, so a script error can't trap anyone */
@property --hole { syntax: "<length>"; inherits: true; initial-value: 0px; }

.intro-screen { display: none; }
.intro .intro-screen { display: block; position: fixed; inset: 0; z-index: 10000; overflow: hidden; color: #FEFAE0;
  background-color: #0E1409;
  background-image: linear-gradient(rgba(69, 189, 98, .05) 1px, transparent 1px), linear-gradient(90deg, rgba(69, 189, 98, .05) 1px, transparent 1px);
  background-size: 40px 40px;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent var(--hole), #000 calc(var(--hole) + 1px));
  mask-image: radial-gradient(circle at 50% 50%, transparent var(--hole), #000 calc(var(--hole) + 1px));
  animation: holeOpen .7s cubic-bezier(.65, 0, .25, 1) 2.9s forwards, introGone 0s 3.6s forwards; }
.intro.intro-done .intro-screen { display: none; }
@keyframes holeOpen { to { --hole: 80vmax; } }
@keyframes introGone { to { visibility: hidden; pointer-events: none; } }

/* Glowing green edge that rides the opening circle */
.intro .intro-screen::before { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(circle at 50% 50%, transparent var(--hole), rgba(69, 189, 98, .95) calc(var(--hole) + 1px), rgba(69, 189, 98, .3) calc(var(--hole) + 10px), rgba(69, 189, 98, 0) calc(var(--hole) + 70px));
  animation: rimOn .12s linear 2.9s forwards; }
@keyframes rimOn { to { opacity: 1; } }

/* Heartbeat trace across the full width */
.intro-ecg { position: absolute; left: 0; right: 0; top: 50%; height: clamp(90px, 16vh, 140px); margin-top: calc(clamp(90px, 16vh, 140px) / -2); transform-origin: 50% 50%; animation: traceIn .3s ease both, traceCollapse .3s cubic-bezier(.7, 0, .84, 0) 2.55s forwards; }
@keyframes traceIn { from { opacity: 0; } }
@keyframes traceCollapse { 90% { opacity: 1; } to { transform: scaleX(0) scaleY(.2); opacity: 0; } }
.intro-ecg svg { display: block; width: 100%; height: 100%; overflow: visible; }
.intro-ecg path { fill: none; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.intro-ecg .ghost { stroke: rgba(69, 189, 98, .12); stroke-width: 1.5; }
.intro-ecg .trace { stroke: #45BD62; stroke-width: 2.2; stroke-dasharray: 100; stroke-dashoffset: calc(100 - var(--p, 0) * 100); filter: drop-shadow(0 0 6px rgba(69, 189, 98, .7)); }
.intro-ecg .head { position: absolute; left: 0; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: #E9FFE9; box-shadow: 0 0 0 4px rgba(69, 189, 98, .35), 0 0 22px 6px rgba(69, 189, 98, .8); opacity: var(--dot, 0); }

/* The point the trace collapses into: one strong pulse, then the circle opens from it */
.intro-core { position: absolute; left: 50%; top: 50%; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; background: #E9FFE9; box-shadow: 0 0 0 6px rgba(69, 189, 98, .35), 0 0 40px 12px rgba(69, 189, 98, .85); opacity: 0; transform: scale(0); animation: corePulse .3s cubic-bezier(.3, 1.6, .5, 1) 2.7s forwards, coreOut .2s ease-in 2.95s forwards; }
@keyframes corePulse { 0% { opacity: 1; transform: scale(0); } 55% { opacity: 1; transform: scale(1.9); } 100% { opacity: 1; transform: scale(1); } }
@keyframes coreOut { to { opacity: 0; transform: scale(3); } }

/* Big percentage above the trace, skill underneath */
.intro-pct { position: absolute; left: 50%; bottom: calc(50% + clamp(56px, 10vh, 84px)); transform: translateX(-50%); font-size: clamp(3.2rem, 9vw, 6rem); font-weight: 600; line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; animation: textIn .45s cubic-bezier(.2, .8, .2, 1) .05s both, pctOut .3s cubic-bezier(.7, 0, .84, 0) 2.45s forwards; }
.intro-skill { position: absolute; left: 50%; top: calc(50% + clamp(56px, 10vh, 84px)); transform: translateX(-50%); display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; font-size: .8rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; color: rgba(254, 250, 224, .75); animation: textIn .45s cubic-bezier(.2, .8, .2, 1) .12s both, skillOut .3s cubic-bezier(.7, 0, .84, 0) 2.5s forwards; }
@keyframes textIn { from { opacity: 0; transform: translate(-50%, 14px); } }
@keyframes pctOut { to { opacity: 0; transform: translate(-50%, -28px); filter: blur(6px); } }
@keyframes skillOut { to { opacity: 0; transform: translate(-50%, 22px); filter: blur(4px); } }
.intro-skill .live { width: 8px; height: 8px; border-radius: 50%; background: #45BD62; box-shadow: 0 0 0 0 rgba(69, 189, 98, .6); animation: livePulse 1.1s ease-out infinite; }
@keyframes livePulse { to { box-shadow: 0 0 0 7px rgba(69, 189, 98, 0); } }
.intro-skill span { display: inline-block; }
.intro-skill span.swap { animation: skillIn .55s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes skillIn { from { opacity: 0; transform: translateY(8px); filter: blur(4px); } }

.intro-skip { position: absolute; right: 20px; top: 20px; z-index: 2; min-height: 40px; padding: 6px 16px; border-radius: 10px; border: 1px solid rgba(254, 250, 224, .2); color: rgba(254, 250, 224, .75); font-size: .8rem; font-weight: 600; animation: textIn .4s ease .3s both, pctOut .25s ease-in 2.45s forwards; }
.intro-skip:hover { border-color: #45BD62; color: #FEFAE0; }

/* The site eases in from slightly zoomed and blurred, as the circle opens */
.intro main, .intro .topbar { animation: siteIn .8s cubic-bezier(.2, .8, .2, 1) 2.9s both; }
@keyframes siteIn { from { transform: scale(1.06); filter: blur(10px); } to { transform: none; filter: none; } }
/* Safety net: once the intro is over, the site is always sharp and unscaled, even if the animation was held up */
.intro.intro-done main, .intro.intro-done .topbar { animation: none; }

/* Skipping: open the circle right away */
.intro.intro-fast .intro-screen { animation: holeOpenFast .75s cubic-bezier(.65, 0, .25, 1) forwards, introGone 0s .8s forwards; }
.intro.intro-fast .intro-screen::before { animation: rimOn .1s linear forwards; }
.intro.intro-fast .intro-pct, .intro.intro-fast .intro-skill, .intro.intro-fast .intro-skip, .intro.intro-fast .intro-ecg { animation: fadeFast .2s ease forwards; }
.intro.intro-fast .intro-core { animation: none; }
.intro.intro-fast main, .intro.intro-fast .topbar { animation: siteInFast .8s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes holeOpenFast { from { --hole: 0px; } to { --hole: 80vmax; } }
@keyframes fadeFast { to { opacity: 0; } }
@keyframes siteInFast { from { transform: scale(1.06); filter: blur(10px); } to { transform: none; filter: none; } }

.intro-pct { font-family: var(--display); font-weight: 400; letter-spacing: .01em; }
.intro-skill, .intro-skip { font-family: var(--mono); }
.intro-skip { background: none; cursor: pointer; }
