/* Cartesian School — homepage-only styles (index.html, /projects/).
   Layered on top of theory.css's design tokens (shadows/surfaces/motion
   live there now, shared with practice.css). This file adds the larger,
   more visual components this page needs: hero, section backgrounds,
   course journey, practice catalog, project cards, reference board. */

/* ==========================================================================
   HERO
   ========================================================================== */
.home-hero {
  position: relative; overflow: hidden; isolation: isolate;
  background:
    radial-gradient(ellipse 820px 620px at 9% 0%, rgba(91,36,249,.3), transparent 67%),
    radial-gradient(ellipse 720px 540px at 88% 42%, rgba(24,93,250,.14), transparent 68%),
    linear-gradient(118deg, var(--navy-900) 0%, var(--navy-950) 72%);
  color: #fff;
  padding: clamp(68px, 7vw, 96px) 24px clamp(64px, 6vw, 86px);
  text-align: left;
}
/* A sparse point field anchors the coordinate plane without reading as stars. */
.home-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    radial-gradient(1.5px 1.5px at 7% 78%, rgba(143,183,254,.42) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 33% 17%, rgba(185,160,252,.3) 50%, transparent 51%),
    radial-gradient(1px 1px at 71% 13%, rgba(255,255,255,.3) 50%, transparent 51%),
    radial-gradient(1px 1px at 84% 79%, rgba(143,183,254,.3) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 96% 31%, rgba(185,160,252,.3) 50%, transparent 51%);
  background-repeat: no-repeat;
}

.home-hero__inner {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: minmax(0, .96fr) minmax(520px, 1.04fr);
  align-items: center; gap: clamp(38px, 4vw, 72px);
  width: min(1320px, 100%); margin: 0 auto;
}
.home-hero__content { min-width: 0; }
.home-hero .kicker {
  display: flex; align-items: center; gap: 11px;
  font-family: 'JetBrains Mono', monospace; font-size: 13px; font-weight: 500;
  font-variant-ligatures: none; letter-spacing: .085em; line-height: 1.35;
  color: var(--blue-300); text-transform: uppercase; margin-bottom: 23px;
  animation: hero-enter .62s .1s var(--ease-standard) both;
}
.home-hero .kicker img {
  display: block; flex: 0 0 auto; width: 25px; height: 30px; object-fit: contain;
  filter: drop-shadow(0 5px 12px rgba(24,93,250,.2));
  animation: hero-logo-enter .62s .1s var(--ease-standard) both;
}
.home-hero h1 {
  color: #fff; font-size: clamp(44px, 4.15vw, 64px); line-height: 1.08;
  letter-spacing: -.035em; max-width: 650px; margin: 0 0 25px;
  text-wrap: balance;
  animation: hero-enter .72s .2s var(--ease-standard) both;
}
.home-hero p {
  color: #c6c6d5; font-size: 18px; line-height: 1.65;
  max-width: 610px; margin: 0 0 36px;
  animation: hero-enter .72s .34s var(--ease-standard) both;
}
.home-cta {
  display: flex; gap: 14px; flex-wrap: wrap; align-items: center;
  animation: hero-enter .72s .47s var(--ease-standard) both;
}
.home-hero .btn-ghost:hover { transform: translateY(-1px); }

/* One shared computational plane: grid, Python runtime, four course domains. */
.hero-system {
  --hero-back-x: 0px;
  --hero-back-y: 0px;
  --hero-plane-x: 0px;
  --hero-plane-y: 0px;
  position: relative; width: 100%; aspect-ratio: 620 / 520;
  min-width: 0; isolation: isolate;
}
.hero-system::after {
  content: ""; position: absolute; z-index: -2; inset: 15% 8% 7% 16%;
  background: radial-gradient(ellipse, rgba(91,36,249,.15), transparent 69%);
  filter: blur(26px); pointer-events: none;
}
.hero-system__grid {
  position: absolute; z-index: -3; inset: -8px;
  background-image:
    repeating-linear-gradient(90deg, rgba(143,183,254,.065) 0 1px, transparent 1px 36px),
    repeating-linear-gradient(0deg, rgba(143,183,254,.065) 0 1px, transparent 1px 36px);
  -webkit-mask-image: radial-gradient(ellipse 70% 75% at 58% 52%, #000 22%, transparent 80%);
  mask-image: radial-gradient(ellipse 70% 75% at 58% 52%, #000 22%, transparent 80%);
  transform: translate3d(0, 0, 0);
  animation: hero-grid-drift 24s ease-in-out infinite alternate;
}
.hero-system__backdrop {
  position: absolute; z-index: -2; inset: 0; pointer-events: none;
  transform: translate3d(var(--hero-back-x), var(--hero-back-y), 0);
  transition: transform 180ms var(--ease-out);
}
.hero-system__prompt {
  position: absolute; right: 1%; top: 27%;
  font-family: 'JetBrains Mono', monospace; font-size: clamp(112px, 10vw, 160px);
  font-weight: 500; line-height: 1; letter-spacing: -.14em;
  color: rgba(143,183,254,.055); text-shadow: 0 0 40px rgba(24,93,250,.08);
  animation: hero-prompt-float 16s ease-in-out infinite alternate;
}
.hero-token {
  position: absolute; font-family: 'JetBrains Mono', monospace; font-size: 11px;
  color: rgba(185,160,252,.25); letter-spacing: .04em;
}
.hero-token--def { left: 2%; top: 47%; }
.hero-token--py { right: 4%; bottom: 6%; }
.hero-token--range { left: 33%; top: 3%; }
.hero-token--lambda { right: 17%; top: 4%; }

.hero-system__plane {
  position: absolute; z-index: 1; inset: 0;
  transform: translate3d(var(--hero-plane-x), var(--hero-plane-y), 0);
  transition: transform 180ms var(--ease-out);
}
.hero-connectors { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.hero-connectors--mobile { display: none; }
.hero-axes { fill: none; stroke: rgba(143,183,254,.2); stroke-width: 1; vector-effect: non-scaling-stroke; }
.hero-axes text {
  fill: rgba(143,183,254,.5); stroke: none;
  font: 12px 'JetBrains Mono', monospace;
}
.hero-connector-lines {
  fill: none; stroke: rgba(143,183,254,.32); stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
}
.hero-connector-signals { fill: none; stroke: var(--blue-300); stroke-width: 2; vector-effect: non-scaling-stroke; }
.hero-signal {
  stroke-dasharray: 4 320; stroke-dashoffset: 320;
  filter: drop-shadow(0 0 4px rgba(143,183,254,.75));
  animation: hero-signal-flow 8s linear infinite;
}
.hero-signal--graph { animation-duration: 9.5s; animation-delay: -3.2s; }
.hero-signal--app { animation-duration: 10.5s; animation-delay: -6.4s; }
.hero-signal--game { animation-duration: 11.5s; animation-delay: -8.1s; }
.hero-route-nodes circle {
  fill: var(--navy-950); stroke: var(--blue-300); stroke-width: 1.5;
  vector-effect: non-scaling-stroke; transform-box: fill-box; transform-origin: center;
  animation: hero-node-pulse 4.8s ease-in-out infinite;
}
.hero-route-nodes circle:nth-child(2) { animation-delay: -1.2s; }
.hero-route-nodes circle:nth-child(3) { animation-delay: -2.4s; }
.hero-route-nodes circle:nth-child(4) { animation-delay: -3.6s; }

.hero-core {
  position: absolute; z-index: 5; left: 50%; top: 46.9%;
  width: 112px; height: 112px; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  border: 1px solid rgba(143,183,254,.42); border-radius: 50%;
  background: radial-gradient(circle at 42% 32%, rgba(21,16,74,.98), rgba(8,1,28,.96) 72%);
  box-shadow: 0 0 0 8px rgba(24,93,250,.035), 0 18px 55px rgba(0,0,0,.4), 0 0 38px rgba(24,93,250,.09);
  animation: hero-core-enter .75s .48s var(--ease-standard) both;
}
.hero-core__orbit {
  position: absolute; inset: -10px; border: 1px dashed rgba(185,160,252,.25); border-radius: 50%;
  animation: hero-orbit-pulse 5.4s ease-in-out infinite;
}
.hero-core__mark { height: 42px; display: flex; align-items: center; }
.hero-core__mark img { display: block; width: 33px; height: 40px; object-fit: contain; }
.hero-core__name {
  margin-top: 1px; color: #fff; font: 600 11px/1.2 'Sora', sans-serif;
  letter-spacing: .08em; text-transform: uppercase;
}
.hero-core__runtime { margin-top: 3px; color: var(--blue-300); font: 8px/1.2 'JetBrains Mono', monospace; }

.hero-module {
  position: absolute; z-index: 3; overflow: hidden;
  color: #e9e9f2; border: 1px solid rgba(143,183,254,.17); border-radius: 10px;
  background: linear-gradient(145deg, rgba(21,16,74,.9), rgba(8,1,28,.92));
  box-shadow: 0 18px 45px rgba(0,0,0,.25), inset 0 1px rgba(255,255,255,.025);
  transition: border-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
.hero-module:hover {
  border-color: rgba(143,183,254,.34);
  box-shadow: 0 20px 50px rgba(0,0,0,.3), 0 0 24px rgba(24,93,250,.07), inset 0 1px rgba(255,255,255,.04);
}
.hero-module__head {
  height: 30px; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 0 11px; border-bottom: 1px solid rgba(143,183,254,.12);
  color: rgba(198,198,213,.58); font: 8px/1 'JetBrains Mono', monospace; letter-spacing: .02em;
}
.hero-module__label {
  display: inline-flex; align-items: center; gap: 7px;
  color: #d9d9e7; font-weight: 600; font-size: 9px; letter-spacing: .12em; text-transform: uppercase;
}
.hero-module__label i {
  width: 6px; height: 6px; display: block; border-radius: 50%;
  background: var(--blue-300); box-shadow: 0 0 8px rgba(143,183,254,.55);
}
.hero-module--code {
  left: 57%; top: 4%; width: 41.5%; height: 29%;
  animation: hero-module-enter .68s .62s var(--ease-standard) both;
}
.hero-module--graph {
  left: 4%; top: 8%; width: 38%; height: 29%;
  animation: hero-module-enter .68s .55s var(--ease-standard) both;
}
.hero-module--app {
  right: 2%; top: 66%; width: 39%; height: 25%;
  animation: hero-module-enter .68s .73s var(--ease-standard) both;
}
.hero-module--game {
  left: 6%; top: 68%; width: 38%; height: 24%;
  animation: hero-module-enter .68s .8s var(--ease-standard) both;
}

.hero-module--code pre {
  margin: 0; padding: 10px 12px; overflow: hidden;
  color: #e2e2ee; background: transparent;
  font: 9.3px/1.55 'JetBrains Mono', monospace; white-space: pre;
}
.syntax-prompt { color: var(--blue-300); }
.syntax-keyword { color: var(--violet-300); }
.syntax-result { color: #f7d65b; }
.hero-code-cursor { color: var(--blue-300); animation: hero-cursor 920ms steps(1, end) infinite; }

.hero-plot { display: block; width: 100%; height: calc(100% - 30px); padding: 5px 8px 6px; }
.hero-plot__grid { fill: none; stroke: rgba(143,183,254,.075); stroke-width: 1; }
.hero-plot__axis { fill: none; stroke: rgba(143,183,254,.32); stroke-width: 1; }
.hero-plot__curve {
  fill: none; stroke: #8fb7fe; stroke-width: 2; stroke-linecap: round;
  filter: drop-shadow(0 0 4px rgba(24,93,250,.4));
  stroke-dasharray: 260; stroke-dashoffset: 260;
  animation: hero-graph-draw 1.8s .82s var(--ease-out) forwards;
}
.hero-plot__vector { fill: none; stroke: rgba(185,160,252,.8); stroke-width: 1.3; }
.hero-plot__point { fill: var(--navy-950); stroke: var(--violet-300); stroke-width: 1.5; }
.hero-plot__point--b { stroke: var(--blue-300); }

.hero-app-status { display: flex; align-items: center; gap: 4px; }
.hero-app-status b {
  width: 5px; height: 5px; border-radius: 50%; background: #5ee28b;
  box-shadow: 0 0 8px rgba(94,226,139,.4); animation: hero-status 4s ease-in-out infinite;
}
.hero-app-ui { display: grid; grid-template-columns: 1.2fr .8fr; gap: 9px; height: calc(100% - 30px); padding: 10px; }
.hero-app-ui__chart {
  height: 100%; display: flex; align-items: flex-end; gap: 5px; padding: 5px 6px;
  border-left: 1px solid rgba(143,183,254,.15); border-bottom: 1px solid rgba(143,183,254,.15);
}
.hero-app-ui__chart span {
  flex: 1; height: 100%; max-height: 46px; border-radius: 2px 2px 0 0;
  background: linear-gradient(to top, rgba(91,36,249,.55), rgba(143,183,254,.8));
  transform: scaleY(var(--bar)); transform-origin: bottom;
}
.hero-app-ui__panel { display: flex; flex-direction: column; gap: 6px; justify-content: center; }
.hero-app-ui__panel span { display: block; width: 100%; height: 4px; border-radius: 3px; background: rgba(198,198,213,.14); }
.hero-app-ui__panel span:nth-child(2) { width: 72%; }
.hero-app-ui__panel b {
  display: block; padding: 4px 5px; border: 1px solid rgba(143,183,254,.22); border-radius: 4px;
  color: var(--blue-300); font: 7px/1 'JetBrains Mono', monospace; text-align: center;
}

.hero-game { display: block; width: 100%; height: calc(100% - 30px); padding: 5px 8px; }
.hero-game__trajectory { fill: none; stroke: rgba(143,183,254,.18); stroke-width: 1; stroke-dasharray: 4 4; }
.hero-game__target { fill: none; stroke: var(--violet-300); stroke-width: 1; }
.hero-game__target circle:last-child { fill: var(--violet-300); }
.hero-game__sprite {
  fill: rgba(143,183,254,.9); stroke: var(--blue-300); stroke-width: 1;
  filter: drop-shadow(0 0 4px rgba(24,93,250,.45));
  animation: hero-game-shift 7s ease-in-out infinite;
}
.hero-game__collision { fill: rgba(91,36,249,.16); stroke: rgba(185,160,252,.52); stroke-width: 1; }

@keyframes hero-enter {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}
@keyframes hero-logo-enter {
  from { opacity: 0; transform: scale(.94) rotate(-2deg); }
  to { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes hero-core-enter {
  from { opacity: 0; transform: translate(-50%, -44%) scale(.94); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes hero-module-enter {
  from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.98); }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes hero-grid-drift {
  from { transform: translate3d(-3px, -2px, 0); }
  to { transform: translate3d(3px, 4px, 0); }
}
@keyframes hero-prompt-float {
  from { transform: translate3d(-2px, -4px, 0) scale(1); opacity: .82; }
  to { transform: translate3d(3px, 5px, 0) scale(1.012); opacity: 1; }
}
@keyframes hero-signal-flow { to { stroke-dashoffset: -8; } }
@keyframes hero-node-pulse {
  0%, 78%, 100% { opacity: .55; transform: scale(1); }
  86% { opacity: 1; transform: scale(1.09); }
}
@keyframes hero-orbit-pulse {
  0%, 100% { opacity: .52; transform: scale(.99); }
  50% { opacity: .88; transform: scale(1.025); }
}
@keyframes hero-cursor { 0%, 48% { opacity: 1; } 49%, 100% { opacity: 0; } }
@keyframes hero-graph-draw { to { stroke-dashoffset: 0; } }
@keyframes hero-status { 0%, 70%, 100% { opacity: .45; } 78%, 90% { opacity: 1; } }
@keyframes hero-game-shift { 0%, 72%, 100% { transform: translate3d(0, 0, 0); } 82% { transform: translate3d(9px, 0, 0); } }

.home-hero.is-paused .hero-system *,
.home-hero.is-paused .hero-system *::before,
.home-hero.is-paused .hero-system *::after {
  animation-play-state: paused !important;
}

/* ==========================================================================
   SECTION SHELL — every major section gets its own visual identity
   ========================================================================== */
.home-section { position: relative; z-index: 0; max-width: var(--content-width); margin: 0 auto; padding: 84px 24px; overflow: hidden; }
.home-section h2 { font-size: 32px; margin-bottom: 8px; text-wrap: balance; }
.home-section .sub { color: var(--color-text-muted); margin-bottom: 44px; max-width: 640px; font-size: 17px; line-height: 1.6; }
.home-section .kicker-label { font-family: 'JetBrains Mono', monospace; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--color-brand-blue); margin-bottom: 12px; }

.panel-canvas { background: var(--surface-0); }
.panel-surface { background: var(--surface-1); }
.panel-inverse { background: var(--surface-inverse-1); color: var(--color-text-inverse); }
.panel-inverse h2, .panel-inverse .kicker-label { color: #fff; }
.panel-inverse .sub { color: var(--gray-400); }

/* Section-specific ambient backgrounds — very low-opacity, non-interactive,
   painted behind content (z-index:-1 inside the section's own stacking
   context created by position:relative + z-index:0 above). Restrained by
   design: readability first, atmosphere second. */
.home-section::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; }

#glavy::before {
  background:
    radial-gradient(900px 520px at 50% 4%, rgba(24,93,250,.055), transparent 62%),
    radial-gradient(760px 480px at 94% 86%, rgba(91,36,249,.045), transparent 60%),
    repeating-linear-gradient(90deg, rgba(13,2,48,.022) 0 1px, transparent 1px 68px),
    repeating-linear-gradient(0deg, rgba(13,2,48,.018) 0 1px, transparent 1px 68px);
}
#praktika::before {
  background:
    radial-gradient(700px 420px at 8% 0%, rgba(91,36,249,.04), transparent 58%),
    radial-gradient(2px 2px at 12% 20%, rgba(13,2,48,.05) 50%, transparent 51%),
    radial-gradient(2px 2px at 32% 60%, rgba(13,2,48,.04) 50%, transparent 51%),
    radial-gradient(2px 2px at 72% 30%, rgba(13,2,48,.04) 50%, transparent 51%),
    radial-gradient(2px 2px at 90% 75%, rgba(13,2,48,.05) 50%, transparent 51%);
}
#proekty::before {
  background:
    radial-gradient(620px 420px at 90% -10%, rgba(245,158,11,.06), transparent 60%),
    radial-gradient(640px 460px at 5% 30%, rgba(91,36,249,.06), transparent 60%),
    radial-gradient(560px 400px at 60% 110%, rgba(24,93,250,.05), transparent 60%);
}
#spravochnik::before {
  background: repeating-linear-gradient(0deg, rgba(13,2,48,.02) 0 1px, transparent 1px 40px),
              repeating-linear-gradient(90deg, rgba(13,2,48,.02) 0 1px, transparent 1px 40px);
  mask-image: radial-gradient(760px 520px at 50% 30%, black, transparent 75%);
  -webkit-mask-image: radial-gradient(760px 520px at 50% 30%, black, transparent 75%);
}

/* ==========================================================================
   COURSE EXPERIENCE — overview metrics + the four-stage learning pathway
   ========================================================================== */
.course-experience {
  position: relative; isolation: isolate; overflow: hidden;
  color: var(--color-text-primary);
  background:
    radial-gradient(ellipse 760px 520px at 88% 8%, rgba(91,36,249,.075), transparent 70%),
    radial-gradient(ellipse 720px 480px at 8% 72%, rgba(24,93,250,.055), transparent 72%),
    linear-gradient(180deg, #fff 0%, #fbfbfe 50%, #f7f8fc 100%);
  border-bottom: 1px solid rgba(13,2,48,.07);
}
.course-experience::before {
  content: ""; position: absolute; z-index: -2; inset: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, rgba(13,2,48,.027) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(0deg, rgba(13,2,48,.027) 0 1px, transparent 1px 56px);
  -webkit-mask-image: linear-gradient(90deg, transparent 1%, #000 24%, #000 76%, transparent 99%);
  mask-image: linear-gradient(90deg, transparent 1%, #000 24%, #000 76%, transparent 99%);
}
.course-experience::after {
  content: ">>>"; position: absolute; z-index: -1; right: -22px; top: 42%; pointer-events: none;
  color: rgba(24,93,250,.032); font: 700 clamp(120px, 17vw, 250px)/1 'JetBrains Mono', monospace;
  letter-spacing: -.18em;
}
.course-experience__geometry { position: absolute; z-index: -1; inset: 0; pointer-events: none; }
.course-experience__axis { position: absolute; display: block; background: rgba(24,93,250,.09); }
.course-experience__axis--x { left: 0; right: 0; top: 45%; height: 1px; }
.course-experience__axis--y { left: calc(50% + 470px); top: 5%; bottom: 5%; width: 1px; }
.course-experience__point {
  position: absolute; width: 7px; height: 7px; border: 1px solid rgba(24,93,250,.22);
  border-radius: 50%; background: #fff; box-shadow: 0 0 0 5px rgba(24,93,250,.035);
}
.course-experience__point--a { left: 9%; top: 22%; }
.course-experience__point--b { right: 11%; top: 48%; }
.course-experience__point--c { left: 34%; bottom: 9%; }
.course-overview { padding-top: clamp(88px, 8vw, 118px); padding-bottom: 80px; overflow: visible; }
.course-format { padding-top: 64px; padding-bottom: clamp(96px, 9vw, 132px); overflow: visible; }
.course-overview::before, .course-format::before { display: none; }
.course-section-heading { max-width: 720px; margin-bottom: 44px; }
.course-section-heading h2 { font-size: clamp(34px, 3.3vw, 46px); letter-spacing: -.03em; margin-bottom: 14px; }
.course-section-lead {
  max-width: 690px; color: var(--color-text-muted); font-size: 18px; line-height: 1.65;
  text-wrap: balance;
}
.course-format .course-section-heading { margin-bottom: 24px; }
.course-format .course-section-heading .sub { max-width: 760px; margin-bottom: 0; }

/* Progressive entrance: content is complete without JS; the enhancement
   only stages elements that have not yet entered the viewport. */
.course-experience.is-enhanced .experience-reveal {
  opacity: 0; transform: translate3d(0, 18px, 0);
  transition: opacity 560ms var(--ease-standard), transform 680ms var(--ease-out);
}
.course-experience.is-enhanced .experience-reveal.is-revealed { opacity: 1; transform: translate3d(0, 0, 0); }
.about-copy.experience-reveal { transition-delay: 80ms; }
.about-stats.experience-reveal { transition-delay: 160ms; }
.course-path.experience-reveal { transition-delay: 90ms; }

/* ---------- О курсе: text + asymmetric metric constellation ---------- */
.about-grid {
  display: grid; grid-template-columns: minmax(0, .84fr) minmax(520px, 1.16fr);
  gap: clamp(52px, 6vw, 84px); align-items: center;
}
.about-copy { min-width: 0; }
.about-copy > p { font-size: 16.5px; line-height: 1.72; margin: 0 0 18px; color: var(--color-text-primary); }
.about-highlights { display: grid; gap: 0; padding: 0; margin: 30px 0 32px; list-style: none; border-top: 1px solid rgba(13,2,48,.09); }
.about-highlights li {
  display: grid; grid-template-columns: 34px 1fr; gap: 13px; align-items: center;
  padding: 13px 0; border-bottom: 1px solid rgba(13,2,48,.09);
  color: var(--navy-800); font-size: 14px; font-weight: 600; line-height: 1.45;
}
.about-highlight__mark {
  color: var(--blue-600); font: 500 10px/1 'JetBrains Mono', monospace;
  letter-spacing: .06em;
}
.about-stats {
  position: relative; min-width: 0; height: 466px; display: grid; z-index: 0;
  grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: repeat(10, minmax(0, 1fr));
  gap: 11px;
}
.about-stats::before {
  content: ""; position: absolute; z-index: -1; inset: 24px 8px;
  background-image:
    repeating-linear-gradient(90deg, rgba(24,93,250,.045) 0 1px, transparent 1px 30px),
    repeating-linear-gradient(0deg, rgba(24,93,250,.045) 0 1px, transparent 1px 30px);
  -webkit-mask-image: radial-gradient(ellipse, #000 18%, transparent 72%);
  mask-image: radial-gradient(ellipse, #000 18%, transparent 72%);
}
.about-stats__routes { position: absolute; z-index: 0; inset: 0; width: 100%; height: 100%; overflow: visible; }
.about-stats__route, .about-stats__signal {
  fill: none; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round;
}
.about-stats__route { stroke: rgba(24,93,250,.22); stroke-width: 1.2; }
.about-stats__signal {
  stroke: var(--blue-500); stroke-width: 2; stroke-dasharray: 7 260; stroke-dashoffset: 270;
  filter: drop-shadow(0 0 3px rgba(24,93,250,.32)); animation: course-metric-signal 10s linear infinite;
  animation-play-state: paused;
}
.about-stats__routes circle { fill: #fff; stroke: rgba(24,93,250,.55); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.course-experience.is-in-view .about-stats__signal { animation-play-state: running; }
.about-stat {
  --metric-delay: 0ms;
  position: relative; z-index: 1; overflow: hidden; display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-width: 0; padding: clamp(18px, 2vw, 23px); border: 1px solid rgba(13,2,48,.1); border-radius: 16px;
  background: rgba(255,255,255,.9); box-shadow: 0 14px 38px rgba(13,2,48,.07), inset 0 1px rgba(255,255,255,.95);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  transition: border-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
.course-experience.is-enhanced .about-stat { opacity: 0; transform: translate3d(0, 14px, 0) scale(.99); }
.course-experience.is-enhanced .about-stat.is-metric-entering {
  animation: course-metric-enter 620ms var(--ease-out) both;
  animation-delay: var(--metric-delay);
}
.course-experience.is-enhanced .about-stat.is-metric-revealed { opacity: 1; transform: none; }
.about-stat > * { position: relative; z-index: 1; }
.about-stat::before {
  content: ""; position: absolute; z-index: 0; right: -24px; top: -24px; width: 92px; height: 92px; border-radius: 50%;
  background: radial-gradient(circle, rgba(91,36,249,.11), transparent 68%); opacity: .82; pointer-events: none;
}
.about-stat::after {
  content: ""; position: absolute; right: 13px; bottom: 13px; width: 17px; height: 17px;
  border-right: 1px solid rgba(24,93,250,.23); border-bottom: 1px solid rgba(24,93,250,.23); pointer-events: none;
}
.course-experience.is-in-view .about-stat.is-metric-revealed::before {
  animation: course-metric-glow-drift 10s ease-in-out infinite;
}
.course-experience.is-in-view .about-stat--pages.is-metric-revealed::before { animation-delay: -4.6s; animation-duration: 11.4s; }
.course-experience.is-in-view .about-stat--projects.is-metric-revealed::before { animation-delay: -2.2s; animation-duration: 9.6s; }
.course-experience.is-in-view .about-stat--practice.is-metric-revealed::before { animation-delay: -5.8s; animation-duration: 12.2s; }
.about-stat--chapters { --metric-delay: 0ms; grid-column: 1 / 8; grid-row: 1 / 7; background: linear-gradient(145deg, #fff 0%, #f5f2ff 100%); }
.about-stat--pages { --metric-delay: 80ms; grid-column: 8 / 13; grid-row: 1 / 4; padding: 16px 18px; }
.about-stat--projects { --metric-delay: 160ms; grid-column: 8 / 13; grid-row: 4 / 7; padding: 16px 18px; }
.about-stat--practice { --metric-delay: 240ms; grid-column: 1 / 13; grid-row: 7 / 11; background: linear-gradient(145deg, #fff 0%, #eef4ff 100%); }
.about-stat__code {
  align-self: start; color: var(--blue-600); font: 500 10px/1 'JetBrains Mono', monospace; letter-spacing: .085em;
}
.about-stat__number-zone { min-width: 0; min-height: 0; display: grid; place-items: center; padding: 8px 0; }
.about-stat .num {
  width: max-content; color: var(--navy-900); font: 800 42px/1 'Sora', sans-serif;
  font-variant-numeric: tabular-nums; letter-spacing: -.045em;
  transition: color var(--duration-base) var(--ease-standard), filter var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
.about-stat.is-metric-entering .num {
  animation: course-metric-number-settle 460ms var(--ease-out) both;
  animation-delay: calc(140ms + var(--metric-delay));
}
.about-stat--chapters .num { font-size: clamp(48px, 5.2vw, 68px); color: var(--violet-500); }
.about-stat--practice .num { font-size: clamp(48px, 4.5vw, 62px); color: var(--blue-600); }
.about-stat__copy { min-width: 0; align-self: end; display: grid; gap: 8px; }
.about-stat .lbl {
  color: var(--navy-800); font-size: 14px; font-weight: 600; line-height: 1.35;
  transition: color var(--duration-base) var(--ease-standard);
}
.about-stat__detail { color: var(--color-text-muted); font: 400 11px/1.4 'JetBrains Mono', monospace; }

@media (hover: hover) and (pointer: fine) {
  .about-stat:hover,
  .course-experience.is-enhanced .about-stat.is-metric-revealed:hover {
    transform: translateY(-2px); border-color: rgba(24,93,250,.3);
    box-shadow: 0 19px 44px rgba(13,2,48,.1), 0 0 24px rgba(24,93,250,.055), inset 0 1px #fff;
  }
  .about-stat:hover::before { opacity: 1; }
  .about-stat:hover .num { transform: translateY(-1px); filter: drop-shadow(0 4px 10px rgba(24,93,250,.12)); }
  .about-stat:hover .lbl { color: var(--navy-900); }
}

.course-experience__bridge { position: relative; width: min(1120px, calc(100% - 48px)); height: 1px; margin: 0 auto; background: rgba(13,2,48,.09); }
.course-experience__bridge::before, .course-experience__bridge::after {
  content: ""; position: absolute; top: 50%; width: 7px; height: 7px; border: 1px solid rgba(24,93,250,.35);
  border-radius: 50%; background: #fff; transform: translateY(-50%);
}
.course-experience__bridge::before { left: 0; }
.course-experience__bridge::after { right: 0; }
.course-experience__bridge span {
  position: absolute; left: 50%; top: 50%; width: 34px; height: 10px; transform: translate(-50%, -50%);
  background: #fafbfe;
}
.course-experience__bridge span::before {
  content: ">>>"; display: block; color: var(--blue-500); text-align: center;
  font: 500 9px/10px 'JetBrains Mono', monospace; letter-spacing: -.06em;
}

/* ---------- Как устроен курс: one connected four-stage pathway ---------- */
.course-path { position: relative; padding-top: 4px; }
.course-path__rail { position: absolute; z-index: 0; pointer-events: none; overflow: visible; }
.course-path__rail--desktop { left: 0; right: 0; top: 2px; width: 100%; height: 108px; }
.course-path__rail--mobile { display: none; }
.course-path__base, .course-path__segment, .course-path__signal {
  fill: none; vector-effect: non-scaling-stroke; stroke-linecap: round;
}
.course-path__base { stroke: rgba(13,2,48,.13); stroke-width: 2; }
.course-path__segment { stroke: rgba(24,93,250,.16); stroke-width: 3; transition: stroke var(--duration-base) var(--ease-standard), filter var(--duration-base) var(--ease-standard); }
.course-path__signal {
  stroke: var(--blue-500); stroke-width: 2.3; stroke-dasharray: 14 970; stroke-dashoffset: 990;
  filter: drop-shadow(0 0 4px rgba(24,93,250,.5)); animation: course-path-signal 8.5s linear infinite;
  animation-play-state: paused;
}
.course-experience.is-in-view .course-path__signal { animation-play-state: running; }
.course-path__stages { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(16px, 2.2vw, 30px); margin: 0; padding: 0; list-style: none; }
.course-stage { position: relative; min-width: 0; }
.course-stage__node {
  position: absolute; z-index: 3; left: 50%; top: 40px; display: grid; place-items: center;
  width: 28px; height: 28px; border: 1px solid rgba(24,93,250,.48); border-radius: 50%;
  background: #fff; box-shadow: 0 0 0 7px rgba(24,93,250,.055), 0 7px 16px rgba(13,2,48,.09);
  transform: translateX(-50%); transition: transform var(--duration-base) var(--ease-out), border-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard);
}
.course-stage__node i {
  display: block; width: 7px; height: 7px; border-radius: 50%; background: var(--blue-500);
  box-shadow: 0 0 9px rgba(24,93,250,.42); animation: course-node-pulse 5.5s ease-in-out infinite;
  animation-play-state: paused;
}
.course-experience.is-in-view .course-stage__node i { animation-play-state: running; }
.course-stage:nth-child(2) .course-stage__node i { animation-delay: -1.4s; }
.course-stage:nth-child(3) .course-stage__node i { animation-delay: -2.8s; }
.course-stage:nth-child(4) .course-stage__node i { animation-delay: -4.2s; }
.course-stage__content {
  position: relative; min-height: 340px; margin-top: 108px; padding: 26px 20px 22px; overflow: hidden;
  border-top: 2px solid rgba(24,93,250,.32); border-bottom: 1px solid rgba(13,2,48,.08);
  background: linear-gradient(180deg, rgba(255,255,255,.82), rgba(255,255,255,.44));
  transition: transform var(--duration-base) var(--ease-out), border-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard), background var(--duration-base) var(--ease-standard);
}
.course-stage:nth-child(even) .course-stage__content { margin-top: 132px; }
.course-stage__content::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 1px;
  background: linear-gradient(rgba(24,93,250,.18), transparent 72%);
}
.course-stage__content::after {
  content: ""; position: absolute; right: 0; bottom: 0; width: 28px; height: 28px;
  border-right: 1px solid rgba(24,93,250,.16); border-bottom: 1px solid rgba(24,93,250,.16);
}
.course-stage:hover .course-stage__node {
  transform: translateX(-50%) scale(1.08); border-color: var(--blue-500);
  box-shadow: 0 0 0 8px rgba(24,93,250,.085), 0 9px 22px rgba(13,2,48,.12);
}
.course-stage:hover .course-stage__content {
  transform: translateY(-4px); border-top-color: var(--blue-500);
  background: rgba(255,255,255,.92); box-shadow: 0 18px 36px rgba(13,2,48,.065);
}
.course-path:has(.course-stage:nth-child(1):hover) .course-path__segment--1,
.course-path:has(.course-stage:nth-child(2):hover) .course-path__segment--2,
.course-path:has(.course-stage:nth-child(3):hover) .course-path__segment--3,
.course-path:has(.course-stage:nth-child(4):hover) .course-path__segment--4 {
  stroke: rgba(24,93,250,.8); filter: drop-shadow(0 0 4px rgba(24,93,250,.3));
}
.course-stage__meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 18px; }
.course-stage__meta span:first-child { color: var(--blue-600); font: 600 12px/1 'JetBrains Mono', monospace; }
.course-stage__meta span:last-child { color: var(--color-text-muted); font: 500 9px/1 'JetBrains Mono', monospace; letter-spacing: .1em; text-transform: uppercase; }
.course-stage__icon {
  display: grid; place-items: center; width: 68px; height: 68px; margin-bottom: 20px;
  color: var(--blue-600); border: 1px solid rgba(24,93,250,.12); border-radius: 14px;
  background: linear-gradient(145deg, rgba(234,241,255,.9), rgba(243,238,255,.78));
  transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-standard);
}
.course-stage__icon svg { display: block; width: 50px; height: 50px; overflow: visible; }
.course-stage__icon svg * {
  fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.course-stage__icon svg circle { fill: currentColor; stroke: none; }
.course-stage:hover .course-stage__icon { transform: translateY(-2px); box-shadow: 0 12px 24px rgba(24,93,250,.1); }
.course-stage h3 { min-height: 47px; margin: 0 0 10px; color: var(--navy-900); font-size: 17px; line-height: 1.35; letter-spacing: -.01em; }
.course-stage p { margin: 0; color: var(--color-text-muted); font-size: 13.5px; line-height: 1.6; }
.course-stage__output {
  display: block; margin-top: 20px; padding-top: 13px; border-top: 1px dashed rgba(13,2,48,.12);
  color: var(--navy-700); font: 500 10px/1.35 'JetBrains Mono', monospace;
}

/* One coherent SVG family, with one restrained signature per stage. */
.course-stage--theory .stage-icon__line--a { animation: course-theory-lines 5.8s ease-in-out infinite; animation-play-state: paused; }
.course-stage--practice .stage-icon__cursor { animation: course-terminal-cursor 1.15s steps(1, end) infinite; animation-play-state: paused; }
.course-stage--compare .stage-icon__column { transform-box: fill-box; transform-origin: center; animation: course-compare-shift 6.4s ease-in-out infinite; animation-play-state: paused; }
.course-stage--compare .stage-icon__column--right { animation-delay: -3.2s; }
.course-stage--projects .stage-icon__status { animation: course-project-status 3.8s ease-in-out infinite; animation-play-state: paused; }
.course-stage--projects .stage-icon__rocket { transform-box: fill-box; transform-origin: center; animation: course-project-nudge 6.8s ease-in-out infinite; animation-play-state: paused; }
.course-experience.is-in-view .stage-icon__line--a,
.course-experience.is-in-view .stage-icon__cursor,
.course-experience.is-in-view .stage-icon__column,
.course-experience.is-in-view .stage-icon__status,
.course-experience.is-in-view .stage-icon__rocket { animation-play-state: running; }

@keyframes course-metric-enter {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(.99); }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes course-metric-number-settle {
  from { opacity: .88; transform: translate3d(0, 3px, 0) scale(.985); filter: drop-shadow(0 4px 12px rgba(24,93,250,.14)); }
  to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); filter: none; }
}
@keyframes course-metric-glow-drift {
  0%, 100% { opacity: .76; transform: translate3d(0, 0, 0); }
  50% { opacity: .96; transform: translate3d(-3px, 2px, 0); }
}
@keyframes course-metric-signal { to { stroke-dashoffset: -8; } }
@keyframes course-path-signal { to { stroke-dashoffset: -14; } }
@keyframes course-node-pulse { 0%, 74%, 100% { opacity: .58; transform: scale(1); } 84% { opacity: 1; transform: scale(1.22); } }
@keyframes course-theory-lines { 0%, 68%, 100% { opacity: .48; } 78%, 88% { opacity: 1; } }
@keyframes course-terminal-cursor { 0%, 48% { opacity: 1; } 49%, 100% { opacity: .12; } }
@keyframes course-compare-shift { 0%, 72%, 100% { transform: translateX(0); opacity: .7; } 82% { transform: translateX(1.5px); opacity: 1; } }
@keyframes course-project-status { 0%, 72%, 100% { opacity: .42; } 82%, 90% { opacity: 1; filter: drop-shadow(0 0 3px currentColor); } }
@keyframes course-project-nudge { 0%, 76%, 100% { transform: translate3d(0, 0, 0); } 86% { transform: translate3d(2px, -2px, 0); } }

/* ==========================================================================
   COURSE JOURNEY — visual roadmap of all 24 chapters (signature element)
   ========================================================================== */
/* COURSE JOURNEY — mounted modules on a light, routed learning backplane. */
.pcb-board {
  position: relative; isolation: isolate; padding: 38px 34px 46px; border: 1px solid #bdd1e8; border-radius: 24px;
  background: radial-gradient(ellipse at 50% 0, #e5edff, transparent 650px),
    repeating-linear-gradient(90deg, #527caf0b 0 1px, transparent 1px 24px),
    repeating-linear-gradient(0deg, #527caf0b 0 1px, transparent 1px 24px), #f3f8fc;
  box-shadow: inset 0 0 0 6px #fff9, 0 8px 24px #274f7910;
}
.pcb-surface { position: absolute; inset: 0; z-index: -1; pointer-events: none; border-radius: inherit; overflow: hidden; }
.pcb-traces { fill: none; stroke: #88aed2; stroke-width: 1.5; opacity: .52; }
.pcb-vias { fill: #f3f8fc; stroke: #6995bd; stroke-width: 1.5; opacity: .7; }
.pcb-components { fill: #e2edf7; stroke: #7e9cba; stroke-width: 1.3; opacity: .58; }
.pcb-silkscreen { fill: #7189a5; font: 9px 'JetBrains Mono', monospace; letter-spacing: 2px; }
.journey-progress {
  position: relative; max-width: 720px; margin: 0 auto 38px; padding: 20px 28px 24px; text-align: left;
  background: linear-gradient(120deg, #e4edff, #f6f8ff 60%, #e1f5f5); border: 1px solid #849fc5; border-radius: 8px;
  box-shadow: inset 0 0 0 5px #fff8, inset 0 -8px 12px #476a9510, 0 5px 0 -2px #b8cadd, 0 8px 14px #36558312;
}
.journey-progress::after { content: ''; position: absolute; left: calc(50% - 13px); top: 100%; width: 26px; height: 39px; background: repeating-linear-gradient(90deg, #859dbc 0 3px, transparent 3px 11.5px); }
.jp-hardware { display: flex; align-items: center; gap: 5px; padding-bottom: 12px; margin-bottom: 14px; border-bottom: 3px double #9fb9d4; }
.jp-hardware span { margin-right: auto; font: 10px 'JetBrains Mono', monospace; letter-spacing: 2px; color: #57708e; }
.jp-hardware i { width: 5px; height: 5px; background: #91a9bd; border-radius: 50%; }
.jp-hardware i:first-of-type { background: #2767ec; box-shadow: 0 0 5px #2767ec80; }
.jp-top { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 6px; }
.journey-progress .jp-headline { font-family: 'Sora', sans-serif; font-weight: 700; font-size: 18px; }
.jp-pct { font-family: 'Sora', sans-serif; font-weight: 800; font-size: 28px; font-variant-numeric: tabular-nums; color: #5148cf; }
.journey-progress .jp-detail { color: #53647e; font-size: 14px; margin-bottom: 16px; }
.jp-bar-track { height: 9px; padding: 1px; border: 1px solid #becddf; background: #d5e1ec; border-radius: 3px; }
.jp-bar-fill { position: relative; height: 100%; width: 0%; border-radius: 2px; background: linear-gradient(90deg, #2767ec, #7451e8, #29aebd); transition: width var(--duration-slow) var(--ease-out); }
.jp-bar-fill[style]:not([style*='width: 0%'])::after { content: ''; position: absolute; right: -3px; top: -1px; width: 7px; height: 7px; border-radius: 50%; background: #199c75; box-shadow: 0 0 6px #199c7566; }
.jp-stats-row { display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 18px; padding-top: 16px; border-top: 1px solid #b8cbe0; }
.jp-stat { font-size: 12px; color: #53647e; }
.jp-stat strong { color: #1a294b; font-family: 'JetBrains Mono', monospace; font-weight: 600; }
.journey-rail { position: relative; max-width: 960px; margin: 0 auto; }
.pcb-bus { position: absolute; left: calc(50% - 13px); top: 0; bottom: 0; width: 26px; display: flex; justify-content: space-between; padding: 0 1px; background: #dce9f2a6; border-radius: 8px; }
.pcb-bus i { width: 3px; height: 100%; background: #96adc8; border-inline: 1px solid #f7fbff; }
.pcb-bus i:nth-child(2) { background: #879ed0; }
.journey-node { --accent: #8b9fb5; --body: #edf3f8; --edge: #adbed0; position: relative; display: grid; grid-template-columns: minmax(0,1fr) 164px minmax(0,1fr); align-items: center; min-height: 172px; padding-block: 14px; }
.journey-node.state-in-progress { --accent: #7660c9; --body: #eceafa; --edge: #afa1d7; }
.journey-node.state-completed { --accent: #168567; --body: #def3e9; --edge: #78b4a1; }
.journey-node.state-current { --accent: #3b61e8; --body: #e1e8ff; --edge: #5d7ce6; }
.jn-route { position: absolute; left: 50%; top: calc(50% - 90px); width: 82px; height: 180px; overflow: visible; fill: none; pointer-events: none; color: var(--accent); }
.journey-node:nth-child(odd) .jn-route { left: calc(50% - 82px); transform: scaleX(-1); }
.jn-route path { vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.jn-route-base { stroke: var(--accent); stroke-width: 2; }
.jn-route-secondary { stroke: #b5c8d9; stroke-width: 1.5; }
.jn-via { fill: #f3f8fc; stroke: currentColor; stroke-width: 1.5; }
.jn-dot { position: relative; grid-column: 2; grid-row: 1; justify-self: center; width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--accent); background: #f3f8fc; z-index: 1; }
.state-completed .jn-dot { background: #168567; box-shadow: 0 0 0 4px #d8f0e8; }
.state-current .jn-dot { background: #3b61e8; box-shadow: 0 0 0 5px #d9e3ff, 0 0 16px #3b61e84d; }
.jn-card { position: relative; grid-row: 1; display: block; padding: 18px 22px; text-align: left; text-decoration: none; color: #1a294b; border: 1.5px solid var(--edge); border-radius: 7px; background: linear-gradient(135deg, #ffffff8c, transparent 60%), var(--body); box-shadow: inset 0 0 0 4px #ffffff80, inset 0 -7px 10px #476a9510, 0 4px 0 -1px #b4c4d5, 0 6px 10px #1e426a14; transition: transform 180ms ease, border-color 180ms ease; }
.journey-node:nth-child(odd) .jn-card { grid-column: 1; }
.journey-node:nth-child(even) .jn-card { grid-column: 3; }
.jn-card::after { content: ''; position: absolute; inset: 8px; border: 1px solid #fff9; border-radius: 2px; pointer-events: none; }
.jn-card:hover { transform: translateY(-2px); border-color: #3b61e8; }
.jn-card:focus-visible { outline: 3px solid #3b61e8; outline-offset: 7px; }
.journey-node:has(.jn-card:is(:hover,:focus-visible)) .jn-route-base { stroke: #3b61e8; }
.jn-pins { position: absolute; top: calc(50% - 15px); left: -13px; width: 12px; display: grid; gap: 6px; }
.jn-pins i { height: 6px; border: 1px solid #90a7c0; border-radius: 1px; background: linear-gradient(#eef5fc, #a6b9cd); }
.journey-node:nth-child(odd) .jn-pins { left: auto; right: -13px; }
.jn-pins i:nth-child(2), .jn-pins i:nth-child(3) { background: var(--accent); border-color: var(--accent); }
.jn-pads { position: absolute; bottom: -6px; left: 24px; display: flex; gap: 5px; }
.jn-pads i { height: 5px; width: 9px; background: #a3b7cb; border: 1px solid #8aa1bb; border-top: 0; }
.journey-node:has([data-module="1"]) .jn-pads { left: auto; right: 24px; }
.journey-node:has([data-module="2"]) .jn-pads { top: -6px; bottom: auto; }
.journey-node:has([data-module="2"]) .jn-card { border-radius: 13px 5px 13px 5px; }
.journey-node:has([data-module="3"]) .jn-card { border-radius: 5px 16px 5px 5px; }
.journey-node:has([data-module="3"]) .jn-pads { left: 50%; }
.jn-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.jn-num { font: 11px 'JetBrains Mono', monospace; color: #526885; }
.jn-part { font: 9px 'JetBrains Mono', monospace; letter-spacing: 1.5px; color: #657a93; }
.jn-title { font-family: 'Sora', sans-serif; font-weight: 700; font-size: 15px; margin-bottom: 12px; line-height: 1.4; overflow-wrap: anywhere; }
.jn-progress-track { height: 5px; border: 1px solid #b9cad8; background: #d2dfea; margin-bottom: 9px; }
.jn-progress-fill { height: 100%; width: 0%; background: var(--accent); transition: width var(--duration-slow) var(--ease-out); }
.jn-meta { font-size: 12px; color: #53647e; }
.jn-state-badge { display: inline-flex; align-items: center; gap: 7px; font: 10px 'JetBrains Mono', monospace; color: #52647d; margin-top: 12px; }
.jn-state-badge:not(:empty)::before { content: ''; width: 6px; height: 6px; border: 1px solid var(--accent); border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px #fff9; }
.state-completed .jn-state-badge { color: #136d55; }
.state-completed .jn-state-badge::after { content: '✓'; font-size: 12px; }
.state-current .jn-state-badge { color: #304fbe; }
.state-current .jn-card { animation: pcb-module-response 8s linear infinite; }
.state-current .jn-pins i:nth-child(2), .state-current .jn-pins i:nth-child(3), .state-current .jn-state-badge::before { animation: pcb-contact-response 8s linear infinite; }
.pcb-packet { stroke: #3866ef; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 5 95; stroke-dashoffset: 100; opacity: 0; filter: drop-shadow(0 0 4px #4774ff); }
.state-current .pcb-packet { opacity: 1; animation: pcb-packet-travel 8s linear infinite; }
.state-preview .jn-route-secondary { animation: pcb-next-preview 8s linear infinite; }
@keyframes pcb-packet-travel { to { stroke-dashoffset: 0; } }
@keyframes pcb-module-response { 0%, 30%, 68%, 100% { box-shadow: inset 0 0 0 4px #ffffff80, 0 4px 0 -1px #9aafe0, 0 0 18px #4169e827; } 42%, 53% { box-shadow: inset 0 0 0 4px #ffffffb3, inset 0 0 0 6px #7796ee, 0 4px 0 -1px #9aafe0, 0 0 28px #4169e852; } }
@keyframes pcb-contact-response { 0%, 30%, 68%, 100% { box-shadow: 0 0 2px #3b61e84d; } 42%, 53% { background: #71d8f2; box-shadow: 0 0 8px #3866ef; } }
@keyframes pcb-next-preview { 0%, 75%, 100% { stroke: #b5c8d9; } 88% { stroke: #819dde; } }
.journey-all-toggle { text-align: center; margin-top: 44px; }

/* ==========================================================================
   PRACTICE catalog — dense but structured modules
   ========================================================================== */
.practice-hero { display: grid; grid-template-columns: minmax(0, .95fr) minmax(430px, 1.1fr); gap: clamp(40px, 5vw, 72px); align-items: center; margin-bottom: 40px; }
.practice-hero__copy { min-width: 0; }
.practice-hero__copy .sub { margin-bottom: 18px; }
.practice-hero__art { min-width: 0; }
.practice-art { display: block; width: 100%; max-width: 520px; height: auto; filter: drop-shadow(0 22px 34px rgba(9,2,31,.32)); }

.practice-line-reveal { transform-box: fill-box; transform-origin: left; animation: practice-line-reveal 7s ease-in-out infinite; }
.practice-run-node { transform-box: fill-box; transform-origin: center; animation: practice-run-press 7s ease-in-out infinite; }
.practice-glow-halo circle { transform-box: fill-box; transform-origin: center; animation: practice-glow-pulse 7s ease-in-out infinite; }
.practice-signal--a { animation: practice-signal-a 7s ease-in-out infinite; }
.practice-signal--b { animation: practice-signal-b 7s ease-in-out infinite; }
.practice-result-idle { animation: practice-result-idle 7s ease-in-out infinite; }
.practice-result-value { transform-box: fill-box; transform-origin: center; animation: practice-result-value 7s ease-in-out infinite; }
.practice-check-fill { animation: practice-check-fill 7s ease-in-out infinite; }
.practice-check-mark { animation: practice-check-draw 7s ease-in-out infinite; }
.practice-progress-seg { animation: practice-progress-seg 7s ease-in-out infinite; }
.practice-progress-dot { animation: practice-progress-dot 7s ease-in-out infinite; }

@keyframes practice-line-reveal {
  0%, 9% { transform: scaleX(0); }
  17%, 86% { transform: scaleX(1); }
  90%, 100% { transform: scaleX(0); }
}
@keyframes practice-run-press {
  0%, 27% { transform: scale(1); }
  29% { transform: scale(.92); }
  33%, 100% { transform: scale(1); }
}
@keyframes practice-glow-pulse {
  0%, 27% { opacity: .28; transform: scale(1); }
  33% { opacity: .55; transform: scale(1.18); }
  46%, 100% { opacity: .28; transform: scale(1); }
}
@keyframes practice-signal-a {
  0%, 28% { opacity: 0; stroke-dashoffset: 0; }
  30% { opacity: 1; stroke-dashoffset: 0; }
  38% { opacity: 1; stroke-dashoffset: -36; }
  40%, 100% { opacity: 0; stroke-dashoffset: -36; }
}
@keyframes practice-signal-b {
  0%, 36% { opacity: 0; stroke-dashoffset: 0; }
  38% { opacity: 1; stroke-dashoffset: 0; }
  45% { opacity: 1; stroke-dashoffset: -69; }
  47%, 100% { opacity: 0; stroke-dashoffset: -69; }
}
@keyframes practice-result-idle { 0%, 44% { opacity: 1; } 47%, 86% { opacity: 0; } 90%, 100% { opacity: 1; } }
@keyframes practice-result-value {
  0%, 44% { opacity: 0; transform: translateY(4px); }
  47%, 86% { opacity: 1; transform: translateY(0); }
  90%, 100% { opacity: 0; transform: translateY(4px); }
}
@keyframes practice-check-fill { 0%, 50% { opacity: 0; } 53%, 86% { opacity: 1; } 90%, 100% { opacity: 0; } }
@keyframes practice-check-draw { 0%, 50% { stroke-dashoffset: 22; } 56%, 86% { stroke-dashoffset: 0; } 90%, 100% { stroke-dashoffset: 22; } }
@keyframes practice-progress-seg { 0%, 58% { stroke-dashoffset: 30; } 66%, 86% { stroke-dashoffset: 0; } 90%, 100% { stroke-dashoffset: 30; } }
@keyframes practice-progress-dot { 0%, 64% { opacity: 0; } 66%, 86% { opacity: 1; } 90%, 100% { opacity: 0; } }

.practice-summary { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 32px; }
.practice-stat-chip { background: var(--surface-2); border: var(--border-hairline); border-radius: var(--radius-full); padding: 9px 20px; font-size: 14px; box-shadow: var(--shadow-sm); }
.practice-stat-chip strong { color: var(--color-brand-violet); font-variant-numeric: tabular-nums; }

.practice-filters { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 36px; }
.pf-btn {
  background: var(--surface-2); border: var(--border-hairline-strong); border-radius: var(--radius-full);
  padding: 9px 20px; font-size: 14px; font-weight: 600; cursor: pointer; color: var(--color-text-primary); font-family: inherit;
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.pf-btn:hover { border-color: var(--navy-900); }
.pf-btn.active { background: var(--navy-900); color: #fff; border-color: var(--navy-900); }

/* ---------------------------------------------------------------------------
   Practice chapter cards — "learning module" system.
   Each card gets a presentational accent (5 families, cycled deterministically
   by nth-of-type across the 24 fixed chapters — purely decorative, unrelated
   to progress). Real state (completed/in-progress/not-started/no-lessons) is
   layered on top via .state-* classes that progress.js already computes from
   the one real localStorage progress store; nothing here invents data.
   --------------------------------------------------------------------------- */
.practice-chapter-group {
  --pcg-a1: 91, 36, 249;   /* violet-500 */
  --pcg-a2: 24, 93, 250;   /* blue-500 */
  position: relative; isolation: isolate;
  margin-bottom: 16px; border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid rgba(var(--pcg-a1), .16);
  background:
    repeating-linear-gradient(90deg, rgba(13,2,48,.028) 0 1px, transparent 1px 26px),
    repeating-linear-gradient(0deg, rgba(13,2,48,.028) 0 1px, transparent 1px 26px),
    radial-gradient(130% 160% at 0% 0%, rgba(var(--pcg-a1), .08), transparent 60%),
    linear-gradient(180deg, rgba(255,255,255,.94), rgba(255,255,255,.8));
  box-shadow: var(--shadow-sm), inset 0 1px rgba(255,255,255,.7);
  transition: transform var(--duration-base) var(--ease-standard),
    box-shadow var(--duration-base) var(--ease-standard),
    border-color var(--duration-base) var(--ease-standard);
}
/* 5 accent families, cycled deterministically across the 24 fixed chapters. */
.practice-chapter-group:nth-of-type(5n+2) { --pcg-a1: 24, 93, 250; --pcg-a2: 34, 211, 238; }   /* blue -> cyan */
.practice-chapter-group:nth-of-type(5n+3) { --pcg-a1: 70, 58, 216; --pcg-a2: 91, 36, 249; }    /* indigo -> violet */
.practice-chapter-group:nth-of-type(5n+4) { --pcg-a1: 34, 211, 238; --pcg-a2: 18, 181, 160; }  /* cyan -> teal */
.practice-chapter-group:nth-of-type(5n)   { --pcg-a1: 91, 36, 249; --pcg-a2: 185, 160, 252; }  /* violet -> lavender */
/* Zero-practice / theory-only chapters: neutral, quieter, no fake progress. */
.practice-chapter-group[data-lesson-ids=""] { --pcg-a1: 107, 107, 125; --pcg-a2: 148, 148, 166; }

.practice-chapter-group::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: linear-gradient(180deg, rgb(var(--pcg-a1)), rgb(var(--pcg-a2)));
  opacity: .8; transition: opacity var(--duration-base) var(--ease-standard);
}
.practice-chapter-group.state-completed::before { background: linear-gradient(180deg, #1FAE63, rgb(var(--pcg-a2))); }
.practice-chapter-group.state-no-lessons::before { opacity: .35; }
/* One-shot light sweep on hover/expand — no continuous animation. */
.practice-chapter-group::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(110deg, transparent 32%, rgba(255,255,255,.4) 46%, transparent 60%);
  transform: translateX(-130%);
}
.practice-chapter-group:has(.pcg-summary:hover)::after,
.practice-chapter-group[open]::after {
  transform: translateX(130%);
  transition: transform .6s var(--ease-standard);
}

.practice-chapter-group:has(.pcg-summary:hover) {
  transform: translateY(-2px);
  border-color: rgba(var(--pcg-a1), .34);
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(var(--pcg-a1), .16);
}
.practice-chapter-group:has(.pcg-summary:hover)::before { opacity: 1; }
.practice-chapter-group[open] {
  transform: translateY(-1px);
  border-color: rgba(var(--pcg-a1), .4);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(var(--pcg-a1), .22), 0 0 32px -10px rgba(var(--pcg-a1), .45);
}
.practice-chapter-group[open]::before { opacity: 1; }
.practice-chapter-group.state-completed:has(.pcg-summary:hover),
.practice-chapter-group.state-completed[open] {
  border-color: rgba(31,174,99,.4);
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(31,174,99,.28), 0 0 28px -10px rgba(31,174,99,.5);
}
.practice-chapter-group.state-no-lessons { box-shadow: none; }
.practice-chapter-group.state-no-lessons:has(.pcg-summary:hover) { box-shadow: var(--shadow-sm); }

.pcg-summary {
  display: flex; align-items: center; gap: 14px; padding: 16px 20px;
  cursor: pointer; list-style: none; position: relative; z-index: 1;
  transition: transform 100ms var(--ease-standard);
}
.pcg-summary:active { transform: scale(.995); }
.pcg-summary::-webkit-details-marker { display: none; }
.pcg-num {
  flex-shrink: 0; font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700;
  letter-spacing: .03em; line-height: 1; padding: 6px 8px; border-radius: var(--radius-sm);
  color: rgb(var(--pcg-a1)); background: rgba(var(--pcg-a1), .12); border: 1px solid rgba(var(--pcg-a1), .2);
}
.practice-chapter-group.state-no-lessons .pcg-num { color: var(--gray-600); background: var(--gray-100); border-color: var(--color-border-default); }
.pcg-heading { min-width: 0; flex: 1; }
.pcg-title-row { display: flex; align-items: baseline; gap: 10px; row-gap: 4px; flex-wrap: wrap; }
.pcg-title { font-family: 'Sora', sans-serif; font-weight: 700; font-size: 16px; color: var(--navy-900); }
.pcg-meta { font-size: 13px; color: var(--color-text-muted); margin-top: 3px; }
.pcg-state-badge {
  display: none; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
  padding: 2px 9px; border-radius: var(--radius-full); white-space: nowrap;
}
.state-completed .pcg-state-badge { display: inline-flex; color: #147A4F; background: rgba(31,174,99,.14); }
.state-completed .pcg-state-badge::before { content: '✓'; }
.state-in-progress .pcg-state-badge { display: inline-flex; color: rgb(var(--pcg-a1)); background: rgba(var(--pcg-a1), .13); }

.pcg-progress { display: flex; align-items: center; gap: 10px; min-width: 150px; flex-shrink: 0; }
.pcg-bar-track {
  position: relative; flex: 1; height: 7px; border-radius: var(--radius-full); overflow: visible;
  background: rgba(var(--pcg-a1), .1); box-shadow: inset 0 1px 2px rgba(13,2,48,.07);
}
.pcg-bar-fill {
  position: relative; height: 100%; border-radius: var(--radius-full); width: 0%;
  background: linear-gradient(90deg, rgb(var(--pcg-a1)), rgb(var(--pcg-a2)));
  box-shadow: 0 0 8px -1px rgba(var(--pcg-a1), .6);
  transition: width var(--duration-slow) var(--ease-out);
}
.state-completed .pcg-bar-fill { background: linear-gradient(90deg, #1FAE63, #12B5A0); box-shadow: 0 0 8px -1px rgba(31,174,99,.6); }
.state-in-progress .pcg-bar-fill::after {
  content: ""; position: absolute; right: 0; top: 50%; width: 7px; height: 7px; border-radius: 50%;
  background: rgb(var(--pcg-a2)); box-shadow: 0 0 6px 1px rgba(var(--pcg-a2), .7);
  transform: translate(50%, -50%) scale(1); animation: pcg-endpoint-pulse 2.4s ease-in-out infinite;
}
@keyframes pcg-endpoint-pulse {
  0%, 100% { opacity: .6; transform: translate(50%, -50%) scale(.95); }
  50% { opacity: 1; transform: translate(50%, -50%) scale(1.12); }
}
.pcg-count { font-size: 12px; color: var(--color-text-muted); white-space: nowrap; font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; }

.pcg-chevron {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; color: rgb(var(--pcg-a1));
  transition: transform var(--duration-base) var(--ease-standard);
}
.pcg-chevron svg { display: block; }
details[open] > .pcg-summary .pcg-chevron { transform: rotate(90deg); }
.practice-chapter-group:not([open]):has(.pcg-summary:hover) .pcg-chevron { transform: translateX(3px); }

@keyframes pcg-reveal { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
.pcg-lessons { border-top: 1px solid var(--color-border-default); padding: 6px 12px 14px; position: relative; z-index: 1; }
details[open] > .pcg-lessons { animation: pcg-reveal .28s var(--ease-standard); }
.practice-lesson-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border-radius: var(--radius-md); text-decoration: none; color: var(--color-text-primary);
  border-left: 3px solid transparent;
  transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard);
}
.practice-lesson-row:hover { background: var(--surface-1); transform: translateX(2px); }
.practice-lesson-row[data-mode="browser"]:hover { border-left-color: var(--color-brand-blue); }
.practice-lesson-row[data-mode="local"]:hover { border-left-color: var(--gray-600); }
.practice-lesson-row[data-mode="adapted"]:hover { border-left-color: var(--violet-500); }
.plr-left { display: flex; align-items: center; gap: 12px; min-width: 0; }
.plr-id { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--color-brand-blue); flex-shrink: 0; width: 46px; }
.plr-title { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plr-badge { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: var(--radius-full); white-space: nowrap; }
.plr-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.plr-badge.mode-browser { background: #EAF1FF; color: var(--blue-600); }
.plr-badge.mode-browser::before { background: var(--blue-500); }
.plr-badge.mode-local { background: var(--gray-100); color: var(--gray-600); }
.plr-badge.mode-local::before { background: var(--gray-600); }
.plr-badge.mode-adapted { background: #F3EEFF; color: var(--violet-500); }
.plr-badge.mode-adapted::before { background: var(--violet-500); }
.plr-check { flex-shrink: 0; color: var(--green-500); font-size: 14px; opacity: 0; transform: scale(.6); transition: opacity var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard); }
.plr-check.done { opacity: 1; transform: scale(1); }

/* ==========================================================================
   PROJECTS — the most visual homepage section
   ========================================================================== */
.projects-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
.project-card {
  position: relative; display: flex; min-width: 0; flex-direction: column; border-radius: var(--radius-lg); overflow: hidden; text-decoration: none;
  color: var(--color-text-primary); background: var(--surface-2); border: var(--border-hairline);
  box-shadow: var(--shadow-sm); transition: transform var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard), border-color var(--duration-base) var(--ease-standard);
}
.project-card::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; box-shadow: inset 0 1px rgba(255,255,255,.58); }
.project-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-xl); border-color: rgba(91,36,249,.28); }
.project-card:focus-visible { outline-width: 3px; outline-offset: 4px; }
.project-card-visual { position: relative; aspect-ratio: 16 / 10; width: 100%; display: block; overflow: hidden; background: var(--navy-950); }
.project-card-visual svg { display: block; width: 100%; height: 100%; transition: transform var(--duration-slow) var(--ease-standard); }
.project-card:hover .project-card-visual svg { transform: scale(1.03); }
.project-card-body { padding: 21px 23px 24px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.project-card-title { margin: 0; font-family: 'Sora', sans-serif; font-weight: 700; font-size: 19px; line-height: 1.3; letter-spacing: -.015em; }
.project-card-desc { margin: 0; font-size: 14px; line-height: 1.58; color: var(--color-text-muted); flex: 1; }
.project-card-topics { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0; }
.project-topic { font: 600 10.5px/1.35 'Inter', sans-serif; letter-spacing: .01em; background: var(--gray-100); color: var(--gray-600); padding: 4px 10px; border: 1px solid rgba(13,2,48,.035); border-radius: var(--radius-full); }
.project-card-cta { font-weight: 600; font-size: 14px; color: var(--color-brand-blue); display: inline-flex; align-items: center; gap: 4px; transition: gap var(--duration-fast) var(--ease-standard); }
.project-card:hover .project-card-cta { gap: 8px; }

.project-art__grid { opacity: .6; }
.project-art__route { stroke-dashoffset: 0; animation: project-route 8s linear infinite; }
.project-art__nodes circle { opacity: .38; transform-box: fill-box; transform-origin: center; animation: project-node 5s ease-in-out infinite; }
.project-art__nodes circle:nth-child(2) { animation-delay: -1.7s; }
.project-art__nodes circle:nth-child(3) { animation-delay: -3.4s; }
.project-art__subject > * { transform-box: fill-box; transform-origin: center; }
.project-art--rock-paper-scissors .project-art__subject > g { animation: project-tilt 5.4s ease-in-out infinite; }
.project-art--tic-tac-toe .project-art__subject > g:nth-of-type(2) { animation: project-mark 4.8s ease-in-out infinite; }

/* story-generator: source pools -> random-selection hub -> assembled result.
   Scoped to .story-* classes (its own scene, not .project-art__subject) so
   this stays isolated from every other project's generic icon animation. */
.project-art--story-generator .story-token {
  transform-box: fill-box; transform-origin: center;
  opacity: .58; animation: story-token-pulse 4.8s ease-in-out infinite;
}
.project-art--story-generator .story-tokens .story-token:nth-child(1) { animation-delay: 0s; }
.project-art--story-generator .story-tokens .story-token:nth-child(2) { animation-delay: -1.6s; }
.project-art--story-generator .story-tokens .story-token:nth-child(3) { animation-delay: -3.2s; }
.project-art--story-generator .story-route { animation: story-route-flow 6s linear infinite; }
.project-art--story-generator .story-routes .story-route:nth-child(2) { animation-delay: -2s; }
.project-art--story-generator .story-routes .story-route:nth-child(3) { animation-delay: -4s; }
.project-art--story-generator .story-route--out { animation-duration: 3s; }
.project-art--story-generator .story-hub-dot {
  transform-box: fill-box; transform-origin: center;
  opacity: .3; animation: story-hub-cycle 4.8s ease-in-out infinite;
}
.project-art--story-generator .story-hub .story-hub-dot:nth-child(2) { animation-delay: -1.6s; }
.project-art--story-generator .story-hub .story-hub-dot:nth-child(3) { animation-delay: -3.2s; }
.project-art--story-generator .story-output-line {
  transform-box: fill-box; transform-origin: left center;
  opacity: 0; transform: translateX(-6px) scaleX(.88);
  animation: story-line-reveal 6s ease-in-out infinite;
}
.project-art--story-generator .story-output-lines .story-output-line:nth-child(1) { animation-delay: 0s; }
.project-art--story-generator .story-output-lines .story-output-line:nth-child(2) { animation-delay: .5s; }
.project-art--story-generator .story-output-lines .story-output-line:nth-child(3) { animation-delay: 1s; }
.project-art--story-generator .story-output-line--accent { animation-name: story-line-reveal-accent; }
.project-art--story-generator .story-spark {
  transform-box: fill-box; transform-origin: center;
  animation: story-spark-pulse 6.4s ease-in-out infinite; animation-delay: 1.6s;
}

@keyframes story-token-pulse { 0%, 100% { opacity: .55; transform: scale(1); } 15% { opacity: 1; transform: scale(1.045); } 30% { opacity: .68; transform: scale(1); } }
@keyframes story-route-flow { to { stroke-dashoffset: -22; } }
@keyframes story-hub-cycle { 0%, 100% { opacity: .28; transform: scale(1); } 50% { opacity: .85; transform: scale(1.35); } }
@keyframes story-line-reveal { 0% { opacity: 0; transform: translateX(-6px) scaleX(.88); } 14% { opacity: .92; transform: translateX(0) scaleX(1); } 80% { opacity: .92; transform: translateX(0) scaleX(1); } 94%, 100% { opacity: 0; transform: translateX(-6px) scaleX(.88); } }
@keyframes story-line-reveal-accent { 0% { opacity: 0; transform: translateX(-6px) scaleX(.88); } 14% { opacity: 1; transform: translateX(0) scaleX(1); } 80% { opacity: 1; transform: translateX(0) scaleX(1); } 94%, 100% { opacity: 0; transform: translateX(-6px) scaleX(.88); } }
@keyframes story-spark-pulse { 0%, 76%, 100% { opacity: .5; transform: scale(.86) rotate(-3deg); } 86% { opacity: 1; transform: scale(1.04) rotate(3deg); } }

/* paint-app: toolbar + canvas with a self-drawing brush stroke, a shape-tool
   outline, and cycling color swatches. Scoped to .paint-* classes (its own
   scene, not .project-art__subject) so this stays isolated from every other
   project's generic icon animation. */
.project-art--paint-app .paint-stroke { animation: paint-stroke-draw 5.5s ease-in-out infinite; }
.project-art--paint-app .paint-cursor {
  transform-box: fill-box; transform-origin: center;
  animation: paint-cursor-move 5.5s ease-in-out infinite; animation-delay: -.4s;
}
.project-art--paint-app .paint-shape {
  transform-box: fill-box; transform-origin: center;
  opacity: 0; transform: scale(.92);
  animation: paint-shape-reveal 6.2s ease-in-out infinite;
}
.project-art--paint-app .paint-shape--oval { animation-delay: .5s; }
.project-art--paint-app .paint-tool--pencil .paint-tool-btn,
.project-art--paint-app .paint-tool--rect .paint-tool-btn {
  transform-box: fill-box; transform-origin: center;
  animation: paint-tool-active 7s ease-in-out infinite;
}
.project-art--paint-app .paint-tool--rect .paint-tool-btn { animation-delay: -3.5s; }
.project-art--paint-app .paint-swatch {
  transform-box: fill-box; transform-origin: center;
  animation: paint-swatch-cycle 6.5s ease-in-out infinite;
}
.project-art--paint-app .paint-swatches .paint-swatch:nth-child(2) { animation-delay: -2.17s; }
.project-art--paint-app .paint-swatches .paint-swatch:nth-child(3) { animation-delay: -4.34s; }

@keyframes paint-stroke-draw { 0% { stroke-dashoffset: 320; } 55%, 85% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 320; } }
@keyframes paint-cursor-move { 0%, 100% { transform: translate(0, 0) scale(1); } 55% { transform: translate(-3px, 2px) scale(1.15); } 75% { transform: translate(0, 0) scale(1); } }
@keyframes paint-shape-reveal { 0%, 26% { opacity: 0; transform: scale(.92); } 42% { opacity: .55; transform: scale(1); } 80% { opacity: .55; transform: scale(1); } 96%, 100% { opacity: 0; transform: scale(.92); } }
@keyframes paint-tool-active { 0%, 40%, 100% { opacity: .85; transform: scale(1); } 8% { opacity: 1; transform: scale(1.045); } }
@keyframes paint-swatch-cycle { 0%, 100% { opacity: .55; transform: scale(1); } 12% { opacity: 1; transform: scale(1.05); } 28% { opacity: .7; transform: scale(1); } }

/* snake: a segmented body threading two turns toward one apple, with a head
   visibly distinct from the body (eyes + a small directional cue) and a
   faint dotted route hinting at the final approach. Scoped to .snake-*
   classes (its own scene, not .project-art__subject) so this stays isolated
   from every other project's generic icon animation. */
.project-art--snake .snake-segment {
  transform-box: fill-box; transform-origin: center;
  animation: snake-wave 5s ease-in-out infinite;
}
.project-art--snake .snake-body .snake-segment:nth-child(1) { animation-delay: -1.75s; }
.project-art--snake .snake-body .snake-segment:nth-child(2) { animation-delay: -1.5s; }
.project-art--snake .snake-body .snake-segment:nth-child(3) { animation-delay: -1.25s; }
.project-art--snake .snake-body .snake-segment:nth-child(4) { animation-delay: -1s; }
.project-art--snake .snake-body .snake-segment:nth-child(5) { animation-delay: -.75s; }
.project-art--snake .snake-body .snake-segment:nth-child(6) { animation-delay: -.5s; }
.project-art--snake .snake-body .snake-segment:nth-child(7) { animation-delay: -.25s; }
.project-art--snake .snake-body .snake-segment:nth-child(8) { animation-delay: 0s; }
.project-art--snake .snake-head {
  transform-box: fill-box; transform-origin: center;
  animation: snake-head-move 5.4s ease-in-out infinite;
}
.project-art--snake .snake-apple {
  transform-box: fill-box; transform-origin: center;
  animation: snake-apple-pulse 4s ease-in-out infinite;
}
.project-art--snake .snake-apple-leaf {
  transform-box: fill-box; transform-origin: center;
  animation: snake-leaf-tilt 4s ease-in-out infinite;
}
.project-art--snake .snake-route { animation: snake-route-flow 6.5s linear infinite; }
.project-art--snake .snake-tail {
  transform-box: fill-box; transform-origin: center;
  animation: snake-tail-grow 8.5s ease-in-out infinite;
}

@keyframes snake-wave { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-4px) scale(1.035); } }
@keyframes snake-head-move { 0%, 100% { transform: translateX(0) scale(1); } 50% { transform: translateX(3px) scale(1.03); } }
@keyframes snake-apple-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes snake-leaf-tilt { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg); } }
@keyframes snake-route-flow { to { stroke-dashoffset: -18; } }
@keyframes snake-tail-grow { 0%, 82%, 100% { opacity: 0; transform: scale(.4); } 88%, 95% { opacity: .85; transform: scale(1); } }

/* space-shooter: enemy formation approaching, the player's own shot in
   flight toward the lead enemy, a return shot from a side enemy, engine
   thrust, and a small explosion timed to the strike — one coherent ~8s
   attack beat layered under independent ambient drift/thrust/starfield
   motion. Scoped to .shooter-* classes (its own scene, not
   .project-art__subject) so this stays isolated from every other
   project's generic icon animation. */
.project-art--space-shooter .shooter-stars-far {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-star-drift-far 13s ease-in-out infinite alternate;
}
.project-art--space-shooter .shooter-stars-near {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-star-drift-near 8s ease-in-out infinite alternate;
}
.project-art--space-shooter .shooter-stars-bright circle {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-star-twinkle 4s ease-in-out infinite;
}
.project-art--space-shooter .shooter-stars-bright circle:nth-child(2) { animation-delay: -2s; }
.project-art--space-shooter .shooter-route { animation: shooter-route-flow 7s linear infinite; }
.project-art--space-shooter .shooter-enemy {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-enemy-drift 6s ease-in-out infinite;
}
.project-art--space-shooter .shooter-enemy--right { animation-delay: -4s; }
.project-art--space-shooter .shooter-enemy--lead {
  animation-name: shooter-enemy-drift, shooter-enemy-target-flash;
  animation-duration: 6s, 8s;
  animation-delay: -2s, 0s;
  animation-timing-function: ease-in-out, linear;
  animation-iteration-count: infinite, infinite;
}
.project-art--space-shooter .shooter-shot {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-shot-fly 8s linear infinite;
}
.project-art--space-shooter .shooter-enemy-shot {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-enemy-shot-fly 8s linear infinite;
}
.project-art--space-shooter .shooter-player {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-player-drift 6s ease-in-out infinite;
}
.project-art--space-shooter .shooter-engine {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-engine-pulse 2s ease-in-out infinite;
}
.project-art--space-shooter .shooter-explosion {
  transform-box: fill-box; transform-origin: center;
  animation: shooter-explosion-burst 8s linear infinite;
}

@keyframes shooter-star-drift-far { 0% { transform: translateY(0); } 100% { transform: translateY(7px); } }
@keyframes shooter-star-drift-near { 0% { transform: translateY(0); } 100% { transform: translateY(10px); } }
@keyframes shooter-star-twinkle { 0%, 100% { opacity: .4; } 50% { opacity: 1; } }
@keyframes shooter-route-flow { to { stroke-dashoffset: -22; } }
@keyframes shooter-enemy-drift { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-4px, 3px); } }
@keyframes shooter-enemy-target-flash { 0%, 41% { opacity: 1; } 43% { opacity: .25; } 50%, 100% { opacity: 1; } }
@keyframes shooter-shot-fly {
  0%, 23% { opacity: 0; transform: translateY(46px); }
  25% { opacity: 1; transform: translateY(46px); }
  44% { opacity: 1; transform: translateY(-56px); }
  47%, 100% { opacity: 0; transform: translateY(-56px); }
}
@keyframes shooter-enemy-shot-fly {
  0%, 63% { opacity: 0; transform: translateY(-46px); }
  66% { opacity: .8; transform: translateY(-46px); }
  88% { opacity: .8; transform: translateY(50px); }
  92%, 100% { opacity: 0; transform: translateY(50px); }
}
@keyframes shooter-player-drift {
  0%, 100% { transform: translateX(0) rotate(0deg); }
  25% { transform: translateX(-9px) rotate(-2deg); }
  50% { transform: translateX(0) rotate(0deg); }
  75% { transform: translateX(9px) rotate(2deg); }
}
@keyframes shooter-engine-pulse {
  0%, 100% { opacity: .7; transform: scaleY(.75); }
  50% { opacity: 1; transform: scaleY(1.15); }
}
@keyframes shooter-explosion-burst {
  0%, 41% { opacity: 0; transform: scale(.4); }
  43.75% { opacity: 1; transform: scale(1.15); }
  50% { opacity: .5; transform: scale(1.3); }
  54%, 100% { opacity: 0; transform: scale(1.3); }
}

/* calculator: a two-line display and a 4x4 keypad keying through the real
   sequence 1, 2, +, 7, = to reach 12 + 7 = 19 on one coordinated 8s loop —
   pressed keys and the display text they produce land on the same beat.
   Scoped to .calc-* classes (its own scene, not .project-art__subject) so
   this stays isolated from every other project's generic icon animation. */
.project-art--calculator .calc-body { filter: drop-shadow(0 10px 20px rgba(8,1,28,.35)); }
.project-art--calculator .calc-display-state { opacity: 0; }
.project-art--calculator .calc-display-state--idle { animation: calc-display-idle 8s ease-in-out infinite; }
.project-art--calculator .calc-display-state--1 { animation: calc-display-1 8s ease-in-out infinite; }
.project-art--calculator .calc-display-state--2 { animation: calc-display-2 8s ease-in-out infinite; }
.project-art--calculator .calc-display-state--3 { animation: calc-display-3 8s ease-in-out infinite; }
.project-art--calculator .calc-display-state--4 { animation: calc-display-4 8s ease-in-out infinite; }
.project-art--calculator .calc-display-state--result { animation: calc-display-result 8s ease-in-out infinite; }
.project-art--calculator .calc-result-value { transform-box: fill-box; transform-origin: center; animation: calc-result-pulse 8s ease-in-out infinite; }
.project-art--calculator .calc-key { transform-box: fill-box; transform-origin: center; }
.project-art--calculator .calc-key--seq-1 { animation: calc-key-pulse 8s ease-in-out infinite; animation-delay: .8s; }
.project-art--calculator .calc-key--seq-2 { animation: calc-key-pulse 8s ease-in-out infinite; animation-delay: 1.6s; }
.project-art--calculator .calc-key--seq-3 { animation: calc-key-pulse 8s ease-in-out infinite; animation-delay: 2.5s; }
.project-art--calculator .calc-key--seq-4 { animation: calc-key-pulse 8s ease-in-out infinite; animation-delay: 3.4s; }
.project-art--calculator .calc-key--seq-5 { animation: calc-key-pulse-strong 8s ease-in-out infinite; animation-delay: 4.5s; }

@keyframes calc-display-idle { 0%, 8% { opacity: 1; } 10%, 90% { opacity: 0; } 100% { opacity: 1; } }
@keyframes calc-display-1 { 0%, 8% { opacity: 0; } 10%, 19% { opacity: 1; } 21%, 100% { opacity: 0; } }
@keyframes calc-display-2 { 0%, 19% { opacity: 0; } 21%, 30% { opacity: 1; } 32%, 100% { opacity: 0; } }
@keyframes calc-display-3 { 0%, 30% { opacity: 0; } 32%, 41% { opacity: 1; } 43%, 100% { opacity: 0; } }
@keyframes calc-display-4 { 0%, 41% { opacity: 0; } 43%, 55% { opacity: 1; } 57%, 100% { opacity: 0; } }
@keyframes calc-display-result { 0%, 55% { opacity: 0; } 63%, 88% { opacity: 1; } 90%, 100% { opacity: 0; } }
@keyframes calc-result-pulse { 0%, 62%, 84%, 100% { transform: scale(1); } 70% { transform: scale(1.06); } }
@keyframes calc-key-pulse { 0% { transform: translateY(2px) scale(.97); filter: drop-shadow(0 0 5px rgba(91,36,249,.55)); } 8%, 100% { transform: translateY(0) scale(1); filter: none; } }
@keyframes calc-key-pulse-strong { 0% { transform: translateY(3px) scale(.95); filter: drop-shadow(0 0 8px rgba(91,36,249,.75)); } 10%, 100% { transform: translateY(0) scale(1); filter: none; } }

/* todo-app: one coordinated 9s loop plays the real task lifecycle — input
   fills, Add is pressed, a new row is inserted, its checkbox fills and the
   checkmark draws, a strike-through draws over the completed text, the
   database glyph pulses on save, the delete control activates and the row
   fades out, then the loop resets. Scoped to .todo-* classes (its own
   scene, not .project-art__subject) so this stays isolated from every
   other project's generic icon animation. */
.project-art--todo-app .todo-app-window { filter: drop-shadow(0 10px 20px rgba(8,1,28,.3)); }
.project-art--todo-app .todo-input-state { transform-box: fill-box; transform-origin: center; }
.project-art--todo-app .todo-input-state--empty { animation: todo-input-empty 9s ease-in-out infinite; }
.project-art--todo-app .todo-input-state--filled { animation: todo-input-filled 9s ease-in-out infinite; }
.project-art--todo-app .todo-add { transform-box: fill-box; transform-origin: center; animation: todo-add-press 9s ease-in-out infinite; }
.project-art--todo-app .todo-row--new { transform-box: fill-box; transform-origin: center; animation: todo-row-insert 9s ease-in-out infinite; }
.project-art--todo-app .todo-row--new .todo-checkbox-fill { animation: todo-checkbox-fill 9s ease-in-out infinite; }
.project-art--todo-app .todo-row--new .todo-check { animation: todo-check-draw 9s ease-in-out infinite; }
.project-art--todo-app .todo-row--new .todo-row__text { animation: todo-text-mute 9s ease-in-out infinite; }
.project-art--todo-app .todo-row--new .todo-strike { animation: todo-strike-draw 9s ease-in-out infinite; }
.project-art--todo-app .todo-row--new .todo-delete { transform-box: fill-box; transform-origin: center; animation: todo-delete-pulse 9s ease-in-out infinite; }
.project-art--todo-app .todo-db-pulse { transform-box: fill-box; transform-origin: center; }
.project-art--todo-app .todo-db-pulse--insert { animation: todo-db-pulse-insert 9s ease-in-out infinite; }
.project-art--todo-app .todo-db-pulse--complete { animation: todo-db-pulse-complete 9s ease-in-out infinite; }

@keyframes todo-input-empty { 0%, 7% { opacity: 1; } 9%, 19% { opacity: 0; } 21%, 100% { opacity: 1; } }
@keyframes todo-input-filled { 0%, 7% { opacity: 0; } 9%, 19% { opacity: 1; } 21%, 100% { opacity: 0; } }
@keyframes todo-add-press {
  0%, 17% { transform: translateY(0) scale(1); filter: none; }
  20% { transform: translateY(2px) scale(.97); filter: drop-shadow(0 0 6px rgba(24,93,250,.6)); }
  23%, 100% { transform: translateY(0) scale(1); filter: none; }
}
@keyframes todo-row-insert {
  0%, 20% { opacity: 0; transform: translateY(-4px); }
  24%, 66% { opacity: 1; transform: translateY(0); }
  71%, 100% { opacity: 0; transform: translateY(-4px); }
}
@keyframes todo-checkbox-fill { 0%, 34% { opacity: 0; } 38%, 66% { opacity: 1; } 71%, 100% { opacity: 0; } }
@keyframes todo-check-draw {
  0%, 37% { stroke-dashoffset: 16; opacity: 0; }
  41%, 66% { stroke-dashoffset: 0; opacity: 1; }
  71%, 100% { stroke-dashoffset: 16; opacity: 0; }
}
@keyframes todo-text-mute { 0%, 42% { opacity: .92; } 46%, 66% { opacity: .25; } 71%, 100% { opacity: .92; } }
@keyframes todo-strike-draw {
  0%, 45% { stroke-dashoffset: 140; opacity: 0; }
  49%, 66% { stroke-dashoffset: 0; opacity: 1; }
  71%, 100% { stroke-dashoffset: 140; opacity: 0; }
}
@keyframes todo-delete-pulse {
  0%, 65% { opacity: .32; transform: scale(1); }
  67% { opacity: .95; transform: scale(1.15); }
  70%, 100% { opacity: .32; transform: scale(1); }
}
@keyframes todo-db-pulse-insert {
  0%, 21% { opacity: 0; transform: translateY(0) scale(.6); }
  25% { opacity: .8; transform: translateY(14px) scale(1); }
  30%, 100% { opacity: 0; transform: translateY(14px) scale(.6); }
}
@keyframes todo-db-pulse-complete {
  0%, 52% { opacity: 0; transform: translateY(0) scale(.6); }
  56% { opacity: .85; transform: translateY(14px) scale(1); }
  61%, 100% { opacity: 0; transform: translateY(14px) scale(.6); }
}

/* bouncing-ball: one ball travels a closed diagonal route inside a bordered
   playfield — right wall, then top wall, then back to rest — with a brief
   squash at each wall, a floor shadow that fades as the ball gets "higher",
   a static dashed motion path, and a 2-pip bounce counter. Scoped to
   .ball-* classes (its own scene, not .project-art__subject) so this stays
   isolated from every other project's generic icon animation. */
.project-art--bouncing-ball .ball-trail { animation: ball-trail-flow 4s linear infinite; }
.project-art--bouncing-ball .ball-shadow { transform-box: fill-box; transform-origin: center; animation: ball-shadow-cycle 6.5s linear infinite; }
.project-art--bouncing-ball .ball-impact { transform-box: fill-box; transform-origin: center; }
.project-art--bouncing-ball .ball-impact--right { animation: ball-impact-right 6.5s linear infinite; }
.project-art--bouncing-ball .ball-impact--top { animation: ball-impact-top 6.5s linear infinite; }
.project-art--bouncing-ball .ball-travel { animation: ball-move 6.5s linear infinite; }
.project-art--bouncing-ball .ball-squash { transform-box: fill-box; transform-origin: center; animation: ball-squash-cycle 6.5s linear infinite; }
.project-art--bouncing-ball .ball-counter-pip-fill { transform-box: fill-box; transform-origin: center; }
.project-art--bouncing-ball .ball-counter-pip-fill--1 { animation: ball-counter-pip-1 6.5s linear infinite; }
.project-art--bouncing-ball .ball-counter-pip-fill--2 { animation: ball-counter-pip-2 6.5s linear infinite; }

@keyframes ball-trail-flow { to { stroke-dashoffset: -22; } }
@keyframes ball-move {
  0% { transform: translate(0, 0); }
  27% { transform: translate(260px, -100px); }
  30% { transform: translate(260px, -100px); }
  50% { transform: translate(100px, -136px); }
  53% { transform: translate(100px, -136px); }
  82% { transform: translate(0, 0); }
  100% { transform: translate(0, 0); }
}
@keyframes ball-squash-cycle {
  0%, 26% { transform: scale(1, 1); }
  28% { transform: scale(.94, 1.06); }
  30%, 49% { transform: scale(1, 1); }
  51% { transform: scale(1.06, .94); }
  53%, 100% { transform: scale(1, 1); }
}
@keyframes ball-shadow-cycle {
  0%, 100% { transform: translateX(0) scale(1); opacity: .22; }
  27%, 30% { transform: translateX(260px) scale(.82); opacity: .13; }
  50%, 53% { transform: translateX(100px) scale(.68); opacity: .09; }
  82% { transform: translateX(0) scale(1); opacity: .22; }
}
@keyframes ball-impact-right {
  0%, 25% { opacity: .35; transform: scale(1); }
  28% { opacity: .95; transform: scale(1.7); }
  32%, 100% { opacity: .35; transform: scale(1); }
}
@keyframes ball-impact-top {
  0%, 48% { opacity: 0; transform: scale(1); }
  51% { opacity: .95; transform: scale(1.7); }
  55%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes ball-counter-pip-1 {
  0%, 27% { opacity: 0; }
  29%, 80% { opacity: 1; }
  84%, 100% { opacity: 0; }
}
@keyframes ball-counter-pip-2 {
  0%, 50% { opacity: 0; }
  52%, 80% { opacity: 1; }
  84%, 100% { opacity: 0; }
}

/* rock-paper-scissors: one animated round — the player picks rock from a
   3-token pool, the computer cycles rock/paper/scissors and settles on
   scissors, both faces move a little toward a small center confrontation
   cue, then rock's win is emphasized (glow, slight lift) while scissors
   dims and shifts back, before the scene resets. Scoped to .rps-* classes
   (its own scene, not .project-art__subject) so this stays isolated from
   every other project's generic icon animation. */
.project-art--rock-paper-scissors .rps-pool-token--selected { transform-box: fill-box; transform-origin: center; animation: rps-pool-select 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-rule-path { animation: rps-rule-flow 12s linear infinite; }
.project-art--rock-paper-scissors .rps-player-move { animation: rps-player-move 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-player-scale { transform-box: fill-box; transform-origin: center; animation: rps-player-scale 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-winner-glow { transform-box: fill-box; transform-origin: center; animation: rps-winner-glow 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-computer-move { animation: rps-computer-move 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-computer--rock { animation: rps-computer-rock 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-computer--paper { animation: rps-computer-paper 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-computer--scissors { transform-box: fill-box; transform-origin: center; animation: rps-computer-scissors 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-reveal-ring { transform-box: fill-box; transform-origin: center; animation: rps-reveal-ring 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-impact-pulse { transform-box: fill-box; transform-origin: center; animation: rps-impact-pulse 8s ease-in-out infinite; }
.project-art--rock-paper-scissors .rps-impact-spark { animation: rps-impact-spark 8s ease-in-out infinite; }

@keyframes rps-rule-flow { to { stroke-dashoffset: -16; } }
@keyframes rps-pool-select {
  0%, 8% { transform: scale(.34); }
  11% { transform: scale(.4); }
  15%, 100% { transform: scale(.34); }
}
@keyframes rps-player-move {
  0%, 8% { opacity: 0; transform: translate(0, 16px); }
  14%, 40% { opacity: 1; transform: translate(0, 0); }
  43%, 47% { opacity: 1; transform: translate(9px, 0); }
  50%, 80% { opacity: 1; transform: translate(9px, -3px); }
  88%, 100% { opacity: 0; transform: translate(0, 16px); }
}
@keyframes rps-player-scale {
  0%, 8% { transform: scale(.8); }
  14%, 47% { transform: scale(1); }
  50%, 80% { transform: scale(1.06); }
  88%, 100% { transform: scale(.8); }
}
@keyframes rps-winner-glow {
  0%, 46% { opacity: 0; transform: scale(.8); }
  50%, 80% { opacity: .4; transform: scale(1); }
  88%, 100% { opacity: 0; transform: scale(.8); }
}
@keyframes rps-computer-move {
  0%, 39% { transform: translate(0, 0); }
  43%, 47% { transform: translate(-9px, 0); }
  52%, 80% { transform: translate(-5px, 0); }
  88%, 100% { transform: translate(0, 0); }
}
@keyframes rps-computer-rock {
  0%, 18% { opacity: 0; }
  20%, 22% { opacity: 1; }
  25%, 100% { opacity: 0; }
}
@keyframes rps-computer-paper {
  0%, 23% { opacity: 0; }
  25%, 27% { opacity: 1; }
  30%, 100% { opacity: 0; }
}
@keyframes rps-computer-scissors {
  0%, 28% { opacity: 0; transform: scale(1); }
  30% { opacity: 1; transform: scale(1.12); }
  33%, 47% { opacity: 1; transform: scale(1); }
  52%, 80% { opacity: .55; transform: scale(1); }
  88%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes rps-reveal-ring {
  0%, 29% { opacity: 0; transform: scale(.8); }
  33%, 46% { opacity: .55; transform: scale(1); }
  52%, 100% { opacity: 0; transform: scale(1.15); }
}
@keyframes rps-impact-pulse {
  0%, 41% { opacity: 0; transform: scale(.4); }
  44% { opacity: .9; transform: scale(1); }
  48%, 100% { opacity: 0; transform: scale(2.2); }
}
@keyframes rps-impact-spark {
  0%, 42% { opacity: 0; }
  45% { opacity: .85; }
  49%, 100% { opacity: 0; }
}

/* temperature-converter: a "20 / °C" input feeds the thermometer, whose
   liquid rises as the Celsius result card lights up, then a small
   conversion hub branches a travelling dot to the Fahrenheit and Kelvin
   cards in turn (20 °C = 68 °F = 293.15 K, drawn once per loop) before the
   scene resets — the point being one entered value producing three
   representations, not a single static mercury column. Scoped to .temp-*
   classes (its own scene, not .project-art__subject) so this stays
   isolated from every other project's generic icon animation. */
.project-art--temperature-converter .temp-input { transform-box: fill-box; transform-origin: center; animation: temp-input-pulse 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-glow { animation: temp-glow-pulse 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-column { transform-box: fill-box; transform-origin: bottom; animation: temp-column-rise 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-hub-ring { transform-box: fill-box; transform-origin: center; animation: temp-hub-pulse 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-flow--fahrenheit { animation: temp-flow-fahrenheit 8s ease-in-out infinite, temp-dash-flow 2.6s linear infinite; }
.project-art--temperature-converter .temp-flow--kelvin { animation: temp-flow-kelvin 8s ease-in-out infinite, temp-dash-flow 2.6s linear infinite; }
.project-art--temperature-converter .temp-flow-dot--fahrenheit { transform-box: fill-box; transform-origin: center; animation: temp-dot-fahrenheit 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-flow-dot--kelvin { transform-box: fill-box; transform-origin: center; animation: temp-dot-kelvin 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-value-state { opacity: 0; }
.project-art--temperature-converter .temp-value-state--empty { animation: temp-value-empty 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-value-state--celsius { animation: temp-value-celsius 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-value-state--fahrenheit { animation: temp-value-fahrenheit 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-value-state--kelvin { animation: temp-value-kelvin 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-unit-card { transform-box: fill-box; transform-origin: center; }
.project-art--temperature-converter .temp-celsius { animation: temp-glow-celsius 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-fahrenheit { animation: temp-glow-fahrenheit 8s ease-in-out infinite; }
.project-art--temperature-converter .temp-kelvin { animation: temp-glow-kelvin 8s ease-in-out infinite; }

@keyframes temp-input-pulse {
  0%, 5%, 96%, 100% { opacity: 1; }
  9%, 92% { opacity: .55; }
}
@keyframes temp-glow-pulse {
  0%, 5%, 94%, 100% { opacity: .16; }
  20%, 78% { opacity: .34; }
}
@keyframes temp-column-rise {
  0%, 6%, 96%, 100% { transform: scaleY(.42); }
  20%, 80% { transform: scaleY(1); }
}
@keyframes temp-hub-pulse {
  0%, 18%, 30%, 46%, 100% { opacity: 0; transform: scale(1); }
  24% { opacity: .8; transform: scale(2.2); }
  40% { opacity: .8; transform: scale(2); }
}
@keyframes temp-flow-fahrenheit {
  0%, 25%, 94%, 100% { opacity: 0; }
  30%, 88% { opacity: .55; }
}
@keyframes temp-flow-kelvin {
  0%, 35%, 94%, 100% { opacity: 0; }
  40%, 88% { opacity: .55; }
}
@keyframes temp-dash-flow { to { stroke-dashoffset: -14; } }
@keyframes temp-dot-fahrenheit {
  0%, 25%, 100% { opacity: 0; transform: translate(0, 0); }
  27% { opacity: 1; transform: translate(2px, 1px); }
  32% { opacity: 0; transform: translate(24px, 4px); }
}
@keyframes temp-dot-kelvin {
  0%, 35%, 100% { opacity: 0; transform: translate(0, 0); }
  37% { opacity: 1; transform: translate(2px, -1px); }
  42% { opacity: 0; transform: translate(24px, 58px); }
}
@keyframes temp-value-empty {
  0%, 6%, 97%, 100% { opacity: 1; }
  10%, 92% { opacity: 0; }
}
@keyframes temp-value-celsius {
  0%, 7%, 96%, 100% { opacity: 0; }
  11%, 90% { opacity: 1; }
}
@keyframes temp-value-fahrenheit {
  0%, 29%, 94%, 100% { opacity: 0; }
  33%, 88% { opacity: 1; }
}
@keyframes temp-value-kelvin {
  0%, 39%, 92%, 100% { opacity: 0; }
  43%, 86% { opacity: 1; }
}
@keyframes temp-glow-celsius {
  0%, 9%, 18%, 100% { filter: none; }
  13% { filter: drop-shadow(0 0 7px rgba(24,93,250,.6)); }
}
@keyframes temp-glow-fahrenheit {
  0%, 31%, 40%, 100% { filter: none; }
  35% { filter: drop-shadow(0 0 7px rgba(24,93,250,.6)); }
}
@keyframes temp-glow-kelvin {
  0%, 41%, 50%, 100% { filter: none; }
  45% { filter: drop-shadow(0 0 7px rgba(24,93,250,.6)); }
}

/* notes-app: a text line types out with a following caret, the unsaved dot
   lights up, the save icon presses, a data pulse travels to the file icon,
   the file gains content and the unsaved dot clears, then a brief
   checkmark confirms before the scene resets — the point being the actual
   edit -> save -> file lifecycle, not a single static document with
   generic bars. Scoped to .notes-* classes (its own scene, not
   .project-art__subject) so this stays isolated from every other
   project's generic icon animation. */
.project-art--notes-app .notes-line--active { transform-box: fill-box; transform-origin: left; animation: notes-line-reveal 8s ease-in-out infinite; }
.project-art--notes-app .notes-caret { transform-box: fill-box; transform-origin: left; animation: notes-caret-move 8s ease-in-out infinite, notes-caret-blink 1s linear infinite; }
.project-art--notes-app .notes-unsaved { animation: notes-unsaved-state 8s ease-in-out infinite; }
.project-art--notes-app .notes-save { transform-box: fill-box; transform-origin: center; animation: notes-save-press 8s ease-in-out infinite; }
.project-art--notes-app .notes-flow { animation: notes-flow-visible 8s ease-in-out infinite, notes-dash-flow 2.4s linear infinite; }
.project-art--notes-app .notes-flow-dot { transform-box: fill-box; transform-origin: center; animation: notes-flow-dot-travel 8s ease-in-out infinite; }
.project-art--notes-app .notes-file-glow { animation: notes-file-confirm 8s ease-in-out infinite; }
.project-art--notes-app .notes-file-line { animation: notes-file-line-fill 8s ease-in-out infinite; }
.project-art--notes-app .notes-saved { transform-box: fill-box; transform-origin: center; animation: notes-saved-check 8s ease-in-out infinite; }

@keyframes notes-line-reveal {
  0%, 14%, 94%, 100% { transform: scaleX(0); }
  27%, 88% { transform: scaleX(1); }
}
@keyframes notes-caret-move {
  0%, 14%, 94%, 100% { transform: translateX(0); }
  27%, 88% { transform: translateX(150px); }
}
@keyframes notes-caret-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}
@keyframes notes-unsaved-state {
  0%, 27%, 60%, 100% { opacity: .2; }
  32%, 58% { opacity: 1; }
}
@keyframes notes-save-press {
  0%, 40%, 46%, 100% { transform: scale(1); filter: none; }
  43% { transform: scale(.94); filter: drop-shadow(0 0 6px rgba(24,93,250,.6)); }
}
@keyframes notes-flow-visible {
  0%, 44%, 56%, 100% { opacity: 0; }
  47%, 52% { opacity: .6; }
}
@keyframes notes-dash-flow { to { stroke-dashoffset: -14; } }
@keyframes notes-flow-dot-travel {
  0%, 45%, 100% { opacity: 0; transform: translate(0, 0); }
  47% { opacity: 1; transform: translate(4px, 8px); }
  52% { opacity: 0; transform: translate(34px, 50px); }
}
@keyframes notes-file-confirm {
  0%, 52%, 66%, 100% { opacity: 0; }
  56%, 62% { opacity: .25; }
}
@keyframes notes-file-line-fill {
  0%, 14%, 52% { opacity: 0; }
  58%, 94% { opacity: .8; }
  100% { opacity: 0; }
}
@keyframes notes-saved-check {
  0%, 58%, 72%, 100% { opacity: 0; transform: scale(.6); }
  64%, 68% { opacity: 1; transform: scale(1); }
}

/* safesort: one coherent safe-sorting lifecycle — unsorted files are swept
   by a scan, a plan card populates with proposed moves, a shield/check
   safety gate validates the plan, two representative files then travel
   into destination folders (never all at once), a duplicate pair is
   compared by hash and highlighted (never deleted), every move is logged
   to a small reversible history strip, and an undo cue confirms the whole
   operation can be reversed before the scene resets. Every element shares
   the same 9s timeline so the narrative reads in order rather than as
   independent looping parts. */
.project-art--safesort .safesort-scan { transform-box: fill-box; transform-origin: left center; animation: safesort-scan-sweep 9s ease-in-out infinite; }
.project-art--safesort .safesort-route--intake { animation: safesort-route-intake 9s ease-in-out infinite; }
.project-art--safesort .safesort-plan { transform-box: fill-box; transform-origin: center; animation: safesort-plan-card 9s ease-in-out infinite; }
.project-art--safesort .safesort-plan-row { transform-box: fill-box; transform-origin: left center; animation: safesort-plan-row 9s ease-in-out infinite; }
.project-art--safesort .safesort-plan-row--2 { animation-delay: .3s; }
.project-art--safesort .safesort-plan-row--3 { animation-delay: .6s; }
.project-art--safesort .safesort-shield-badge { animation: safesort-shield-badge 9s ease-in-out infinite; }
.project-art--safesort .safesort-shield-check { animation: safesort-shield-check 9s ease-in-out infinite; }
.project-art--safesort .safesort-folder-active { animation: safesort-folder-active 9s ease-in-out infinite; }
.project-art--safesort .safesort-route--apply-1 { animation: safesort-route-apply-1 9s ease-in-out infinite; }
.project-art--safesort .safesort-route--apply-2 { animation: safesort-route-apply-2 9s ease-in-out infinite; }
.project-art--safesort .safesort-files__mover--1 { transform-box: fill-box; transform-origin: center; animation: safesort-mover-1 9s ease-in-out infinite; }
.project-art--safesort .safesort-files__mover--2 { transform-box: fill-box; transform-origin: center; animation: safesort-mover-2 9s ease-in-out infinite; }
.project-art--safesort .safesort-folder-pulse--1 { transform-box: fill-box; transform-origin: center; animation: safesort-folder-pulse-1 9s ease-in-out infinite; }
.project-art--safesort .safesort-folder-pulse--2 { transform-box: fill-box; transform-origin: center; animation: safesort-folder-pulse-2 9s ease-in-out infinite; }
.project-art--safesort .safesort-history-row { transform-box: fill-box; transform-origin: left center; animation: safesort-history-row 9s ease-in-out infinite; }
.project-art--safesort .safesort-history-row--2 { animation-delay: .8s; }
.project-art--safesort .safesort-duplicate-tile { transform-box: fill-box; transform-origin: center; animation: safesort-duplicate-pulse 9s ease-in-out infinite; }
.project-art--safesort .safesort-duplicate-check-badge { animation: safesort-duplicate-check-badge 9s ease-in-out infinite; }
.project-art--safesort .safesort-duplicate-check { animation: safesort-duplicate-check 9s ease-in-out infinite; }
.project-art--safesort .safesort-hash-tick { animation: safesort-hash-tick 9s ease-in-out infinite; }
.project-art--safesort .safesort-history-check-badge { animation: safesort-history-check-badge 9s ease-in-out infinite; }
.project-art--safesort .safesort-history-check { animation: safesort-history-check 9s ease-in-out infinite; }
.project-art--safesort .safesort-undo { transform-box: fill-box; transform-origin: center; animation: safesort-undo-appear 9s ease-in-out infinite; }

@keyframes safesort-scan-sweep {
  0%, 6% { opacity: 0; transform: translateX(0); }
  10% { opacity: .4; transform: translateX(20px); }
  20% { opacity: .4; transform: translateX(80px); }
  26%, 100% { opacity: 0; transform: translateX(90px); }
}
@keyframes safesort-route-intake {
  0%, 8% { opacity: .18; }
  16%, 22% { opacity: .55; }
  28%, 100% { opacity: .18; }
}
@keyframes safesort-plan-card {
  0%, 18% { opacity: 0; transform: scale(.94); }
  24%, 88% { opacity: 1; transform: scale(1); }
  94%, 100% { opacity: 0; transform: scale(.94); }
}
@keyframes safesort-plan-row {
  0%, 22% { opacity: 0; transform: scaleX(.7); }
  28%, 88% { opacity: .7; transform: scaleX(1); }
  94%, 100% { opacity: 0; transform: scaleX(.7); }
}
@keyframes safesort-shield-badge {
  0%, 32% { opacity: 0; }
  38%, 88% { opacity: 1; }
  94%, 100% { opacity: 0; }
}
@keyframes safesort-shield-check {
  0%, 32% { stroke-dashoffset: 20; opacity: 0; }
  38%, 88% { stroke-dashoffset: 0; opacity: 1; }
  94%, 100% { stroke-dashoffset: 20; opacity: 0; }
}
@keyframes safesort-folder-active {
  0%, 36% { opacity: 0; }
  42%, 88% { opacity: .85; }
  94%, 100% { opacity: 0; }
}
@keyframes safesort-route-apply-1 {
  0%, 40% { opacity: .15; }
  44%, 50% { opacity: .6; }
  56%, 100% { opacity: .15; }
}
@keyframes safesort-route-apply-2 {
  0%, 49% { opacity: .15; }
  53%, 59% { opacity: .6; }
  65%, 100% { opacity: .15; }
}
@keyframes safesort-mover-1 {
  0%, 41% { opacity: 0; transform: translate(0,0) scale(1); }
  44% { opacity: 1; transform: translate(10px,3px) scale(1); }
  50%, 100% { opacity: 0; transform: translate(74px,21px) scale(.5); }
}
@keyframes safesort-mover-2 {
  0%, 50% { opacity: 0; transform: translate(0,0) scale(1); }
  53% { opacity: 1; transform: translate(10px,3px) scale(1); }
  59%, 100% { opacity: 0; transform: translate(74px,41px) scale(.5); }
}
@keyframes safesort-folder-pulse-1 {
  0%, 46% { opacity: 0; transform: scale(.6); }
  50% { opacity: .7; transform: scale(1.6); }
  56%, 100% { opacity: 0; transform: scale(2.2); }
}
@keyframes safesort-folder-pulse-2 {
  0%, 55% { opacity: 0; transform: scale(.6); }
  59% { opacity: .7; transform: scale(1.6); }
  65%, 100% { opacity: 0; transform: scale(2.2); }
}
@keyframes safesort-history-row {
  0%, 44% { opacity: 0; transform: translateX(-6px); }
  48%, 88% { opacity: .55; transform: translateX(0); }
  94%, 100% { opacity: 0; transform: translateX(-6px); }
}
@keyframes safesort-duplicate-pulse {
  0%, 59% { opacity: .85; transform: scale(1); }
  63% { opacity: 1; transform: scale(1.06); }
  68%, 100% { opacity: .85; transform: scale(1); }
}
@keyframes safesort-duplicate-check-badge {
  0%, 64% { opacity: 0; }
  70%, 88% { opacity: 1; }
  94%, 100% { opacity: 0; }
}
@keyframes safesort-duplicate-check {
  0%, 64% { stroke-dashoffset: 14; opacity: 0; }
  70%, 88% { stroke-dashoffset: 0; opacity: 1; }
  94%, 100% { stroke-dashoffset: 14; opacity: 0; }
}
@keyframes safesort-hash-tick {
  0%, 64% { opacity: .3; }
  70%, 88% { opacity: .85; }
  94%, 100% { opacity: .3; }
}
@keyframes safesort-history-check-badge {
  0%, 72% { opacity: 0; }
  78%, 88% { opacity: 1; }
  94%, 100% { opacity: 0; }
}
@keyframes safesort-history-check {
  0%, 72% { stroke-dashoffset: 12; opacity: 0; }
  78%, 88% { stroke-dashoffset: 0; opacity: 1; }
  94%, 100% { stroke-dashoffset: 12; opacity: 0; }
}
@keyframes safesort-undo-appear {
  0%, 72% { opacity: 0; transform: translate(300px,158px) scale(.6) rotate(-18deg); }
  78%, 88% { opacity: 1; transform: translate(300px,158px) scale(.85) rotate(0deg); }
  94%, 100% { opacity: 0; transform: translate(300px,158px) scale(.6) rotate(-18deg); }
}

/* bouncing-balls-oop: four independent ball instances, each on its own
   closed route and duration, bouncing off the shared playfield's walls at
   their own pace — the point being several simultaneous objects, not one
   ball with extras pasted on. Trails reuse each ball's own movement
   keyframes on a small negative delay instead of a static dashed path (the
   single-ball sibling's device), a "class" node briefly fans three lines
   toward three balls, and a corner ring ticks once per the longest cycle
   for the one shared update loop. Scoped to .oop-* classes (its own scene,
   not .project-art__subject) so this stays isolated from every other
   project's generic icon animation. */
.project-art--bouncing-balls-oop .oop-instance-link { transform-box: fill-box; transform-origin: center; animation: oop-instance-link 7.2s ease-in-out infinite; }
.project-art--bouncing-balls-oop .oop-ball-travel,
.project-art--bouncing-balls-oop .oop-ball-squash,
.project-art--bouncing-balls-oop .oop-trail,
.project-art--bouncing-balls-oop .oop-impact,
.project-art--bouncing-balls-oop .oop-loop-ring { transform-box: fill-box; transform-origin: center; }
.project-art--bouncing-balls-oop .oop-ball-travel--a { animation: oop-move-a 5.7s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-squash--a { animation: oop-squash-a 5.7s linear infinite; }
.project-art--bouncing-balls-oop .oop-trail--a1 { animation: oop-move-a 5.7s linear infinite; animation-delay: -.12s; }
.project-art--bouncing-balls-oop .oop-trail--a2 { animation: oop-move-a 5.7s linear infinite; animation-delay: -.24s; }
.project-art--bouncing-balls-oop .oop-impact--a1 { animation: oop-impact-a1 5.7s linear infinite; }
.project-art--bouncing-balls-oop .oop-impact--a2 { animation: oop-impact-a2 5.7s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-travel--b { animation: oop-move-b 4.8s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-squash--b { animation: oop-squash-b 4.8s linear infinite; }
.project-art--bouncing-balls-oop .oop-trail--b1 { animation: oop-move-b 4.8s linear infinite; animation-delay: -.14s; }
.project-art--bouncing-balls-oop .oop-impact--b { animation: oop-impact-b 4.8s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-travel--c { animation: oop-move-c 6.4s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-squash--c { animation: oop-squash-c 6.4s linear infinite; }
.project-art--bouncing-balls-oop .oop-trail--c1 { animation: oop-move-c 6.4s linear infinite; animation-delay: -.16s; }
.project-art--bouncing-balls-oop .oop-impact--c { animation: oop-impact-c 6.4s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-travel--d { animation: oop-move-d 7.2s linear infinite; }
.project-art--bouncing-balls-oop .oop-ball-squash--d { animation: oop-squash-d 7.2s linear infinite; }
.project-art--bouncing-balls-oop .oop-trail--d1 { animation: oop-move-d 7.2s linear infinite; animation-delay: -.18s; }
.project-art--bouncing-balls-oop .oop-impact--d { animation: oop-impact-d 7.2s linear infinite; }
.project-art--bouncing-balls-oop .oop-loop-ring { animation: oop-loop-ring 7.2s linear infinite; }

@keyframes oop-instance-link {
  0%, 3% { opacity: 0; }
  6%, 11% { opacity: 1; }
  17%, 100% { opacity: 0; }
}
@keyframes oop-move-a {
  0% { transform: translate(0, 0); }
  27% { transform: translate(264px, -88px); }
  30% { transform: translate(264px, -88px); }
  50% { transform: translate(87px, -128px); }
  53% { transform: translate(87px, -128px); }
  82% { transform: translate(0, 0); }
  100% { transform: translate(0, 0); }
}
@keyframes oop-squash-a {
  0%, 26% { transform: scale(1, 1); }
  28% { transform: scale(.93, 1.05); }
  30%, 49% { transform: scale(1, 1); }
  51% { transform: scale(1.05, .94); }
  53%, 100% { transform: scale(1, 1); }
}
@keyframes oop-impact-a1 {
  0%, 25% { opacity: .35; transform: scale(1); }
  28% { opacity: .95; transform: scale(1.7); }
  32%, 100% { opacity: .35; transform: scale(1); }
}
@keyframes oop-impact-a2 {
  0%, 48% { opacity: 0; transform: scale(1); }
  51% { opacity: .95; transform: scale(1.7); }
  55%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes oop-move-b {
  0% { transform: translate(0, 0); }
  35% { transform: translate(286px, -7px); }
  38% { transform: translate(286px, -7px); }
  78% { transform: translate(0, 0); }
  100% { transform: translate(0, 0); }
}
@keyframes oop-squash-b {
  0%, 34% { transform: scale(1, 1); }
  36% { transform: scale(.93, 1.05); }
  38%, 100% { transform: scale(1, 1); }
}
@keyframes oop-impact-b {
  0%, 33% { opacity: 0; transform: scale(1); }
  36% { opacity: .9; transform: scale(1.6); }
  40%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes oop-move-c {
  0% { transform: translate(0, 0); }
  45% { transform: translate(-17px, 131px); }
  48% { transform: translate(-17px, 131px); }
  85% { transform: translate(0, 0); }
  100% { transform: translate(0, 0); }
}
@keyframes oop-squash-c {
  0%, 44% { transform: scale(1, 1); }
  46% { transform: scale(1.05, .93); }
  48%, 100% { transform: scale(1, 1); }
}
@keyframes oop-impact-c {
  0%, 43% { opacity: 0; transform: scale(1); }
  46% { opacity: .9; transform: scale(1.6); }
  50%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes oop-move-d {
  0% { transform: translate(0, 0); }
  55% { transform: translate(-272px, -20px); }
  58% { transform: translate(-272px, -20px); }
  90% { transform: translate(0, 0); }
  100% { transform: translate(0, 0); }
}
@keyframes oop-squash-d {
  0%, 54% { transform: scale(1, 1); }
  56% { transform: scale(.93, 1.05); }
  58%, 100% { transform: scale(1, 1); }
}
@keyframes oop-impact-d {
  0%, 53% { opacity: 0; transform: scale(1); }
  56% { opacity: .9; transform: scale(1.6); }
  60%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes oop-loop-ring {
  0%, 60% { opacity: 0; transform: scale(1); }
  63% { opacity: .6; transform: scale(1); }
  70%, 100% { opacity: 0; transform: scale(3.6); }
}

@keyframes project-route { to { stroke-dashoffset: -44; } }
@keyframes project-node { 0%, 68%, 100% { opacity: .28; transform: scale(1); } 78% { opacity: .78; transform: scale(1.35); } }
@keyframes project-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes project-bounce { 0%, 100% { transform: translateY(0) scaleY(1); } 45% { transform: translateY(-8px) scaleY(1.02); } 78% { transform: translateY(1px) scaleY(.96); } }
@keyframes project-exhaust { 0%, 100% { opacity: .45; transform: scaleY(.78); } 50% { opacity: 1; transform: scaleY(1.08); } }
@keyframes project-spark { 0%, 100% { opacity: .62; transform: scale(.88) rotate(-2deg); } 50% { opacity: 1; transform: scale(1.04) rotate(2deg); } }
@keyframes project-tilt { 0%, 100% { transform: rotate(0); } 50% { transform: rotate(3deg); } }
@keyframes project-mark { 0%, 100% { opacity: .6; } 45%, 72% { opacity: 1; } }

/* ==========================================================================
   СПРАВОЧНИК — clean technical reference board
   ========================================================================== */
.reference-hero { display: grid; grid-template-columns: minmax(0, .82fr) minmax(460px, 1.18fr); gap: clamp(44px, 6vw, 84px); align-items: center; margin-bottom: 44px; }
.reference-hero__copy { min-width: 0; }
.home-section .reference-hero__copy .sub { margin-bottom: 18px; }
.reference-hero__note { max-width: 510px; margin: 0; color: var(--color-text-muted); font-size: 14px; line-height: 1.65; }
.reference-hero__art { min-width: 0; }
.reference-art { display: block; width: 100%; height: auto; filter: drop-shadow(0 24px 32px rgba(13,2,48,.18)); }
.reference-art__search { animation: reference-search 6s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.reference-art__nodes circle { animation: reference-node 5.5s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.reference-art__nodes circle:nth-child(2) { animation-delay: -1.4s; }
.reference-art__nodes circle:nth-child(3) { animation-delay: -2.8s; }
.reference-art__nodes circle:nth-child(4) { animation-delay: -4.2s; }
@keyframes reference-search { 0%, 100% { transform: translate(0, 0) rotate(0); } 50% { transform: translate(-6px, 4px) rotate(-2deg); } }
@keyframes reference-node { 0%, 70%, 100% { transform: scale(1); } 82% { transform: scale(1.45); } }

.reference-board { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.reference-card {
  display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; align-items: center; gap: 16px; min-width: 0; padding: 20px 22px; background: var(--surface-2);
  border: var(--border-hairline); border-radius: var(--radius-md); text-decoration: none; color: var(--color-text-primary);
  transition: border-color var(--duration-base) var(--ease-standard), box-shadow var(--duration-base) var(--ease-standard), transform var(--duration-base) var(--ease-standard);
}
.reference-card:hover { border-color: var(--color-brand-blue); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.reference-card:focus-visible { outline-width: 3px; outline-offset: 4px; }
.reference-card .ri {
  color: var(--color-brand-blue); width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, #eef3ff, #f4efff); border: 1px solid rgba(24,93,250,.08); border-radius: 12px;
}
.reference-card .ri .cs-icon { margin-right: 0; }
.reference-card__copy { min-width: 0; }
.reference-card .rt { font-weight: 600; font-size: 15px; }
.reference-card .rs { margin-top: 3px; font-size: 13px; line-height: 1.45; color: var(--color-text-muted); }
.reference-card__arrow { color: var(--color-brand-blue); font-size: 17px; transition: transform var(--duration-fast) var(--ease-standard); }
.reference-card:hover .reference-card__arrow { transform: translateX(3px); }

/* ==========================================================================
   SIGNATURE AUTHOR PROFILE — real portrait + Cartesian systems drawing
   ========================================================================== */
.author-profile {
  position: relative; isolation: isolate; overflow: hidden; color: #f7f8ff;
  background:
    radial-gradient(ellipse 660px 560px at 86% 35%, rgba(61,114,255,.15), transparent 69%),
    radial-gradient(ellipse 720px 620px at 4% 86%, rgba(124,92,255,.1), transparent 72%),
    linear-gradient(132deg, #0b0724 0%, #100a2d 52%, #0b0724 100%);
  border-block: 1px solid rgba(168,176,199,.12);
}
.author-profile::before {
  content: ""; position: absolute; z-index: -2; inset: 0; pointer-events: none;
  opacity: .72;
  background-image:
    repeating-linear-gradient(90deg, rgba(168,176,199,.05) 0 1px, transparent 1px 52px),
    repeating-linear-gradient(0deg, rgba(168,176,199,.05) 0 1px, transparent 1px 52px);
  -webkit-mask-image: radial-gradient(ellipse 92% 82% at 55% 48%, #000 20%, transparent 82%);
  mask-image: radial-gradient(ellipse 92% 82% at 55% 48%, #000 20%, transparent 82%);
}
.author-profile::after {
  content: ""; position: absolute; z-index: -1; width: 440px; height: 440px; right: 4%; top: 15%;
  border-radius: 50%; pointer-events: none; opacity: .44; filter: blur(46px);
  background: radial-gradient(circle, rgba(61,114,255,.18), rgba(124,92,255,.06) 48%, transparent 72%);
}
.author-profile.is-profile-revealed.is-profile-in-view::after { animation: author-ambient-glow 20s ease-in-out infinite alternate; }
.author-profile__geometry { position: absolute; z-index: -1; inset: 0; pointer-events: none; }
.author-profile__geometry svg { display: block; width: 100%; height: 100%; }
.author-profile__geometry path {
  fill: none; stroke: rgba(61,114,255,.16); stroke-width: 1; vector-effect: non-scaling-stroke;
}
.author-profile__geometry circle {
  fill: #0b0724; stroke: rgba(61,114,255,.52); stroke-width: 1.5; vector-effect: non-scaling-stroke;
}
.author-profile__coordinate {
  position: absolute; color: rgba(168,176,199,.3); font: 500 9px/1 'JetBrains Mono', monospace;
  letter-spacing: .09em; text-transform: uppercase;
}
.author-profile__coordinate--nw { left: max(24px, calc((100% - 1320px) / 2)); top: 31px; }
.author-profile__coordinate--se { right: max(24px, calc((100% - 1320px) / 2)); bottom: 29px; }
.author-profile__ambient-node {
  position: absolute; width: 7px; height: 7px; border: 1px solid rgba(61,114,255,.56);
  border-radius: 50%; background: #0b0724; box-shadow: 0 0 0 5px rgba(61,114,255,.045);
}
.author-profile__ambient-node--a { left: 7.8%; top: 30%; }
.author-profile__ambient-node--b { right: 7.2%; bottom: 16%; }
.author-profile.is-profile-revealed.is-profile-in-view .author-profile__ambient-node { animation: author-node-breathe 12s ease-in-out infinite; }
.author-profile.is-profile-revealed.is-profile-in-view .author-profile__ambient-node--b { animation-delay: -6s; }

.author-profile__inner { width: min(1320px, 100%); margin: 0 auto; padding: clamp(96px, 8vw, 132px) 24px clamp(84px, 7vw, 112px); }
.author-profile__layout {
  display: grid; grid-template-columns: minmax(0, 1.48fr) minmax(340px, .92fr);
  grid-template-areas: "intro portrait" "body portrait" "metadata metadata";
  column-gap: clamp(42px, 5.3vw, 78px); row-gap: 42px; align-items: start;
}
.author-profile__intro { grid-area: intro; min-width: 0; }
.author-profile__eyebrow {
  display: flex; align-items: center; gap: 12px; margin: 0 0 22px; color: #8fb7fe;
  font: 600 11px/1.25 'JetBrains Mono', monospace; letter-spacing: .105em; text-transform: uppercase;
}
.author-profile__eyebrow::before { content: ""; width: 34px; height: 1px; background: #3d72ff; box-shadow: 0 0 8px rgba(61,114,255,.42); }
.author-profile__name {
  max-width: 620px; margin: 0 0 16px; color: #f7f8ff; font-size: clamp(38px, 3.2vw, 52px);
  line-height: 1.1; letter-spacing: -.03em; text-wrap: balance;
}
.author-profile__role { margin: 0; color: #dfe3ef; font: 600 clamp(17px, 1.55vw, 21px)/1.45 'Sora', sans-serif; }
.author-profile__specialization {
  display: flex; flex-wrap: wrap; gap: 0; max-width: 760px; margin: 19px 0 0;
  color: #8fb7fe; font: 500 12px/1.55 'JetBrains Mono', monospace; letter-spacing: .025em;
}
.author-profile__specialization span { white-space: nowrap; }
.author-profile__specialization span:not(:last-child)::after { content: " · "; margin-inline: 8px; color: rgba(168,176,199,.42); }

.author-portrait { grid-area: portrait; width: min(100%, 415px); margin: 14px auto 0; align-self: start; }
.author-portrait__canvas { --author-frame-inset: 26px; position: relative; aspect-ratio: 4 / 5; isolation: isolate; }
.author-portrait picture {
  position: absolute; z-index: 0;
  inset: calc(var(--author-frame-inset) * 1.25) var(--author-frame-inset);
  display: block; overflow: hidden;
  background: #171039; box-shadow: 0 26px 58px rgba(0,0,0,.34), 0 0 0 1px rgba(247,248,255,.08);
}
.author-portrait img {
  display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%;
  transform: scale(1); transition: transform 420ms var(--ease-out), filter 420ms var(--ease-standard);
  filter: saturate(.92) contrast(1.025);
}
.author-portrait__frame { position: absolute; z-index: 2; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.author-portrait__frame path, .author-portrait__frame circle { vector-effect: non-scaling-stroke; }
.author-portrait__outline, .author-portrait__corners, .author-portrait__ticks, .author-portrait__route, .author-portrait__signal {
  fill: none; stroke-linecap: square; stroke-linejoin: miter;
}
.author-portrait__outline { stroke: rgba(168,176,199,.38); stroke-width: 1; }
.author-portrait__corners { stroke: rgba(61,114,255,.84); stroke-width: 1.4; }
.author-portrait__ticks { stroke: rgba(168,176,199,.38); stroke-width: 1; }
.author-portrait__route { stroke: rgba(124,92,255,.58); stroke-width: 1.2; }
.author-portrait__signal { stroke: #8fb7fe; stroke-width: 2; stroke-dasharray: .08 .92; filter: drop-shadow(0 0 4px rgba(61,114,255,.58)); }
.author-portrait__nodes circle { fill: #0b0724; stroke: #8fb7fe; stroke-width: 1.3; }
.author-portrait__label {
  position: absolute; z-index: 3; padding: 3px 5px; color: rgba(223,227,239,.62); background: #0d0826;
  font: 500 8px/1 'JetBrains Mono', monospace; letter-spacing: .08em; white-space: nowrap;
}
.author-portrait__label--systems { left: -5px; top: 24%; transform: rotate(-90deg) translateX(-100%); transform-origin: left top; }
.author-portrait__label--ai { right: -4px; top: 20%; }
.author-portrait__label--avionics { right: -6px; bottom: 19%; transform: rotate(90deg) translateX(100%); transform-origin: right bottom; }
.author-portrait__label--id { left: 8%; bottom: -2px; }
.author-portrait figcaption {
  display: flex; align-items: center; gap: 10px; margin: 14px 26px 0; color: rgba(168,176,199,.58);
  font: 500 8.5px/1.4 'JetBrains Mono', monospace; letter-spacing: .07em; text-transform: uppercase;
}
.author-portrait figcaption::before { content: ""; flex: 0 0 18px; height: 1px; background: rgba(61,114,255,.58); }

.author-profile__body { grid-area: body; min-width: 0; }
.author-bio { max-width: 760px; }
.author-bio p { max-width: 70ch; margin: 0; color: #a8b0c7; font-size: 14px; line-height: 1.72; }
.author-bio p + p { margin-top: 12px; }
.author-bio .author-bio__lead {
  max-width: 65ch; margin-bottom: 20px; color: #f0f2f8; font-size: clamp(17px, 1.5vw, 20px); line-height: 1.62;
}

.author-domains {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 28px;
  margin: 38px 0 0; padding: 0; border-top: 1px solid rgba(168,176,199,.15); list-style: none;
}
.author-domain {
  position: relative; display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px;
  min-width: 0; padding: 17px 0 16px; border-bottom: 1px solid rgba(168,176,199,.15);
}
.author-domain::after {
  content: ""; position: absolute; left: 0; bottom: -1px; width: 22px; height: 1px; background: #3d72ff;
  box-shadow: 0 0 7px rgba(61,114,255,.44); transition: width 300ms var(--ease-out), box-shadow 300ms var(--ease-standard);
}
.author-domain--wide { grid-column: 1 / -1; }
.author-domain__index { padding-top: 3px; color: #8fb7fe; font: 500 9px/1 'JetBrains Mono', monospace; letter-spacing: .06em; }
.author-domain h3 { margin: 0 0 5px; color: #f7f8ff; font: 650 12px/1.35 'Sora', sans-serif; letter-spacing: -.005em; text-transform: uppercase; }
.author-domain p { margin: 0; color: rgba(168,176,199,.78); font: 400 10.5px/1.5 'JetBrains Mono', monospace; }

.author-affiliations { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; margin-top: 34px; }
.author-affiliation { min-width: 0; padding-left: 15px; border-left: 1px solid rgba(61,114,255,.48); }
.author-affiliation__label { display: block; margin-bottom: 8px; color: rgba(168,176,199,.58); font: 500 8px/1.2 'JetBrains Mono', monospace; letter-spacing: .1em; }
.author-affiliation a, .author-affiliation h3 { margin: 0; color: #f7f8ff; font: 650 15px/1.4 'Sora', sans-serif; }
.author-affiliation a {
  display: inline-flex; gap: 7px; align-items: center; text-decoration: none;
  text-decoration-color: transparent; text-underline-offset: 4px;
  transition: color 220ms var(--ease-standard), text-decoration-color 220ms var(--ease-standard), filter 220ms var(--ease-standard);
}
.author-affiliation a span { color: #8fb7fe; transition: transform 220ms var(--ease-out); }
.author-affiliation p { margin: 4px 0 0; color: #a8b0c7; font-size: 12px; line-height: 1.45; }
.author-affiliation a:focus-visible { outline: 2px solid #8fb7fe; outline-offset: 5px; border-radius: 2px; }

.author-metadata {
  grid-area: metadata; display: grid; grid-template-columns: .8fr 1.45fr .9fr 1.1fr; margin: 8px 0 0; padding: 0;
  border-block: 1px solid rgba(168,176,199,.16);
}
.author-metadata div { min-width: 0; padding: 17px 20px 16px 0; }
.author-metadata div + div { padding-left: 20px; border-left: 1px solid rgba(168,176,199,.12); }
.author-metadata dt { color: #8fb7fe; font: 600 9px/1.3 'JetBrains Mono', monospace; letter-spacing: .08em; }
.author-metadata dd { margin: 5px 0 0; color: rgba(223,227,239,.7); font: 500 9px/1.45 'JetBrains Mono', monospace; text-transform: uppercase; }

/* Content remains complete without JavaScript. Enhancement hides only the
   not-yet-seen state, then releases all entrance transform ownership. */
.author-profile.is-enhanced .author-reveal { opacity: 0; transform: translate3d(0, 12px, 0); }
.author-profile.is-enhanced .author-reveal--portrait { transform: scale(.985); }
.author-profile.is-enhanced.is-profile-entering .author-reveal { animation: author-content-enter 680ms var(--ease-out) both; }
.author-profile.is-enhanced.is-profile-entering .author-reveal--eyebrow { animation-delay: 100ms; }
.author-profile.is-enhanced.is-profile-entering .author-reveal--name { animation-delay: 180ms; }
.author-profile.is-enhanced.is-profile-entering .author-reveal--role { animation-delay: 260ms; }
.author-profile.is-enhanced.is-profile-entering .author-reveal--portrait { animation: author-portrait-enter 800ms var(--ease-out) 320ms both; }
.author-profile.is-enhanced.is-profile-entering .author-bio .author-reveal { animation-duration: 420ms; }
.author-profile.is-enhanced.is-profile-entering .author-bio .author-reveal:nth-child(1) { animation-delay: 500ms; }
.author-profile.is-enhanced.is-profile-entering .author-bio .author-reveal:nth-child(2) { animation-delay: 560ms; }
.author-profile.is-enhanced.is-profile-entering .author-bio .author-reveal:nth-child(3) { animation-delay: 620ms; }
.author-profile.is-enhanced.is-profile-entering .author-bio .author-reveal:nth-child(4) { animation-delay: 680ms; }
.author-profile.is-enhanced.is-profile-entering .author-domain { animation-duration: 360ms; }
.author-profile.is-enhanced.is-profile-entering .author-domain:nth-child(1) { animation-delay: 650ms; }
.author-profile.is-enhanced.is-profile-entering .author-domain:nth-child(2) { animation-delay: 730ms; }
.author-profile.is-enhanced.is-profile-entering .author-domain:nth-child(3) { animation-delay: 810ms; }
.author-profile.is-enhanced.is-profile-entering .author-domain:nth-child(4) { animation-delay: 890ms; }
.author-profile.is-enhanced.is-profile-entering .author-domain:nth-child(5) { animation-delay: 970ms; }
.author-profile.is-enhanced.is-profile-entering .author-reveal--affiliations { animation-delay: 820ms; animation-duration: 400ms; }
.author-profile.is-enhanced.is-profile-entering .author-reveal--metadata { animation-delay: 900ms; animation-duration: 340ms; }
.author-profile.is-profile-revealed .author-reveal { opacity: 1; transform: none; animation: none; }

.author-profile.is-enhanced .author-portrait__outline,
.author-profile.is-enhanced .author-portrait__corners,
.author-profile.is-enhanced .author-portrait__route { stroke-dasharray: 1; stroke-dashoffset: 1; }
.author-profile.is-enhanced .author-portrait__nodes { opacity: 0; }
.author-profile.is-enhanced .author-portrait__signal { opacity: 0; stroke-dashoffset: 1; }
.author-profile.is-profile-entering .author-portrait__outline,
.author-profile.is-profile-entering .author-portrait__corners,
.author-profile.is-profile-entering .author-portrait__route { animation: author-frame-draw 800ms var(--ease-standard) 420ms both; }
.author-profile.is-profile-entering .author-portrait__nodes { animation: author-frame-nodes 360ms var(--ease-standard) 720ms both; }
.author-profile.is-profile-entering .author-portrait__signal { animation: author-frame-signal 560ms linear 760ms both; }
.author-profile.is-profile-revealed .author-portrait__outline,
.author-profile.is-profile-revealed .author-portrait__corners,
.author-profile.is-profile-revealed .author-portrait__route { stroke-dashoffset: 0; animation: none; }
.author-profile.is-profile-revealed .author-portrait__nodes { opacity: 1; animation: none; }
.author-profile.is-profile-revealed .author-portrait__signal { opacity: .62; stroke-dashoffset: 0; animation: none; }

@media (hover: hover) and (pointer: fine) {
  .author-portrait:hover img { transform: scale(1.007); filter: saturate(.98) contrast(1.035); }
  .author-portrait:hover .author-portrait__outline { stroke: rgba(168,176,199,.62); }
  .author-portrait:hover .author-portrait__corners { stroke: #8fb7fe; filter: drop-shadow(0 0 4px rgba(61,114,255,.42)); }
  .author-domain:hover::after { width: 58px; box-shadow: 0 0 11px rgba(61,114,255,.7); }
  .author-affiliation a:hover { color: #8fb7fe; text-decoration: underline; text-decoration-color: rgba(143,183,254,.55); filter: drop-shadow(0 0 8px rgba(61,114,255,.22)); }
  .author-affiliation a:hover span { transform: translate3d(2px, -2px, 0); }
}

@keyframes author-content-enter {
  from { opacity: 0; transform: translate3d(0, 12px, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}
@keyframes author-portrait-enter {
  from { opacity: 0; transform: scale(.985); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes author-frame-draw { to { stroke-dashoffset: 0; } }
@keyframes author-frame-nodes { from { opacity: 0; } to { opacity: 1; } }
@keyframes author-frame-signal {
  0% { opacity: 0; stroke-dashoffset: 1; }
  20%, 82% { opacity: .9; }
  100% { opacity: .62; stroke-dashoffset: 0; }
}
@keyframes author-ambient-glow { from { transform: translate3d(-2px, -2px, 0) scale(.98); } to { transform: translate3d(2px, 2px, 0) scale(1.02); } }
@keyframes author-node-breathe { 0%, 72%, 100% { opacity: .44; } 84% { opacity: .92; } }

.home-footer { background: var(--surface-inverse-1); color: var(--gray-400); padding: 44px 24px; text-align: center; font-size: 13px; }
.home-footer__legal { margin-top: 10px; }
.home-footer__legal a { color: var(--gray-400); text-decoration: none; border-bottom: 1px dotted currentColor; }
.home-footer__legal a:hover, .home-footer__legal a:focus-visible { color: #fff; }

/* ---------- Reference — licence card accent (violet -> electric-blue) ---------- */
.reference-card--license {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--violet-500) 0%, var(--blue-500) 100%);
  border-color: transparent;
  color: #fff;
}
.reference-card--license::after {
  content: "";
  position: absolute;
  top: -55%;
  right: -15%;
  width: 160px;
  height: 160px;
  background: radial-gradient(circle, rgba(255, 255, 255, .38), transparent 70%);
  pointer-events: none;
}
.reference-card--license .ri { background: rgba(255, 255, 255, .92); border-color: rgba(255, 255, 255, .5); color: var(--violet-500); }
.reference-card--license .rt { color: #fff; }
.reference-card--license .rs { color: rgba(255, 255, 255, .85); }
.reference-card--license .reference-card__arrow { color: #fff; }
.reference-card--license:hover { border-color: transparent; box-shadow: 0 14px 32px rgba(91, 36, 249, .35); }

/* ---------- Responsive ---------- */
@media (max-width: 1100px) {
  .home-hero__inner { grid-template-columns: 1fr; gap: 42px; }
  .home-hero__content { width: min(760px, 100%); }
  .home-hero h1 { max-width: 760px; }
  .hero-system { width: min(680px, 100%); justify-self: center; }
  .author-profile__layout { column-gap: 42px; }
  .author-profile__name { font-size: clamp(36px, 3.6vw, 46px); }
  .reference-hero { grid-template-columns: minmax(0, .88fr) minmax(400px, 1.12fr); gap: 42px; }
  .practice-hero { grid-template-columns: minmax(0, .88fr) minmax(380px, 1.02fr); gap: 38px; }
}

@media (max-width: 900px) {
  .course-path { max-width: 760px; padding-left: 68px; }
  .course-path__rail--desktop { display: none; }
  .course-path__rail--mobile { display: block; left: 0; top: 0; width: 52px; height: 100%; }
  .course-path__stages { grid-template-columns: 1fr; gap: 18px; }
  .course-stage__node { left: -42px; top: 30px; }
  .course-stage__content, .course-stage:nth-child(even) .course-stage__content { min-height: 0; margin-top: 0; padding: 24px 26px 25px; }
  .course-stage h3 { min-height: 0; }
  .author-profile__layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "intro" "portrait" "body" "metadata";
    row-gap: 42px;
  }
  .author-profile__intro, .author-profile__body { width: min(760px, 100%); }
  .author-portrait { width: min(100%, 440px); margin-top: 2px; justify-self: center; }
  .author-profile__name { max-width: none; font-size: clamp(34px, 5.2vw, 42px); }
  .reference-hero { grid-template-columns: 1fr; gap: 34px; }
  .reference-hero__copy { max-width: 680px; }
  .reference-hero__art { width: min(640px, 100%); }
  .practice-hero { grid-template-columns: 1fr; gap: 28px; margin-bottom: 32px; }
  .practice-hero__copy { max-width: 680px; }
  .practice-hero__art { width: min(480px, 100%); }
}

@media (max-width: 860px) {
  .about-grid { grid-template-columns: 1fr; gap: 54px; }
  .about-copy { max-width: 680px; }
  .about-stats { width: min(650px, 100%); justify-self: center; }
  .projects-grid { grid-template-columns: repeat(2, 1fr); }
  .home-section { padding: 60px 20px; }
  .course-overview { padding-top: 74px; padding-bottom: 64px; }
  .course-format { padding-top: 52px; padding-bottom: 84px; }
  .course-section-heading { margin-bottom: 34px; }
  .course-experience__axis--y { left: 88%; }
  .jp-top { align-items: baseline; gap: 10px; }

  /* Mobile backplane: one bus, short routes, full-width mounted modules. */
  .pcb-board { padding: 26px 18px 32px; border-radius: 16px; }
  .pcb-surface { opacity: .48; }
  .journey-progress { padding: 16px 18px 20px; margin-bottom: 30px; }
  .journey-progress::after { left: 9px; height: 31px; }
  .journey-node { grid-template-columns: 56px minmax(0,1fr); min-height: 178px; }
  .pcb-bus { left: 9px; }
  .journey-node .jn-dot { grid-column: 1; justify-self: start; margin-left: 16px; }
  .journey-node .jn-route, .journey-node:nth-child(odd) .jn-route { left: 22px; width: 34px; transform: none; }
  .journey-node:nth-child(odd) .jn-card, .journey-node:nth-child(even) .jn-card { grid-column: 2; }
  .journey-node:nth-child(odd) .jn-pins { left: -13px; right: auto; }
  .jn-card { padding: 17px 16px; }
  .jn-part { font-size: 8px; letter-spacing: .5px; }
  .jn-title { font-size: 14px; }

}

@media (max-width: 700px) {
  .home-hero { padding-top: 60px; }
  .home-hero__inner { gap: 34px; }
  .home-hero h1 { font-size: clamp(36px, 8vw, 48px); }
  .home-hero p { font-size: 17px; }
  .hero-token--range, .hero-token--lambda { display: none; }
  .course-experience::after { right: -16px; font-size: 112px; }
  .course-section-lead { font-size: 16px; }
  .about-copy > p { font-size: 16px; }
  .about-stats {
    height: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: auto;
    gap: 12px;
  }
  .about-stats::before, .about-stats__routes { display: none; }
  .about-stat { min-height: 160px; padding: 16px 16px 18px; }
  .about-stat--chapters { grid-column: 1 / -1; grid-row: 1; min-height: 180px; }
  .about-stat--pages { grid-column: 1; grid-row: 2; }
  .about-stat--projects { grid-column: 2; grid-row: 2; }
  .about-stat--practice { grid-column: 1 / -1; grid-row: 3; min-height: 176px; }
  .about-stat .num { font-size: 36px; }
  .about-stat--chapters .num { font-size: 48px; }
  .about-stat--practice .num { font-size: 44px; }
  .course-experience__bridge { width: calc(100% - 40px); }

  /* Practice chapter cards: stack into clean, non-overlapping rows instead
     of squeezing chapter badge / title / progress / chevron into one line. */
  .pcg-summary { flex-wrap: wrap; row-gap: 10px; padding: 14px 40px 14px 14px; position: relative; }
  .pcg-chevron { position: absolute; top: 14px; right: 10px; }
  .pcg-progress { flex: 1 1 100%; min-width: 0; }
  .pcg-num { padding: 5px 7px; font-size: 10px; }
}

@media (max-width: 600px) {
  .projects-grid { grid-template-columns: 1fr; }
  .reference-board { grid-template-columns: 1fr; }
  .reference-hero { margin-bottom: 34px; }
  .reference-hero__note { font-size: 13.5px; }
  .reference-card { padding: 17px; }
  .home-hero { padding: 52px 20px 50px; }
  .home-hero__inner { gap: 30px; }
  .home-hero .kicker { gap: 8px; margin-bottom: 18px; font-size: 10.5px; letter-spacing: .06em; }
  .home-hero .kicker img { width: 21px; height: 25px; }
  .home-hero h1 { font-size: clamp(33px, 9.3vw, 40px); line-height: 1.1; margin-bottom: 20px; letter-spacing: -.03em; }
  .home-hero p { font-size: 16px; line-height: 1.58; margin-bottom: 28px; }
  .home-cta { display: grid; width: 100%; gap: 10px; }
  .home-cta .btn { width: 100%; }

  .hero-system { width: min(390px, 100%); height: 430px; aspect-ratio: auto; }
  .hero-system::after { inset: 18% 3% 7%; filter: blur(20px); }
  .hero-system__grid {
    inset: -4px;
    background-image:
      repeating-linear-gradient(90deg, rgba(143,183,254,.06) 0 1px, transparent 1px 28px),
      repeating-linear-gradient(0deg, rgba(143,183,254,.06) 0 1px, transparent 1px 28px);
    -webkit-mask-image: radial-gradient(ellipse 80% 82% at 50% 48%, #000 20%, transparent 82%);
    mask-image: radial-gradient(ellipse 80% 82% at 50% 48%, #000 20%, transparent 82%);
  }
  .hero-system__prompt { right: 1%; top: 36%; font-size: 88px; }
  .hero-token--def { left: 3%; top: 39%; }
  .hero-token--py { right: 4%; bottom: 27%; }
  .hero-connectors--desktop { display: none; }
  .hero-connectors--mobile { display: block; }

  .hero-core { left: 50%; top: 45.1%; width: 88px; height: 88px; }
  .hero-core__orbit { inset: -7px; }
  .hero-core__mark { height: 34px; }
  .hero-core__mark img { width: 27px; height: 33px; }
  .hero-core__name { font-size: 9px; }
  .hero-core__runtime { font-size: 6.6px; }

  .hero-module__head { height: 27px; padding: 0 8px; font-size: 7px; }
  .hero-module__label { gap: 5px; font-size: 8px; }
  .hero-module__label i { width: 5px; height: 5px; }
  .hero-module--code { left: 0; top: 0; width: 63%; height: 130px; }
  .hero-module--graph { left: auto; right: 0; top: 8%; width: 35%; height: 112px; }
  .hero-module--app { left: 0; right: auto; top: auto; bottom: 0; width: 47%; height: 108px; }
  .hero-module--game { left: auto; right: 0; top: auto; bottom: 0; width: 47%; height: 108px; }
  .hero-module--code pre { padding: 9px 8px; font-size: 8.7px; line-height: 1.55; }
  .hero-plot { height: calc(100% - 27px); padding: 5px 4px; }
  .hero-app-ui, .hero-game { height: calc(100% - 27px); }
  .hero-app-ui { gap: 6px; padding: 8px; }
  .hero-app-ui__chart { gap: 3px; padding: 4px; }

  .course-section-heading h2 { font-size: 34px; }
  .course-overview { padding-top: 68px; }
  .course-format { padding-bottom: 76px; }
  .about-highlights { margin-top: 26px; }
  .about-highlights li { grid-template-columns: 30px 1fr; gap: 9px; font-size: 13px; }
  .course-path { padding-left: 58px; }
  .course-path__rail--mobile { left: -5px; }
  .course-stage__node { left: -37px; }
  .course-stage__content, .course-stage:nth-child(even) .course-stage__content {
    display: grid; grid-template-columns: 56px minmax(0, 1fr); column-gap: 15px;
    padding: 20px 17px 20px;
  }
  .course-stage__meta { grid-column: 1 / -1; margin-bottom: 16px; }
  .course-stage__icon { grid-column: 1; grid-row: 2 / 5; width: 54px; height: 54px; margin: 0; border-radius: 12px; }
  .course-stage__icon svg { width: 42px; height: 42px; }
  .course-stage h3 { grid-column: 2; grid-row: 2; margin-bottom: 7px; font-size: 16px; }
  .course-stage p { grid-column: 2; grid-row: 3; font-size: 13px; }
  .course-stage__output { grid-column: 2; grid-row: 4; margin-top: 14px; padding-top: 10px; }

  .author-profile__inner { padding: 76px 20px 72px; }
  .author-profile__layout { row-gap: 36px; }
  .author-profile__eyebrow { margin-bottom: 18px; font-size: 10px; }
  .author-profile__name { margin-bottom: 14px; font-size: clamp(34px, 8vw, 40px); line-height: 1.1; }
  .author-profile__role { font-size: 16px; }
  .author-profile__specialization { margin-top: 16px; font-size: 10.5px; }
  .author-profile__specialization span:not(:last-child)::after { margin-inline: 5px; }
  .author-portrait { width: min(100%, 390px); }
  .author-portrait__canvas { --author-frame-inset: 25px; }
  .author-bio p { font-size: 13.5px; }
  .author-bio .author-bio__lead { font-size: 17px; }
  .author-domains { grid-template-columns: 1fr; margin-top: 32px; }
  .author-domain--wide { grid-column: auto; }
  .author-affiliations { grid-template-columns: 1fr; gap: 20px; }
  .author-metadata { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .author-metadata div { padding: 14px 10px; }
  .author-metadata div + div { padding-left: 10px; }
  .author-metadata div:nth-child(3) { border-left: 0; }
  .author-metadata div:nth-child(n + 3) { border-top: 1px solid rgba(168,176,199,.12); }
  .author-profile__coordinate--nw { left: 20px; top: 22px; }
  .author-profile__coordinate--se { right: 20px; bottom: 20px; }
}

@media (max-width: 380px) {
  .home-hero { padding-left: 18px; padding-right: 18px; }
  .home-hero h1 { font-size: 32px; }
  .hero-system { height: 410px; }
  .hero-module--code { height: 124px; }
  .hero-module--graph { height: 106px; }
  .hero-module--app, .hero-module--game { height: 104px; }
  .hero-module--code pre { font-size: 8.2px; }
  .course-path { padding-left: 52px; }
  .course-path__rail--mobile { left: -8px; }
  .course-stage__node { left: -31px; }
  .course-stage__content, .course-stage:nth-child(even) .course-stage__content { grid-template-columns: 50px minmax(0, 1fr); column-gap: 11px; padding-left: 14px; padding-right: 13px; }
  .course-stage__icon { width: 48px; height: 48px; }
  .course-stage__icon svg { width: 38px; height: 38px; }
  .course-stage h3 { font-size: 15px; }
  .course-stage p { font-size: 12.5px; }
  .about-stats { gap: 10px; }
  .about-stat { padding-left: 14px; padding-right: 14px; }
  .author-profile__inner { padding-inline: 18px; }
  .author-profile__name { font-size: 34px; }
  .author-portrait__canvas { --author-frame-inset: 23px; }
  .author-portrait__label--ai { right: -2px; }
  .author-portrait__label--avionics { right: -3px; }
  .author-bio .author-bio__lead { font-size: 16.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .jn-card, .project-card, .about-stat, .course-stage__content, .course-stage__node,
  .course-stage__icon, .course-path__segment, .exercise, .reference-card,
  .practice-lesson-row, .project-card-visual svg, .jn-dot { transition: none; }
  .jp-bar-fill, .pcg-bar-fill, .jn-progress-fill { transition: none; }
  .practice-chapter-group, .practice-chapter-group::after, .pcg-chevron, .pcg-summary { transition: none; }
  .practice-chapter-group::after { display: none; }
  .practice-chapter-group:has(.pcg-summary:hover) { transform: none; }
  details[open] > .pcg-lessons { animation: none; }
  .state-in-progress .pcg-bar-fill::after { animation: none; opacity: 1; }
  .pcb-board *, .pcb-board *::before, .pcb-board *::after { animation: none !important; transition: none !important; }
  .state-current .pcb-packet { opacity: 1; stroke-dashoffset: 55; }
  .state-current .jn-card { box-shadow: inset 0 0 0 4px #ffffff80, 0 4px 0 -1px #9aafe0, 0 0 18px #4169e827; }
  .jn-card:hover { transform: none; }
  .home-hero__content > *, .hero-system *, .hero-system *::before, .hero-system *::after {
    animation: none !important;
  }
  .course-experience *, .course-experience *::before, .course-experience *::after {
    animation: none !important;
  }
  .course-experience.is-enhanced .experience-reveal { opacity: 1; transform: none; transition: none; }
  .course-experience.is-enhanced .about-stat,
  .course-experience.is-enhanced .about-stat.is-metric-entering,
  .course-experience.is-enhanced .about-stat.is-metric-revealed {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .about-stat .num { transform: none !important; filter: none !important; transition: none !important; }
  .course-path__signal { stroke-dasharray: none; opacity: .36; }
  .about-stats__signal { stroke-dasharray: none; opacity: .34; }
  .hero-plot__curve { stroke-dashoffset: 0; }
  .hero-system__backdrop, .hero-system__plane { transform: none !important; transition: none; }
  .hero-code-cursor { opacity: 1; }
  .author-profile *, .author-profile *::before, .author-profile *::after { animation: none !important; }
  .author-profile .author-reveal,
  .author-profile.is-enhanced .author-reveal,
  .author-profile.is-profile-entering .author-reveal,
  .author-profile.is-profile-revealed .author-reveal {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .author-profile .author-portrait__outline,
  .author-profile .author-portrait__corners,
  .author-profile .author-portrait__route { stroke-dashoffset: 0 !important; }
  .author-profile .author-portrait__nodes { opacity: 1 !important; }
  .author-profile .author-portrait__signal { opacity: .62 !important; stroke-dashoffset: 0 !important; }
  .author-profile .author-portrait img { transform: none !important; transition: none !important; }
  .author-profile::after { transform: none !important; }
  .project-art *, .reference-art *, .practice-art * { animation: none !important; }
  .project-card:hover, .reference-card:hover,
  .project-card:hover .project-card-visual svg,
  .reference-card:hover .reference-card__arrow { transform: none !important; }
  .project-art--story-generator .story-token,
  .project-art--story-generator .story-hub-dot,
  .project-art--story-generator .story-output-line,
  .project-art--story-generator .story-spark { opacity: 1 !important; transform: none !important; }
  .project-art--story-generator .story-route { stroke-dashoffset: 0 !important; }
  .project-art--paint-app .paint-cursor,
  .project-art--paint-app .paint-tool-btn { transform: none !important; }
  .project-art--paint-app .paint-shape,
  .project-art--paint-app .paint-swatch { opacity: 1 !important; transform: none !important; }
  .project-art--paint-app .paint-stroke { stroke-dashoffset: 0 !important; }
  .project-art--space-shooter .shooter-explosion { opacity: 0 !important; }
  .project-art--space-shooter .shooter-route { stroke-dashoffset: 0 !important; }
  .project-art--calculator .calc-display-state { opacity: 0 !important; }
  .project-art--calculator .calc-display-state--result { opacity: 1 !important; }
  .project-art--calculator .calc-result-value { transform: none !important; }
  .project-art--calculator .calc-key--seq-5 {
    transform: translateY(1px) scale(.98) !important;
    filter: drop-shadow(0 0 5px rgba(91,36,249,.55)) !important;
  }
  .project-art--todo-app .todo-add,
  .project-art--todo-app .todo-row--new,
  .project-art--todo-app .todo-delete { transform: none !important; }
  .project-art--todo-app .todo-input-state--empty { opacity: 1 !important; }
  .project-art--todo-app .todo-input-state--filled { opacity: 0 !important; }
  .project-art--todo-app .todo-checkbox-fill { opacity: 1 !important; }
  .project-art--todo-app .todo-row--new .todo-row__text { opacity: .25 !important; }
  .project-art--todo-app .todo-check,
  .project-art--todo-app .todo-strike { stroke-dashoffset: 0 !important; opacity: 1 !important; }
  .project-art--todo-app .todo-db-pulse { opacity: 0 !important; }
  .project-art--rock-paper-scissors .rps-winner-glow { opacity: .4 !important; transform: none !important; }
  .project-art--rock-paper-scissors .rps-computer--rock,
  .project-art--rock-paper-scissors .rps-computer--paper { opacity: 0 !important; }
  .project-art--rock-paper-scissors .rps-computer--scissors { opacity: .55 !important; transform: none !important; }
  .project-art--rock-paper-scissors .rps-reveal-ring,
  .project-art--rock-paper-scissors .rps-impact-pulse,
  .project-art--rock-paper-scissors .rps-impact-spark { opacity: 0 !important; }
  .project-art--bouncing-balls-oop .oop-instance-link,
  .project-art--bouncing-balls-oop .oop-impact,
  .project-art--bouncing-balls-oop .oop-loop-ring,
  .project-art--bouncing-balls-oop .oop-trail { opacity: 0 !important; }
  .project-art--bouncing-balls-oop .oop-ball-travel,
  .project-art--bouncing-balls-oop .oop-ball-squash { transform: none !important; }
  .project-art--temperature-converter .temp-value-state--empty { opacity: 0 !important; }
  .project-art--temperature-converter .temp-value-state--celsius,
  .project-art--temperature-converter .temp-value-state--fahrenheit,
  .project-art--temperature-converter .temp-value-state--kelvin { opacity: 1 !important; }
  .project-art--temperature-converter .temp-column { transform: scaleY(.78) !important; }
  .project-art--temperature-converter .temp-glow { opacity: .3 !important; }
  .project-art--temperature-converter .temp-input { opacity: 1 !important; }
  .project-art--temperature-converter .temp-hub-ring,
  .project-art--temperature-converter .temp-flow-dot { opacity: 0 !important; }
  .project-art--temperature-converter .temp-flow--fahrenheit,
  .project-art--temperature-converter .temp-flow--kelvin { opacity: .5 !important; }
  .project-art--temperature-converter .temp-celsius,
  .project-art--temperature-converter .temp-fahrenheit,
  .project-art--temperature-converter .temp-kelvin { filter: none !important; }
  .project-art--notes-app .notes-line--active { transform: scaleX(1) !important; }
  .project-art--notes-app .notes-caret { opacity: 1 !important; transform: translateX(150px) !important; }
  .project-art--notes-app .notes-unsaved { opacity: .2 !important; }
  .project-art--notes-app .notes-save { transform: none !important; filter: none !important; }
  .project-art--notes-app .notes-flow,
  .project-art--notes-app .notes-flow-dot,
  .project-art--notes-app .notes-file-glow,
  .project-art--notes-app .notes-saved { opacity: 0 !important; }
  .project-art--notes-app .notes-file-line { opacity: .8 !important; }
  .project-art--safesort .safesort-scan { opacity: 0 !important; }
  .project-art--safesort .safesort-route--intake { opacity: .3 !important; }
  .project-art--safesort .safesort-plan { opacity: 1 !important; transform: none !important; }
  .project-art--safesort .safesort-plan-row { opacity: .7 !important; transform: none !important; }
  .project-art--safesort .safesort-shield-badge { opacity: 1 !important; }
  .project-art--safesort .safesort-shield-check { stroke-dashoffset: 0 !important; opacity: 1 !important; }
  .project-art--safesort .safesort-folder-active { opacity: .85 !important; }
  .project-art--safesort .safesort-route--apply-1,
  .project-art--safesort .safesort-route--apply-2 { opacity: .15 !important; }
  .project-art--safesort .safesort-files__mover--1,
  .project-art--safesort .safesort-files__mover--2,
  .project-art--safesort .safesort-folder-pulse--1,
  .project-art--safesort .safesort-folder-pulse--2 { opacity: 0 !important; }
  .project-art--safesort .safesort-history-row { opacity: .55 !important; transform: none !important; }
  .project-art--safesort .safesort-duplicate-tile { opacity: .85 !important; transform: none !important; }
  .project-art--safesort .safesort-duplicate-check-badge { opacity: 1 !important; }
  .project-art--safesort .safesort-duplicate-check { stroke-dashoffset: 0 !important; opacity: 1 !important; }
  .project-art--safesort .safesort-hash-tick { opacity: .85 !important; }
  .project-art--safesort .safesort-history-check-badge { opacity: 1 !important; }
  .project-art--safesort .safesort-history-check { stroke-dashoffset: 0 !important; opacity: 1 !important; }
  .project-art--safesort .safesort-undo { opacity: 1 !important; transform: translate(300px,158px) scale(.85) !important; }
  .practice-line-reveal { transform: scaleX(1) !important; }
  .practice-run-node { transform: none !important; }
  .practice-glow-halo circle { opacity: .4 !important; transform: none !important; }
  .practice-signal--a, .practice-signal--b { opacity: 0 !important; }
  .practice-result-idle { opacity: 0 !important; }
  .practice-result-value { opacity: 1 !important; transform: none !important; }
  .practice-check-fill { opacity: 1 !important; }
  .practice-check-mark { stroke-dashoffset: 0 !important; }
  .practice-progress-seg { stroke-dashoffset: 0 !important; }
  .practice-progress-dot { opacity: 1 !important; }
}
