/* ═══════════════════════════════════════════════════════════════
   StepZero — motion layer for the article and hub pages.

   Built the same way as the Daytona site: CSS keyframes plus a few
   lines of vanilla JS. No animation library, so nothing is loaded
   from a third-party host and the DSGVO-safe self-hosting stands.

   Two rules this file never breaks:
     1. Every animated element renders its FINAL state after 4s even
        if the script never runs. Content is never held hostage by JS.
     2. prefers-reduced-motion disables all of it and shows the end
        state immediately.
═══════════════════════════════════════════════════════════════ */

:root {
  --gold-h: #fff6da;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
  --dur-s: .35s;
  --dur-m: .6s;
  --dur-l: .9s;
}

/* ── 1. REVEALS ──────────────────────────────────────────────
   Three directions, staggered by a per-element --i index.

   IMPORTANT: the hidden start state is scoped to html.motion, which the
   script sets only after it has loaded. No script, blocked script, throttled
   animation or old browser => the text simply renders, fully visible.
   Content is never hidden by something that might not run. */
.motion .rv, .motion .rv-l, .motion .rv-r {
  opacity: 0;
  transition:
    opacity var(--dur-m) var(--ease-out) calc(var(--i, 0) * 70ms),
    transform var(--dur-m) var(--ease-out) calc(var(--i, 0) * 70ms);
  will-change: opacity, transform;
}
.motion .rv   { transform: translateY(18px) }
.motion .rv-l { transform: translateX(-22px) }
.motion .rv-r { transform: translateX(22px) }
.motion .rv.in, .motion .rv-l.in, .motion .rv-r.in { opacity: 1; transform: none }

/* Safety net — if the observer never fires, show everything anyway. */
@keyframes rv-fallback { to { opacity: 1; transform: none } }
.motion .rv, .motion .rv-l, .motion .rv-r { animation: rv-fallback .01s linear 4s forwards }
.motion .rv.in, .motion .rv-l.in, .motion .rv-r.in { animation: none }

/* ── 2. THE ASCENT — the brand mark is a staircase, so the
   section numbers climb one step as they arrive. ───────────── */
@keyframes step-up {
  0%   { opacity: 0; transform: translate3d(-10px, 10px, 0) }
  60%  { opacity: 1 }
  100% { opacity: 1; transform: none }
}
.motion article h2[id].in::before {
  animation: step-up var(--dur-m) var(--ease-out) both;
}

/* ── 3. LOOP TABLE — rows cascade like a chain closing ─────── */
.motion .loop.in .loop-row {
  animation: row-in var(--dur-m) var(--ease-out) both;
  animation-delay: calc(var(--r, 0) * 90ms);
}
@keyframes row-in {
  from { opacity: 0; transform: translateX(-14px) }
  to   { opacity: 1; transform: none }
}
.motion .loop:not(.in) .loop-row { opacity: 0; animation: rv-fallback .01s linear 4s forwards }

/* ── 4. KEYLINE — the gold rule draws itself downward ──────── */
.keyline { position: relative }
/* the real border stays visible; the animated bar only draws over it,
   so a stalled animation degrades to the plain gold rule */
.motion .keyline::before {
  content: ''; position: absolute; left: -2px; top: 0;
  width: 2px; height: 100%; background: var(--gold);
  transform: scaleY(0); transform-origin: 0 0;
  transition: transform var(--dur-l) var(--ease-out);
}
.motion .keyline.in::before { transform: scaleY(1) }
@keyframes keyline-fallback { to { transform: scaleY(1) } }
.motion .keyline:not(.in)::before { animation: keyline-fallback .01s linear 4s forwards }

/* ── 5. RELATED CARDS — staggered lift ─────────────────────── */
.motion .related-grid .rel-card {
  opacity: 0; transform: translateY(16px);
  transition: opacity var(--dur-m) var(--ease-out) calc(var(--c, 0) * 90ms),
              transform var(--dur-m) var(--ease-out) calc(var(--c, 0) * 90ms),
              border-color .3s, background .3s;
}
.motion .related.in .rel-card { opacity: 1; transform: none }
.motion .related:not(.in) .rel-card { animation: rv-fallback .01s linear 4s forwards }

/* ── 6. TABLE OF CONTENTS — active section is marked while
   reading, so the sticky list doubles as a position indicator. */
.toc a { position: relative; padding-left: 0; transition: color .25s, padding-left .3s var(--ease-out) }
.toc li.active a { color: var(--gold-l); padding-left: 8px }
.toc li.active::before { color: var(--gold) }
.toc li::before { transition: color .25s }

/* ── 7. NAV — condenses once you start reading ─────────────── */
nav { transition: padding .35s var(--ease-out), background .35s }
nav.scrolled { padding-block: 7px; background: rgba(10,16,31,.94) }

/* ── 8. GOLD SHEEN on the primary button, same trick the
   Daytona page uses on its CTA. ─────────────────────────────── */
.btn-gold { position: relative; overflow: hidden }
.btn-gold::after {
  content: ''; position: absolute; top: 0; left: -120%; width: 55%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.55), transparent);
  transform: skewX(-18deg); animation: sheen 5.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes sheen { 0%,58% { left: -120% } 78%,100% { left: 130% } }

/* ── 9. LINKS in body copy get an underline that grows ─────── */
article > p a, .today a, details p a {
  text-decoration: none; background-image: linear-gradient(var(--gold), var(--gold));
  background-size: 0 1px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size .35s var(--ease-out);
}
article > p a:hover, .today a:hover, details p a:hover { background-size: 100% 1px }

/* ── REDUCED MOTION — everything off, final state shown ────── */
@media (prefers-reduced-motion: reduce) {
  .rv, .rv-l, .rv-r,
  .related-grid .rel-card,
  .loop:not(.in) .loop-row {
    opacity: 1 !important; transform: none !important;
    animation: none !important; transition: none !important;
  }
  .keyline::before { transform: scaleY(1) !important; animation: none !important; transition: none !important }
  article h2[id].in::before { animation: none !important }
  .motion .loop.in .loop-row { animation: none !important }
  .btn-gold::after { animation: none !important; display: none }
  nav { transition: none !important }
}

/* ═══════════════════════════════════════════════════════════════
   PASS 2 — motion with a bit more character.
   Everything below is scoped to .motion, so the no-JS contract holds.
═══════════════════════════════════════════════════════════════ */

/* ── 10. HEADLINE — words rise one after another, the way the
   homepage hero already does. Split by the script. ──────────── */
.motion h1 .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em) rotate(1.5deg);
  animation: word-up .75s var(--ease-out) forwards;
  animation-delay: calc(var(--w, 0) * 55ms + 120ms);
}
@keyframes word-up {
  to { opacity: 1; transform: none }
}

/* ── 11. THE CHAIN — the four links of the loop are literally a
   chain, so a gold line draws down through them. ───────────── */
.loop { position: relative }
.motion .loop::after {
  content: ''; position: absolute; left: 0; top: 0; width: 2px; height: 100%;
  background: linear-gradient(var(--gold), var(--gold-d));
  transform: scaleY(0); transform-origin: 0 0;
  transition: transform 1.1s var(--ease-out) .15s;
}
.motion .loop.in::after { transform: scaleY(1) }
.motion .loop-k { transition: color .4s var(--ease-out), letter-spacing .4s var(--ease-out) }
.motion .loop.in .loop-row:hover .loop-k { color: var(--gold-l); letter-spacing: .1em }

/* ── 12. HUD BRACKETS — the corner ticks draw themselves in on
   the cards, matching the frame language of the app. ───────── */
.rel-card { position: relative }
.rel-card::before, .rel-card::after {
  content: ''; position: absolute; width: 12px; height: 12px;
  border: 1px solid var(--gold); opacity: 0;
  transition: opacity .3s var(--ease-out), width .35s var(--ease-out), height .35s var(--ease-out);
  pointer-events: none;
}
.rel-card::before { top: -1px; left: -1px; border-right: none; border-bottom: none }
.rel-card::after  { bottom: -1px; right: -1px; border-left: none; border-top: none }
.rel-card:hover::before, .rel-card:hover::after { opacity: .85; width: 18px; height: 18px }

/* ── 13. TERRAIN — the stepped motif drifts very slowly, so the
   background has depth instead of sitting dead still. ──────── */
@keyframes terrain-drift {
  from { background-position: 0 0 }
  to   { background-position: 480px -480px }   /* one full tile, diagonally up */
}
html.motion::before { animation: terrain-drift 240s linear infinite }

/* ── 14. READING PROGRESS as steps, not a smooth bar — the
   brand is a staircase, so the bar is segmented. ───────────── */
@supports (animation-timeline: scroll()) {
  html::after {
    background-image:
      var(--metal),
      repeating-linear-gradient(90deg, transparent 0 46px, rgba(10,16,31,.85) 46px 50px);
    background-blend-mode: normal;
  }
}

/* ── 15. SECTION NUMBER gets a brief gold flare as it lands ── */
@keyframes num-flare {
  0%   { color: var(--gold-d); text-shadow: none }
  35%  { color: var(--gold-h, #fff6da); text-shadow: 0 0 14px rgba(232,194,100,.7) }
  100% { color: var(--gold-d); text-shadow: none }
}
.motion article h2[id].in::before { animation: step-up var(--dur-m) var(--ease-out) both, num-flare 1.4s ease-out .2s both }

/* ── 16. PRIMARY BUTTON lifts and its shadow spreads ───────── */
.btn-gold { transition: transform .35s var(--ease-out), box-shadow .35s var(--ease-out), letter-spacing .35s var(--ease-out) }
.btn-gold:hover { letter-spacing: .18em }
.btn-gold:active { transform: translateY(0) scale(.985) }

/* ── 17. TOC entries slide their marker as you pass ────────── */
.toc li::before { transition: color .25s, transform .3s var(--ease-out) }
.toc li.active::before { transform: translateX(2px) scale(1.15) }

/* ── REDUCED MOTION — the additions switch off too ─────────── */
@media (prefers-reduced-motion: reduce) {
  .motion h1 .w { opacity: 1 !important; transform: none !important; animation: none !important }
  .motion .loop::after { transform: scaleY(1) !important; transition: none !important }
  .rel-card::before, .rel-card::after { transition: none !important }
  html.motion::before { animation: none !important }
  .motion article h2[id].in::before { animation: none !important }
  .btn-gold:hover { letter-spacing: .14em }
}
