/* ==========================================================
   Print animation v2 (2026-10-10), on the home page's 3D printing section since 2026-10-19.
   Shared by hero-print-v2.html and scroll-preview.html.
   CSS and SVG only, no JavaScript. v1 is hero-print-preview.html.

   What v2 adds over v1, from Evan's notes ("more life", "the drive
   needs to visually extend deeper into the drive holder"):
   - Drives seat 38% of their height deep, like the real 21.6 mm
     slot on a 57 mm T7. The buried part shows through the holder
     like translucent filament, inside a visible slot pocket.
   - A dark gap either side of each drive at the slot mouth, a
     front lip that covers the drive, a shadow where it enters.
   - Print: progress bar, spinning hotend fan, blinking head light,
     a bright trail of fresh filament under the nozzle.
   - Loading: status reads Loading with a drive counter; each drive
     accelerates in, bounces once, the bed gives a small thud, a
     flash marks the seat, and the light blinks twice then holds.
   - Ready: one glow around the part, then idle life forever:
     drive lights flicker like disk activity at uneven rates, a
     glint sweeps across the drives every 7 s, the fan keeps going.
   - Hover (mouse only): the drives lift partway out in a wave so
     you can see how deep they sit, and drop back on mouse-out.

   Timeline (s): print 0.4-5.8 · park 5.8-6.4 · Loading 5.9 ·
   drives land 6.73 / 6.93 / 7.13 / 7.33 · Ready 7.6 · idle from 8.4
   ========================================================== */

@property --layer { syntax: "<integer>"; inherits: false; initial-value: 0; }
@property --drives { syntax: "<integer>"; inherits: false; initial-value: 0; }


.hero__side { display: grid; gap: 18px; }

.printer { overflow: hidden; background: linear-gradient(180deg, var(--raise-2), var(--raise)); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.printer__bar, .printer__cap { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 20px; font-family: var(--mono); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.printer__bar { position: relative; border-bottom: 1px solid var(--line); }
.printer__bar::after { content: ""; position: absolute; left: 0; bottom: -1px; width: 100%; height: 2px; background: var(--accent); transform-origin: 0 50%; animation: pr-progress 5.4s steps(36, end) 0.4s both, pr-step-back 0.6s ease 7.6s both; }
.printer__cap { border-top: 1px solid var(--line); }

.printer__state, .printer__count { display: grid; }
.printer__state { color: var(--accent); }
.printer__state > span, .printer__count > span { grid-area: 1 / 1; display: inline-flex; align-items: center; gap: 9px; }
.printer__count > span { justify-content: flex-end; }
.printer__state > span::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.printer__state .is-printing { animation: pr-fade-out 0.25s 5.9s both; }
.printer__state .is-printing::before { animation: pr-pulse 0.9s ease-in-out 0s 6 alternate both; }
.printer__state .is-loading { animation: pr-window 1.7s linear 5.9s both; }
.printer__state .is-loading::before { animation: pr-pulse 0.3s ease-in-out infinite alternate; }
.printer__state .is-ready { animation: pr-fade-in 0.3s 7.6s both; }
.printer__state .is-ready::before { animation: pr-breathe 2.4s ease-in-out 8.4s infinite; }
.printer__layer { counter-reset: layer var(--layer); animation: pr-count 5.4s steps(36, end) 0.4s both, pr-fade-out 0.25s 5.9s both; }
.printer__layer::after { content: "Layer " counter(layer) " / 36"; }
.printer__drives { counter-reset: drives var(--drives); animation: pr-count-drives 0.8s steps(4, end) 6.532s both, pr-fade-in 0.25s 5.9s both; }
.printer__drives::after { content: "Drives " counter(drives) " / 4"; }

.printer__scene { display: block; width: 100%; height: auto; }

/* Scene colours. The holder prints in the site accent; drives keep their real charcoal in both themes. */
.pr-rail { stroke: var(--line-strong); stroke-width: 2; stroke-linecap: round; }
.pr-rod { stroke: var(--line); stroke-width: 2; }
.pr-plate { fill: var(--raise-2); stroke: var(--line-strong); stroke-width: 1; }
.pr-carriage { fill: var(--raise-2); stroke: var(--line-strong); stroke-width: 1; }
.pr-block { fill: var(--line); stroke: var(--line-strong); stroke-width: 1; }
.pr-fan-ring { fill: var(--raise-2); stroke: var(--line-strong); stroke-width: 1; }
.pr-fan-blades { stroke: var(--line-strong); stroke-width: 1.6; stroke-linecap: round; fill: none; }
.pr-tip { fill: var(--line-strong); }
.pr-led-head { fill: var(--accent); }
.pl-fill { fill: var(--accent); fill-opacity: 0.16; }
.pl-line { fill: var(--accent); fill-opacity: 0.34; }
.pr-top { fill: var(--accent); fill-opacity: 0.34; stroke: var(--accent); stroke-width: 1; }
.pr-slot { fill: #000; fill-opacity: 0.62; }
.pr-face-bg { fill: var(--raise); }
.pr-pocket { fill: #000; fill-opacity: 0.14; stroke: var(--accent); stroke-opacity: 0.5; stroke-width: 1; }
.pr-face { fill: url(#pr-layers); stroke: var(--accent); stroke-width: 1.5; }
.pr-lip { fill: var(--accent); fill-opacity: 0.5; }
.pr-drive { fill: #1f2226; stroke: #4a5059; stroke-width: 1; }
.pr-ghost-r { fill: #1f2226; fill-opacity: 0.78; stroke: #78808b; stroke-width: 1; stroke-dasharray: 3 2.5; }
@media (prefers-color-scheme: light) { .pr-ghost-r { fill-opacity: 0.5; } }
.pr-port { fill: #0b0c0e; }
.pr-led-off { fill: #4a4f57; }
.pr-led-on { fill: var(--accent); filter: drop-shadow(0 0 3px var(--accent)); }
.pr-ao { fill: url(#pr-ao); }
.pr-glow { stroke: var(--accent); stroke-width: 1.5; stroke-opacity: 0.45; }
.pr-trail { fill: var(--accent); filter: drop-shadow(0 0 4px var(--accent)); }
.pr-tip-glow { fill: var(--accent); filter: drop-shadow(0 0 5px var(--accent)); }
.pr-seat { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; filter: drop-shadow(0 0 4px var(--accent)); }
.pr-done { fill: none; stroke: var(--accent); stroke-width: 2; filter: drop-shadow(0 0 6px var(--accent)); }
.pr-glint { fill: url(#pr-glint-g); }

/* Print */
.pr-bed { animation: pr-bed 5.4s steps(36, end) 0.4s both; }
.pr-reveal { transform-box: fill-box; transform-origin: 50% 100%; animation: pr-reveal 5.4s steps(36, end) 0.4s both; }
.pr-head { animation: pr-park 0.6s cubic-bezier(0.45, 0, 0.2, 1) 5.8s both; }
.pr-sweep { animation: pr-sweep 0.15s linear 0.4s 36 alternate both; }
.pr-glow, .pr-trail, .pr-tip-glow { animation: pr-glow-life 5.8s linear both; }
.pr-led-head { animation: pr-pulse 0.54s ease-in-out 0.4s 10 alternate both; }
.pr-fan-spin { animation: pr-spin 0.4s linear infinite; }

/* Loading: delays come from each drive's --i (0 to 3), 0.2 s apart. */
.pr-drive-g { animation: pr-drop 0.6s calc(6.3s + var(--i) * 0.2s) both; }
.pr-led-on { animation: pr-power 0.6s calc(6.93s + var(--i) * 0.2s) both; }
.pr-ao { animation: pr-fade-in 0.25s calc(6.68s + var(--i) * 0.2s) both; }
.pr-seat { animation: pr-flash 0.45s ease-out calc(6.71s + var(--i) * 0.2s) both; }
.pr-thud { animation: pr-thud 1s linear 6.652s both; }

/* Ready, then idle */
.pr-done { animation: pr-flash 0.9s ease-out 7.6s both; }
.pr-frame { animation: pr-step-back 0.6s ease 7.6s both; }
.pr-led-act { animation: pr-activity calc(1.9s + var(--i) * 0.7s) linear calc(8.4s + var(--i) * 0.37s) infinite; }
.pr-glint { transform: translateX(100px) skewX(-18deg); animation: pr-glint 7s ease-in-out 8.4s infinite both; }

/* Hover: lift the drives partway out so their depth shows. Mouse only. */
.pr-lift { transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--i) * 55ms); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .printer:hover .pr-lift { transform: translateY(-20px); }
}

@keyframes pr-count { from { --layer: 0; } to { --layer: 36; } }
@keyframes pr-count-drives { from { --drives: 0; } to { --drives: 4; } }
@keyframes pr-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes pr-bed { from { transform: translateY(-72px); } to { transform: translateY(0); } }
@keyframes pr-reveal { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes pr-sweep { from { transform: translateX(150px); } to { transform: translateX(310px); } }
@keyframes pr-park { from { transform: translateX(0); } to { transform: translateX(250px); } }
@keyframes pr-spin { to { transform: rotate(360deg); } }
@keyframes pr-glow-life { 0%, 6.9% { opacity: 0; } 8.5% { opacity: 1; } 98.5% { opacity: 1; } 100% { opacity: 0; } }
@keyframes pr-drop {
  0% { transform: translateY(-190px); opacity: 0; animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.55); }
  15% { opacity: 1; }
  72% { transform: translateY(0); animation-timing-function: cubic-bezier(0.2, 0.6, 0.4, 1); }
  84% { transform: translateY(-6px); animation-timing-function: cubic-bezier(0.6, 0, 0.8, 0.4); }
  100% { transform: translateY(0); opacity: 1; }
}
@keyframes pr-thud {
  0%, 14%, 34%, 54%, 74%, 100% { transform: translateY(0); }
  8%, 28%, 48%, 68% { transform: translateY(1.5px); }
}
@keyframes pr-power { 0% { opacity: 0; } 15% { opacity: 1; } 32% { opacity: 0.1; } 50% { opacity: 1; } 66% { opacity: 0.1; } 82%, 100% { opacity: 1; } }
@keyframes pr-activity { 0%, 100% { opacity: 1; } 4% { opacity: 0.15; } 8% { opacity: 1; } 11% { opacity: 0.25; } 14% { opacity: 1; } 58% { opacity: 1; } 61% { opacity: 0.2; } 64% { opacity: 1; } }
@keyframes pr-glint { 0% { transform: translateX(100px) skewX(-18deg); } 22%, 100% { transform: translateX(380px) skewX(-18deg); } }
@keyframes pr-flash { 0% { opacity: 0; } 25% { opacity: 1; } 100% { opacity: 0; } }
@keyframes pr-window { 0% { opacity: 0; } 12% { opacity: 1; } 88% { opacity: 1; } 100% { opacity: 0; } }
@keyframes pr-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pr-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes pr-pulse { from { opacity: 1; } to { opacity: 0.25; } }
@keyframes pr-breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@keyframes pr-step-back { from { opacity: 1; } to { opacity: 0.35; } }

/* Reduced motion: no movement, the finished state only, no idle loops, no hover lift. */
@media (prefers-reduced-motion: reduce) {
  .printer *, .printer *::before, .printer *::after { animation-duration: 1ms !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; }
  .pr-sweep { animation: none !important; transform: translateX(150px); }
  .pr-glint, .pr-fan-spin, .pr-led-act, .printer__state .is-ready::before { animation: none !important; }
  .pr-lift { transition: none !important; }
}
@media (max-width: 900px) { .hero__side { max-width: 520px; } }

/* On the site (2026-10-19) the printer sits below the fold, so it waits until it is on screen:
   index.html adds .js to <html> and .is-live to the printer when a third of it is visible.
   Without JavaScript it simply plays on load, as the preview did. */
.js .printer:not(.is-live), .js .printer:not(.is-live) *, .js .printer:not(.is-live)::before, .js .printer:not(.is-live)::after,
.js .printer:not(.is-live) *::before, .js .printer:not(.is-live) *::after { animation-play-state: paused !important; }
