/* ── Blue Papers drawings (archive/papers/art/*.svg, drawn by art/draw.py) ──
   Each drawing is inline SVG in four layers: construction (.c), the object (.o),
   dimensions and callouts (.d), lettering (.x). Colour is currentColor plus one
   accent (--art-acc), set by the sheet the drawing sits on. Line weights are
   set in screen pixels through --u (viewBox units per CSS pixel, kept by
   art.js), so a hairline is 0.75 px at any size.
   Motion, only after art.js marks the drawing: it draws itself once as it
   comes into view (construction, then object, then dimensions, about 2.5 s),
   then one part keeps working (the drum turns, the token travels, the needle
   sweeps). Loops run only while the drawing is on screen. Under
   prefers-reduced-motion it is static and fully drawn. */

.art{ --u:1; --art-acc:currentColor; display:block; width:100%; height:auto; overflow:visible; }
.art path, .art circle{ fill:none; stroke:currentColor; stroke-width:calc(.75px * var(--u)); stroke-linecap:round; stroke-linejoin:round; }
.art .w{ stroke-width:calc(1.25px * var(--u)); }
.art .f{ stroke-opacity:.5; }
.art .c path, .art .c circle{ stroke-opacity:.5; }
.art .c .f{ stroke-opacity:.3; }
.art .cl{ stroke-dasharray:calc(16px * var(--u)) calc(3px * var(--u)) calc(2px * var(--u)) calc(3px * var(--u)); stroke-opacity:.6; }
.art .hd{ stroke-dasharray:calc(4px * var(--u)) calc(3px * var(--u)); stroke-opacity:.6; }
.art .ht{ stroke-opacity:.6; }
.art .fa{ fill:currentColor; stroke:none; }
.art .a{ stroke:var(--art-acc); }
.art .fa.a{ fill:var(--art-acc); }
.art .af{ fill:var(--art-acc); fill-opacity:.22; }
.art text{ font-family:"DM Sans", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; font-size:15px; font-weight:500; letter-spacing:.05em;
  fill:currentColor; stroke:none; font-variant-numeric:tabular-nums lining-nums; }
.art .th{ font-weight:700; }
.art .tn{ font-size:13px; font-weight:700; letter-spacing:0; }
.art .tq{ font-size:10px; font-weight:700; letter-spacing:0; }
.art .tl{ font-size:24px; font-weight:700; letter-spacing:.08em; }
.art .m{ text-anchor:middle; }
.art .e{ text-anchor:end; }
/* lettering that would render under 10 px is dropped (art.js sets .h10 … .h24 by size) */
.art.h10 .tq, .art.h13 .tn, .art.h15 .t, .art.h24 .tl{ display:none; }
.art.h15 .tb{ display:none; }   /* a table or stamp frame goes with its lettering */
/* the moving parts' resting state */
.art .pen{ stroke:var(--art-acc); stroke-width:calc(2.25px * var(--u)); opacity:0; }

/* ── drawing itself in ─────────────────────────────────────────────── */
.art .c{ --b:0s; } .art .o{ --b:.55s; } .art .d{ --b:1.3s; } .art .x{ --b:1.45s; }
.art .k0{ --k:0s; } .art .k1{ --k:.1s; } .art .k2{ --k:.2s; } .art .k3{ --k:.3s; } .art .k4{ --k:.4s; } .art .k5{ --k:.5s; }
/* waiting to be drawn: .pend (set by art.js), or before art.js runs on a page that set html.art-js */
.art.pend .q, html.art-js .art:not(.on) .q{ stroke-dasharray:1 2; stroke-dashoffset:1; }
.art.pend :is(.cl, .hd, .ht, .fa, .af, text), html.art-js .art:not(.on) :is(.cl, .hd, .ht, .fa, .af, text){ opacity:0; }
.art.on .q{ stroke-dasharray:1 2; stroke-dashoffset:1; animation-name:art-draw; animation-duration:.9s;
  animation-timing-function:cubic-bezier(.45, 0, .2, 1); animation-fill-mode:both; animation-delay:calc(var(--b) + var(--k)); }
.art.on :is(.cl, .hd, .ht, .fa, .af, text){ animation-name:art-fade; animation-duration:.6s; animation-timing-function:ease-out;
  animation-fill-mode:both; animation-delay:calc(var(--b) + var(--k) + .3s); }
@keyframes art-draw{ from{ stroke-dashoffset:1; } to{ stroke-dashoffset:0; } }
@keyframes art-fade{ from{ opacity:0; } to{ opacity:1; } }

/* ── the one part that keeps working, only while on screen ─────────── */
/* BP-001: the drum and the gear train turn (z36 : z20), the stylus writes the trace */
.art.on .s1{ animation:art-spin 28s linear 2.6s infinite; }
.art.on .s2{ animation:art-spin-r calc(28s * 20 / 36) linear 2.6s infinite; }
.art.on .arm{ animation:art-arm 7s ease-in-out 2.6s infinite; }
.art.on .pen.pen{ stroke-dasharray:1 2; animation:art-pen 7s linear 2.6s infinite; }
@keyframes art-spin{ from{ transform:rotate(0deg); } to{ transform:rotate(360deg); } }
@keyframes art-spin-r{ from{ transform:rotate(0deg); } to{ transform:rotate(-360deg); } }
@keyframes art-arm{ 0%, 100%{ transform:rotate(0deg); } 25%{ transform:rotate(-1.4deg); } 60%{ transform:rotate(1.1deg); } }
@keyframes art-pen{ 0%{ stroke-dashoffset:1; opacity:.95; } 78%{ stroke-dashoffset:0; opacity:.95; } 100%{ stroke-dashoffset:0; opacity:0; } }
/* BP-002: a token travels the pipeline, waiting in each chamber */
.art.on .tok{ animation:art-tok 9s cubic-bezier(.5, 0, .3, 1) 2.6s infinite; opacity:0; }
/* BP-003: the needle sweeps the dial and settles on "pending" */
.art.on .ndl{ animation:art-ndl 8s cubic-bezier(.3, 0, .2, 1) 2.4s infinite; }
@keyframes art-tok{
  0%{ transform:translate(0, 0); opacity:0; } 4%{ opacity:1; }
  10%{ transform:translate(0, 146px); } 18%, 26%{ transform:translate(180px, 146px); }
  33%, 41%{ transform:translate(340px, 146px); } 51%, 62%{ transform:translate(556px, 146px); }
  70%, 74%{ transform:translate(722px, 146px); } 84%{ transform:translate(850px, 146px); opacity:1; }
  92%, 100%{ transform:translate(850px, 146px); opacity:0; } }
@keyframes art-ndl{
  0%, 8%{ transform:rotate(0deg); } 38%{ transform:rotate(130deg); } 50%{ transform:rotate(122deg); }
  62%{ transform:rotate(-12deg); } 70%{ transform:rotate(6deg); } 76%{ transform:rotate(-2deg); } 82%, 100%{ transform:rotate(0deg); } }

/* off screen, every loop holds still (art.js drops .live) */
.art.on:not(.live) :is(.spin, .arm, .pen, .tok, .ndl){ animation-play-state:paused; }

@media (prefers-reduced-motion: reduce){
  .art *{ animation:none !important; }
  .art .q{ stroke-dasharray:none !important; stroke-dashoffset:0 !important; }
  .art :is(.cl, .hd, .ht, .fa, .af, text){ opacity:1 !important; }
  .art .pen{ opacity:0 !important; }
  .art .tok{ opacity:1 !important; }
}
