/* ==========================================================================
   Motion graphics, 2026-10-19 (after the printer in printer.css, which Evan
   asked for more of: "make a few more of those to sprinkle around").
   CSS and inline SVG only. Everything waits for .is-live (index.html's one
   script adds it when the piece is a third on screen); without JavaScript it
   plays on load. Reduced motion shows a finished still.
   1 shared · 2 the ship dock · 3 tile icons that draw themselves
   4 the Boxfight card's map reel
   ========================================================================== */

/* 1. Shared ---------------------------------------------------------------- */
.js [data-motion]:not(.is-live), .js [data-motion]:not(.is-live) *,
.js [data-motion]:not(.is-live) *::before, .js [data-motion]:not(.is-live) *::after { animation-play-state: paused !important; }

/* 2. The ship dock: Evan's department at Amazon --------------------------- */
/* A 12 s loop. Packages ride the belt into the trailer, which fills from the
   nose back to the door (0-66 %). The door rolls down (66-70 %), the trailer
   pulls away (70-80 %), an empty one backs in (84-96 %), the door rolls up. */
.dock { margin-top: 26px; overflow: hidden; background: linear-gradient(180deg, var(--raise-2), var(--raise)); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.dock__bar, .dock__cap { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 11px 18px; font-family: var(--mono); font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.dock__bar { position: relative; border-bottom: 1px solid var(--line); }
.dock__bar::after { content: ""; position: absolute; left: 0; bottom: -1px; width: 100%; height: 2px; background: var(--accent); transform-origin: 0 50%; animation: dk-fill 12s linear infinite both; }
.dock__cap { border-top: 1px solid var(--line); }
.dock__state { display: grid; }
.dock__state > span { grid-area: 1 / 1; display: inline-flex; align-items: center; gap: 8px; }
.dock__state > span::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.dock__state .is-loading { animation: dk-show-loading 12s steps(1, end) infinite both; }
.dock__state .is-dispatched { animation: dk-show-dispatched 12s steps(1, end) infinite both; }
.dock__state .is-dispatched::before { background: var(--muted); }
.dock__scene { display: block; width: 100%; height: auto; }

.dk-floor { stroke: var(--line-strong); stroke-width: 1.5; }
.dk-wall { fill: var(--raise-2); stroke: var(--line); }
.dk-door { fill: var(--bg); stroke: var(--line-strong); stroke-width: 1.5; }
.dk-belt { fill: var(--raise-2); stroke: var(--line-strong); stroke-width: 1.2; }
.dk-belt-run { stroke: var(--muted); stroke-width: 1.2; stroke-dasharray: 3 9; fill: none; animation: dk-belt 0.6s linear infinite; }
.dk-leg { stroke: var(--line-strong); stroke-width: 1.5; }
.dk-roll { fill: var(--line-strong); }
.dk-pkg { fill: #b78a57; stroke: #6d5233; stroke-width: 0.8; }
.dk-tape { stroke: #e6cfa7; stroke-width: 1; }
.dk-trailer-body { fill: var(--raise); stroke: var(--line-strong); stroke-width: 1.5; }
.dk-trailer-inside { fill: var(--bg); }
.dk-load { fill: #a57a4a; stroke: #6d5233; stroke-width: 0.6; }
.dk-cover { fill: var(--bg); transform-box: fill-box; transform-origin: 0 50%; animation: dk-reveal 12s linear infinite both; }
.dk-cab { fill: var(--line-strong); }
.dk-glass { fill: var(--accent); opacity: 0.55; }
.dk-wheel { fill: #111111; stroke: var(--line-strong); stroke-width: 1.5; }
.dk-rolldoor { fill: var(--line-strong); transform-box: fill-box; transform-origin: 50% 0; animation: dk-rolldoor 12s ease-in-out infinite both; }
.dk-light { fill: var(--accent); animation: dk-light 12s steps(1, end) infinite both; }

.dk-trailer { animation: dk-trailer 12s cubic-bezier(0.45, 0, 0.35, 1) infinite both; }
.dk-pkgs { animation: dk-pkgs 12s linear infinite both; }
.dk-p { animation: dk-ride 2.4s linear infinite both; }
.dk-p:nth-child(2) { animation-delay: -0.6s; }
.dk-p:nth-child(3) { animation-delay: -1.2s; }
.dk-p:nth-child(4) { animation-delay: -1.8s; }

@keyframes dk-belt { to { stroke-dashoffset: -12; } }
@keyframes dk-ride { 0% { transform: translateX(0); opacity: 0; } 6% { opacity: 1; } 88% { opacity: 1; } 100% { transform: translateX(250px); opacity: 0; } }
@keyframes dk-pkgs { 0%, 66% { opacity: 1; } 68%, 95% { opacity: 0; } 98%, 100% { opacity: 1; } }
/* The empty-trailer cover retracts toward the door as the load builds. */
/* Steps, one row of boxes at a time; it snaps back to empty while the trailer is out of view (80-81 %). */
@keyframes dk-reveal { 0% { transform: scaleX(1); } 66% { transform: scaleX(0.02); } 80% { transform: scaleX(0.02); } 80.5%, 100% { transform: scaleX(1); } }
@keyframes dk-trailer {
  0%, 70% { transform: translateX(0); opacity: 1; }
  80% { transform: translateX(240px); opacity: 0; }
  83% { transform: translateX(240px); opacity: 0; }
  84% { transform: translateX(200px); opacity: 1; }
  96%, 100% { transform: translateX(0); opacity: 1; }
}
@keyframes dk-rolldoor { 0%, 64% { transform: scaleY(0); } 69%, 95% { transform: scaleY(1); } 99%, 100% { transform: scaleY(0); } }
@keyframes dk-fill { 0% { transform: scaleX(0); } 66% { transform: scaleX(1); } 70%, 96% { transform: scaleX(1); opacity: 0.35; } 97% { transform: scaleX(0); opacity: 1; } 100% { transform: scaleX(0); } }
@keyframes dk-show-loading { 0% { opacity: 1; } 68% { opacity: 0; } 96% { opacity: 1; } }
@keyframes dk-show-dispatched { 0% { opacity: 0; } 68% { opacity: 1; } 96% { opacity: 0; } }
@keyframes dk-light { 0% { opacity: 1; } 68% { opacity: 0.25; } 96% { opacity: 1; } }

/* 3. Tile icons draw themselves ------------------------------------------- */
.tiles[data-motion] .tile__icon path { stroke-dasharray: 100; stroke-dashoffset: 100; animation: icon-draw 1.1s cubic-bezier(0.45, 0, 0.25, 1) both; }
.tiles[data-motion] .tile:nth-child(2) .tile__icon path { animation-delay: 0.18s; }
.tiles[data-motion] .tile:nth-child(3) .tile__icon path { animation-delay: 0.36s; }
.tiles[data-motion] .tile:nth-child(4) .tile__icon path { animation-delay: 0.54s; }
.tiles[data-motion] .tile__icon { animation: icon-pop 0.5s cubic-bezier(0.3, 1.4, 0.5, 1) both; }
.tiles[data-motion] .tile:nth-child(2) .tile__icon { animation-delay: 0.18s; }
.tiles[data-motion] .tile:nth-child(3) .tile__icon { animation-delay: 0.36s; }
.tiles[data-motion] .tile:nth-child(4) .tile__icon { animation-delay: 0.54s; }
@keyframes icon-draw { to { stroke-dashoffset: 0; } }
@keyframes icon-pop { 0% { scale: 0.6; opacity: 0; } 100% { scale: 1; opacity: 1; } }

/* 4. The Boxfight card's big picture cross-fades between maps ------------- */
.feature__reel { position: relative; overflow: hidden; grid-row: 1 / -1; aspect-ratio: 16 / 9; background: #111111; }
.feature__reel img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; animation: reel-fade 15s linear infinite both; }
.feature__reel img:nth-child(1) { animation-delay: -1s; }
.feature__reel img:nth-child(2) { animation-delay: 4s; }
.feature__reel img:nth-child(3) { animation-delay: 9s; }
@keyframes reel-fade { 0% { opacity: 0; transform: scale(1.03); } 6% { opacity: 1; } 33% { opacity: 1; } 39% { opacity: 0; transform: scale(1.09); } 100% { opacity: 0; transform: scale(1.09); } }


/* 5. The printer's replay button ----------------------------------------- */
.printer__cap-end { display: inline-flex; align-items: center; gap: 12px; }
.motion-replay { display: grid; place-items: center; width: 26px; height: 26px; padding: 0; border: 1px solid var(--line-strong); border-radius: 50%; background: transparent; color: var(--accent); font: 500 15px/1 var(--font); cursor: pointer; transition: border-color 0.15s, transform 0.3s; }
.motion-replay:hover { border-color: var(--accent); transform: rotate(-90deg); }

/* 6. Beside section 01's heading: a Claude Code terminal, rebuilt the same night to match
   Claude Code's own window (claude.com's product image). Earlier brief (Evan, 2026-10-19: "just make it a
   terminal window... prompt 'Claude Code'... a little Claude logo that says 'You're talking to
   Claude'... a little fun prompt"). A 12 s loop: the welcome box shows (0-8 %), the prompt types
   (10-34 %), the reply types (42-58 %), the result (64-74 %), it holds, then fades (92-100 %).
   The spark is drawn, not a font glyph, in Claude's orange. */
/* Section 01's top: the heading and its paragraph on the left, the terminal beside them, so the
   paragraph wraps sooner and nothing sits under an empty heading row (Evan, 2026-10-19). */
.intro-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 560px); gap: clamp(28px, 4vw, 56px); align-items: center; }
.intro-split__text { margin-top: 18px; max-width: 60ch; font-size: 1.08em; color: var(--text); }
/* Twice the old height (Evan), grown up and down into the section padding: the negative margins are
   a share of the terminal's own width, so the row keeps its old height at every width. */
.techbanner { margin: -10% 0 -14%; width: 100%; }
.intro-split + .prose > p.sub:first-child { margin-top: clamp(32px, 4vw, 44px); font-size: 13px; }
.techbanner svg { display: block; width: 100%; height: auto; }
.cc-win { fill: #0d0d0d; }
.cc-bar { fill: #1b1b1b; }
.cc-edge { fill: none; stroke: #343434; stroke-width: 1.5; }
.cc-dot { fill: #555553; }
.cc-text { font: 400 14px/1 var(--mono); fill: #e4e2dd; white-space: pre; }
.cc-dim { fill: #8d8b86; }
.cc-or, .cc-bullet { fill: #d97757; }
.cc-bullet { fill: #e8e6e1; }
.cc-spin line { stroke: #d97757; stroke-width: 2; stroke-linecap: round; }
.cc-spin { transform-box: fill-box; transform-origin: center; animation: cc-rot 1.2s linear infinite; }
.cc-box { fill: none; stroke: #5a5a58; stroke-width: 1.2; }
.cc-caret { fill: #e4e2dd; }
.cc-welcome { fill: none; stroke: #d97757; stroke-width: 1.3; }
.cc-cover { fill: #0d0d0d; transform-box: fill-box; transform-origin: 100% 50%; shape-rendering: crispEdges; }

/* A 14 s loop, as Claude Code itself behaves: the prompt is typed into the input box (5-33 %),
   sent (36 %: it moves up into the conversation and the box clears), Claude thinks with the orange
   spark (37-54 %), then replies with its bullet and a result line (55-76 %), holds, and fades. */
.cc-all { animation: cc-all 14s ease infinite both; }
.cc-in .cc-cover { animation: cc-type-in 14s steps(54, end) infinite both; }
.cc-draft { animation: cc-draft 14s steps(1, end) infinite both; }
.cc-caret { animation: cc-caret-move 14s steps(54, end) infinite both, cc-blink 1s steps(1, end) infinite; }
.cc-sent { animation: cc-sent 14s steps(1, end) infinite both; }
.cc-think { animation: cc-think 14s steps(1, end) infinite both; }
.cc-r1 .cc-cover { animation: cc-type-r1 14s steps(39, end) infinite both; }
.cc-r2 .cc-cover { animation: cc-type-r2 14s steps(43, end) infinite both; }
.cc-r3 .cc-cover { animation: cc-type-r3 14s steps(36, end) infinite both; }
.cc-r4 .cc-cover { animation: cc-type-r4 14s steps(42, end) infinite both; }
@keyframes cc-all { 0% { opacity: 0; } 3% { opacity: 1; } 93% { opacity: 1; } 99%, 100% { opacity: 0; } }
@keyframes cc-type-in { 0%, 5% { transform: scaleX(1); } 33%, 100% { transform: scaleX(0); } }
@keyframes cc-caret-move { 0%, 5% { transform: translateX(0); } 33% { transform: translateX(453.6px); } 36%, 100% { transform: translateX(0); } }
@keyframes cc-draft { 0% { opacity: 1; } 36% { opacity: 0; } }
@keyframes cc-sent { 0% { opacity: 0; } 36% { opacity: 1; } }
@keyframes cc-think { 0% { opacity: 0; } 37% { opacity: 1; } 54% { opacity: 0; } }
@keyframes cc-type-r1 { 0%, 55% { transform: scaleX(1); } 63%, 100% { transform: scaleX(0); } }
@keyframes cc-type-r2 { 0%, 64% { transform: scaleX(1); } 70%, 100% { transform: scaleX(0); } }
@keyframes cc-type-r3 { 0%, 71% { transform: scaleX(1); } 76%, 100% { transform: scaleX(0); } }
@keyframes cc-type-r4 { 0%, 77% { transform: scaleX(1); } 83%, 100% { transform: scaleX(0); } }
@keyframes cc-rot { to { rotate: 360deg; } }
@keyframes cc-blink { 50% { opacity: 0; } }

@media (max-width: 1000px) { .intro-split { grid-template-columns: minmax(0, 1fr); } .techbanner { display: none; } }

/* On a phone the caption keeps only its right-hand line, so it never wraps into two cramped rows. */
@media (max-width: 520px) { .dock__cap > span:first-child { display: none; } .dock__cap { padding-inline: 14px; font-size: 10.5px; letter-spacing: 0.03em; } }

@media (prefers-reduced-motion: reduce) {
  .dock *, .dock__bar::after, .tiles[data-motion] *, .feature__reel img, .techbanner * { animation: none !important; }
  .cc-cover, .cc-draft, .cc-think, .cc-caret { opacity: 0; }
  .cc-sent { opacity: 1; }
  .motion-replay { display: none; }
  .dk-cover { transform: scaleX(0.04); }
  .dk-rolldoor { transform: scaleY(0); }
  .dock__state .is-dispatched { opacity: 0; }
  .tiles[data-motion] .tile__icon path { stroke-dashoffset: 0; }
  .feature__reel img:first-child { opacity: 1; }
}
