/* Rebuy text animations */
.typing::after { content: "▍"; margin-left: 2px; color: var(--buy); animation: caret .7s steps(1) infinite; }
@keyframes caret { 50% { opacity: 0; } }

.rotline { font: 600 clamp(18px, 2.4vw, 24px)/1.3 var(--sans); color: var(--ink2); margin: -6px 0 18px; letter-spacing: -.01em; }
.rot { position: relative; display: inline-grid; vertical-align: bottom; overflow: hidden; height: 1.3em; min-width: 9ch; color: var(--buy); }
.rot-w { grid-area: 1 / 1; white-space: nowrap; }
.rot-w.in { animation: rotin .5s var(--ease) both; }
.rot-w.out { animation: rotout .5s var(--ease) both; }
@keyframes rotin { from { transform: translateY(100%); opacity: 0; filter: blur(4px); } to { transform: none; opacity: 1; filter: none; } }
@keyframes rotout { to { transform: translateY(-100%); opacity: 0; filter: blur(4px); } }

h1 .loop .w.wave { display: inline-block; animation: bob 3.2s ease-in-out infinite !important; animation-delay: calc(var(--wi) * 140ms) !important; }
@keyframes bob { 0%, 70%, 100% { transform: none; } 35% { transform: translateY(-.07em); } }

[data-text] { font-variant-ligatures: none; }

@media (prefers-reduced-motion: reduce) { h1 .loop .w.wave { animation: none !important; } }

/* fixes: embers canvas must stay out of the hero grid; split words inside the gradient headline need their own fill */
.hero > canvas.embers { position: absolute; inset: 0; z-index: 0; grid-area: auto; }
h1 .loop:has(.w) { background: none; color: var(--buy); -webkit-background-clip: border-box; background-clip: border-box; animation: none; }
h1 .loop .w { color: var(--buy); text-shadow: 0 0 24px rgba(184,255,60,.25); }
