/* Code panel: typewriter the agent.ts source line by line, then stream the console output. Triggered once per page when the panel scrolls into view. */

/* Default state — lines hidden until JS measures and stamps delays. .is-armed switches them to "waiting to play" so we don't flash unstyled content for users without JS. */
.tubo-code-line[data-armed] > :nth-child(2) {
  clip-path: inset(0 100% 0 0);
  will-change: clip-path;
}

.tubo-code-line.is-playing > :nth-child(2) {
  animation: tubo-type var(--anim-dur, 0.4s) steps(var(--anim-steps, 24)) var(--anim-delay, 0s) both;
}

@keyframes tubo-type {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* Line number: subtle pop as the line starts typing — gives the panel that "live" feel. */
.tubo-code-line[data-armed] > :nth-child(1) {
  opacity: 0.25;
  transition: opacity 0.15s linear var(--anim-delay, 0s);
}
.tubo-code-line.is-playing > :nth-child(1) {
  opacity: 1;
}

/* Caret: a thin amber bar that rides the leading edge of each line as it types. Done as a ::after on the line container, animated in lockstep with the clip-path width. */
.tubo-code-line[data-armed] {
  position: relative;
}
.tubo-code-line[data-armed]::after {
  content: "";
  position: absolute;
  top: 0.25em;
  bottom: 0.25em;
  left: 0;
  width: 1px;
  background: var(--color-accent, #ddae6c);
  opacity: 0;
  transform: translateX(0);
  pointer-events: none;
}
.tubo-code-line.is-playing::after {
  animation:
    tubo-caret-track var(--anim-dur, 0.4s) linear var(--anim-delay, 0s) both,
    tubo-caret-fade 0.18s linear calc(var(--anim-delay, 0s) + var(--anim-dur, 0.4s)) both;
}
@keyframes tubo-caret-track {
  from { opacity: 0.95; transform: translateX(1.75rem); }
  to   { opacity: 0.95; transform: translateX(100%); }
}
@keyframes tubo-caret-fade {
  to { opacity: 0; }
}

/* Console rows: stream in with a quick slide-up + fade. */
.tubo-console-line[data-armed] {
  opacity: 0;
  transform: translateY(6px);
  will-change: opacity, transform;
}
.tubo-console-line.is-playing {
  animation: tubo-console-in 0.32s cubic-bezier(0.2, 0.8, 0.2, 1) var(--anim-delay, 0s) both;
}
@keyframes tubo-console-in {
  to { opacity: 1; transform: translateY(0); }
}

/* Respect reduced-motion preference: collapse all animations and reveal everything statically. */
@media (prefers-reduced-motion: reduce) {
  .tubo-code-line[data-armed] > :nth-child(2),
  .tubo-code-line[data-armed] > :nth-child(1) {
    clip-path: none !important;
    opacity: 1 !important;
  }
  .tubo-code-line[data-armed]::after { display: none !important; }
  .tubo-console-line[data-armed] {
    opacity: 1 !important;
    transform: none !important;
  }
}
