/* ==========================================================================
   Scroll-triggered SVG animations (home page).
   main.js adds .play once when an .anim element scrolls into view. Every
   animation runs once and holds its final frame (fill-mode: forwards).
   Reduced motion: durations and delays collapse to zero, so only the final
   frame shows.
   ========================================================================== */

.anim { display: block; width: 100%; height: auto; }
.anim text { font-family: var(--font-mono); font-size: 15px; fill: var(--muted); }
.anim .w { fill: var(--text); }
.anim .v { fill: var(--copper-2); }
.anim .c { fill: var(--cyan); }
.anim .grid line { stroke: var(--line); stroke-width: 1; }
.anim .axis line, .anim .axis path { stroke: var(--line-2); stroke-width: 1.2; fill: none; }
.anim .box { fill: var(--surface-2); stroke: var(--line-2); stroke-width: 1; }

@keyframes a-draw { to { stroke-dashoffset: 0; } }
@keyframes a-on { to { opacity: 1; } }
@keyframes a-off { to { opacity: 0; } }
@keyframes a-cyan-stroke { to { stroke: var(--cyan); } }
@keyframes a-cyan-fill { to { fill: var(--cyan); } }
@keyframes a-copper-stroke { to { stroke: var(--copper); } }
@keyframes a-copper-fill { to { fill: var(--copper-2); } }

/* ----- TIA: Bode plot draws itself ----- */

.anim--tia .curve { fill: none; stroke: var(--copper); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.anim--tia .mark line { stroke: var(--cyan); stroke-width: 1; stroke-dasharray: 3 3; }
.anim--tia .mark circle { fill: var(--cyan); }
.anim--tia .f0, .anim--tia .f1 { opacity: 0; }
.anim--tia.play .curve { animation: a-draw 1.8s ease-in-out forwards; }
.anim--tia.play .f0 { animation: a-on .3s .7s forwards; }
.anim--tia.play .f1 { animation: a-on .3s 1.9s forwards; }

/* ----- PLL: VCO locks to the reference ----- */

.anim--pll .ref, .anim--pll .vco { fill: none; stroke-width: 2; stroke-linejoin: round; }
.anim--pll .ref { stroke: var(--text); }
.anim--pll .vco { stroke: var(--copper); transform-box: view-box; transform-origin: 50px 0; transform: translateX(16px) scaleX(1.07); }
.anim--pll .guide { stroke: var(--line-2); stroke-dasharray: 3 3; }
.anim--pll .lockbox { fill: none; stroke: var(--line-2); }
.anim--pll .ldot { fill: var(--line-2); }
.anim--pll .lt1 { opacity: 0; }
@keyframes a-pll-lock {
  0% { transform: translateX(16px) scaleX(1.07); }
  45% { transform: translateX(-3px) scaleX(.993); }
  70% { transform: translateX(1px) scaleX(1.002); }
  85% { transform: translateX(-.4px) scaleX(1); }
  100% { transform: translateX(0) scaleX(1); }
}
.anim--pll.play .vco { animation: a-pll-lock 2.2s ease-in-out forwards; }
.anim--pll.play .lt0 { animation: a-off .2s 2.1s forwards; }
.anim--pll.play .lt1 { animation: a-on .2s 2.1s forwards; }
.anim--pll.play .ldot { animation: a-cyan-fill .3s 2.1s forwards; }

/* ----- SRAM: 6T cell read ----- */

.anim--sram .wire line, .anim--sram .wire path { stroke: var(--text); stroke-width: 1.3; fill: none; }
.anim--sram .tr { stroke: var(--text); stroke-width: 1.3; }
.anim--sram .wl { stroke: var(--line-2); stroke-width: 1.6; }
.anim--sram .bl line, .anim--sram .blb line { stroke: var(--text); stroke-width: 1.3; }
.anim--sram .dot circle { fill: var(--text); }
.anim--sram .sw path { fill: none; stroke-width: 1.8; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.anim--sram .twl { stroke: var(--cyan); }
.anim--sram .tbl { stroke: var(--text); }
.anim--sram .tblb { stroke: var(--copper); }
.anim--sram .mk1 line, .anim--sram .mk2 line { stroke: var(--line-2); stroke-dasharray: 3 3; }
.anim--sram .br path { fill: none; stroke: var(--copper); stroke-width: 1; }
.anim--sram .mk1, .anim--sram .mk2, .anim--sram .br { opacity: 0; }
.anim--sram.play .wl { animation: a-cyan-stroke .3s .3s forwards; }
.anim--sram.play .lwl { animation: a-cyan-fill .3s .3s forwards; }
.anim--sram.play .acc { animation: a-cyan-stroke .3s .6s forwards; }
.anim--sram.play .sw path { animation: a-draw 1.4s linear .4s forwards; }
.anim--sram.play .blb line { animation: a-copper-stroke .4s 1s forwards; }
.anim--sram.play .lblb, .anim--sram.play .lblb2 { animation: a-copper-fill .4s 1s forwards; }
.anim--sram.play .mk1 { animation: a-on .2s .6s forwards; }
.anim--sram.play .mk2 { animation: a-on .2s 1.5s forwards; }
.anim--sram.play .br { animation: a-on .3s 1.7s forwards; }
.anim--sram.play .lbl, .anim--sram.play .lbl2 { animation: a-cyan-fill .3s 1.7s forwards; }

/* ----- Power devices: I-V curves trace out ----- */

.anim--pwr .dio, .anim--pwr .mos { fill: none; stroke-width: 2; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.anim--pwr .dio { stroke: var(--copper); }
.anim--pwr .mos { stroke: var(--cyan); }
.anim--pwr .pd circle { fill: var(--bg); stroke: var(--copper-2); stroke-width: 1.5; opacity: 0; }
.anim--pwr .pm circle { fill: var(--bg); stroke: var(--cyan); stroke-width: 1.5; opacity: 0; }
.anim--pwr .lab { opacity: 0; }
.anim--pwr .lm line { stroke: var(--cyan); stroke-width: 2; }
.anim--pwr.play .dio, .anim--pwr.play .mos { animation: a-draw 1.6s linear .2s forwards; }
.anim--pwr.play .pd circle, .anim--pwr.play .pm circle { animation: a-on .2s forwards; }
.anim--pwr.play .p0 { animation-delay: .25s; }
.anim--pwr.play .p1 { animation-delay: .4s; }
.anim--pwr.play .p2 { animation-delay: .6s; }
.anim--pwr.play .p3 { animation-delay: 1s; }
.anim--pwr.play .p4 { animation-delay: 1.4s; }
.anim--pwr.play .p5 { animation-delay: 1.8s; }
.anim--pwr.play .lab { animation: a-on .3s 1.9s forwards; }

/* ----- Ellipsometer: beam, then band edge vs. doping ----- */

.anim--ellip .film { fill: var(--copper); opacity: .85; }
.anim--ellip .sub { fill: var(--line-2); }
.anim--ellip .b1, .anim--ellip .b2, .anim--ellip .b3, .anim--ellip .b4 { fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.anim--ellip .b1 { stroke: var(--text); }
.anim--ellip .b2 { stroke: var(--cyan); }
.anim--ellip .b3 { stroke: var(--copper); }
.anim--ellip .b4 { stroke: var(--copper); stroke-width: 1.2; opacity: .7; }
.anim--ellip .psi, .anim--ellip .d2, .anim--ellip .d3 { opacity: 0; }
.anim--ellip .egmk { fill: var(--copper-2); }
@keyframes a-eg { to { transform: translateX(110.4px); } }
.anim--ellip.play .b1 { animation: a-draw .5s linear forwards; }
.anim--ellip.play .b2 { animation: a-draw .25s linear .5s forwards; }
.anim--ellip.play .b3 { animation: a-draw .5s linear .5s forwards; }
.anim--ellip.play .b4 { animation: a-draw .5s linear .75s forwards; }
.anim--ellip.play .psi { animation: a-on .3s 1.1s forwards; }
.anim--ellip.play .d1 { animation: a-off .1s 2s forwards; }
.anim--ellip.play .d2 { animation: a-on .1s 2s forwards, a-off .1s 2.8s forwards; }
.anim--ellip.play .d3 { animation: a-on .1s 2.8s forwards; }
.anim--ellip.play .egmk { animation: a-eg 2.4s linear 1.2s forwards; }

/* ----- Mirror: sine drive, resonant pivot, beam sweep ----- */

.anim--mirror .sine { fill: none; stroke: var(--cyan); stroke-width: 1.8; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.anim--mirror .bin { stroke: var(--text); stroke-width: 1.4; }
.anim--mirror .beam { stroke: var(--copper); stroke-width: 1.6; transform-box: view-box; transform-origin: 190px 180px; }
.anim--mirror .mir { stroke: var(--text); stroke-width: 3; stroke-linecap: round; transform-box: view-box; transform-origin: 190px 180px; }
.anim--mirror .piv { fill: var(--copper-2); }
.anim--mirror .t { fill: var(--line-2); }
@keyframes a-mir {
  0% { transform: rotate(0deg); animation-timing-function: ease-in-out; }
  20% { transform: rotate(-14deg); animation-timing-function: linear; }
  70% { transform: rotate(14deg); animation-timing-function: ease-in-out; }
  100% { transform: rotate(0deg); }
}
@keyframes a-beam {
  0% { transform: rotate(0deg); animation-timing-function: ease-in-out; }
  20% { transform: rotate(-28deg); animation-timing-function: linear; }
  70% { transform: rotate(28deg); animation-timing-function: ease-in-out; }
  100% { transform: rotate(0deg); }
}
.anim--mirror.play .sine { animation: a-draw 2.4s linear forwards; }
.anim--mirror.play .mir { animation: a-mir 2.4s forwards; }
.anim--mirror.play .beam { animation: a-beam 2.4s forwards; }
.anim--mirror.play .t { animation: a-copper-fill .15s forwards; }
.anim--mirror.play .t0 { animation-delay: .48s; }
.anim--mirror.play .t1 { animation-delay: .61s; }
.anim--mirror.play .t2 { animation-delay: .76s; }
.anim--mirror.play .t3 { animation-delay: .92s; }
.anim--mirror.play .t4 { animation-delay: 1.08s; }
.anim--mirror.play .t5 { animation-delay: 1.24s; }
.anim--mirror.play .t6 { animation-delay: 1.4s; }
.anim--mirror.play .t7 { animation-delay: 1.55s; }
.anim--mirror.play .t8 { animation-delay: 1.68s; }

/* ----- FPGA block diagram (static) ----- */

.anim--fpga text { fill: var(--text); }
.anim--fpga .n { fill: var(--muted); }
.anim--fpga .blk { fill: var(--surface-2); stroke: var(--line-2); }
.anim--fpga .dash { stroke-dasharray: 4 3; }
.anim--fpga .fpga { fill: none; stroke: var(--copper); stroke-width: 1; stroke-dasharray: 5 4; opacity: .7; }
.anim--fpga .arr path { fill: none; stroke: var(--muted); stroke-width: 1.4; }
.anim--fpga .ah path { fill: var(--muted); }

/* ----- Hero: ALD cycle (substrate, DEZ pulse, purge, H2O pulse, purge; one monolayer per cycle) ----- */

.ald-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.ald-film { position: absolute; left: 0; right: 0; bottom: 0; display: block; width: 100%; height: 58px; }
.ald-film .sub { fill: var(--line-2); }
.ald-film .l { fill: var(--copper); transform-box: fill-box; transform-origin: bottom; transform: scaleY(0); }
.ald-film .l:nth-of-type(odd) { fill: var(--copper-2); }
.ald-chamber { position: absolute; display: block; pointer-events: none; }
.ald-chamber--desk { left: 62%; top: 0; width: 38%; height: calc(100% - 58px); }
.ald-chamber--phone { display: none; }
.ald-chamber .mol { opacity: 0; }
/* Glyph colors are set on the sprite: <use> clones are styled as the originals are. */
.ald-sprite .dez-c { fill: var(--copper-2); }
.ald-sprite .dez-l { stroke: var(--muted); stroke-width: 2; }
.ald-sprite .dez-e { fill: var(--muted); }
.ald-sprite .h2o-o { fill: var(--cyan); }
.ald-sprite .h2o-h { fill: var(--text); }
@keyframes a-fall {
  0% { transform: translateY(-500px); opacity: 0; }
  4% { opacity: 1; }
  30% { transform: translateY(0); opacity: 1; }
  38%, 100% { transform: translateY(0); opacity: 0; }
}
@keyframes a-fall-s {
  0% { transform: translateY(-190px); opacity: 0; }
  4% { opacity: 1; }
  30% { transform: translateY(0); opacity: 1; }
  38%, 100% { transform: translateY(0); opacity: 0; }
}
@keyframes a-grow { to { transform: scaleY(1); } }
@keyframes a-s1 { 0%, 37.9% { opacity: 1; } 38%, 100% { opacity: 0; } }
@keyframes a-s2 { 0%, 37.9% { opacity: 0; } 38%, 49.9% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes a-s3 { 0%, 49.9% { opacity: 0; } 50%, 87.9% { opacity: 1; } 88%, 100% { opacity: 0; } }
@keyframes a-s4 { 0%, 87.9% { opacity: 0; } 88%, 99.9% { opacity: 1; } 100% { opacity: 0; } }
.anim--ald.play .ald-dez .mol { animation: a-fall 1.5s linear 6 forwards; animation-delay: calc(.3s + var(--d, 0s)); }
.anim--ald.play .ald-h2o .mol { animation: a-fall 1.5s linear 6 forwards; animation-delay: calc(1.05s + var(--d, 0s)); }
.anim--ald.play .ald-chamber--phone .mol { animation-name: a-fall-s; }
.anim--ald.play .ald-film .l { animation: a-grow .3s ease-out forwards; }
.anim--ald.play .ald-film .l1 { animation-delay: 1.85s; }
.anim--ald.play .ald-film .l2 { animation-delay: 3.35s; }
.anim--ald.play .ald-film .l3 { animation-delay: 4.85s; }
.anim--ald.play .ald-film .l4 { animation-delay: 6.35s; }
.anim--ald.play .ald-film .l5 { animation-delay: 7.85s; }
.anim--ald.play .ald-film .l6 { animation-delay: 9.35s; }

.ald-readout { position: relative; margin-top: 26px; padding-bottom: 74px; }
.ald-chip {
  display: inline-flex; align-items: baseline; gap: 10px;
  padding: 6px 12px; border: 1px solid var(--line); border-radius: 6px;
  background: rgba(17, 22, 29, .88);
  font-family: var(--font-mono); font-size: var(--fs-small); color: var(--muted);
}
.ald-k { color: var(--text); }
.ald-steps { position: relative; display: inline-block; width: 13ch; height: 1.2em; }
.ald-s { position: absolute; left: 0; top: 0; opacity: 0; white-space: nowrap; }
.ald-thick { color: var(--copper-2); }
.anim--ald.play .ald-s1 { animation: a-s1 1.5s linear .3s 6 forwards; }
.anim--ald.play .ald-s2 { animation: a-s2 1.5s linear .3s 6 forwards; }
.anim--ald.play .ald-s3 { animation: a-s3 1.5s linear .3s 6 forwards; }
.anim--ald.play .ald-s4 { animation: a-s4 1.5s linear .3s 6 forwards; }
.anim--ald.play .ald-s5 { animation: a-on .3s 9.35s forwards; }

@media (max-width: 820px) {
  .ald-chamber--desk { display: none; }
  .ald-chamber--phone { display: block; left: 0; bottom: 58px; width: 100%; height: 170px; }
  .ald-readout { margin-top: 118px; padding-bottom: 72px; }
}

/* ----- Reduced motion: jump straight to the final frame ----- */

@media (prefers-reduced-motion: reduce) {
  .anim.play, .anim.play * { animation-duration: 1ms !important; animation-delay: 0ms !important; }
}
