/* Cute loaders — six animated SVG/CSS loaders ported from the
   Claude Design "EZdoc Loaders" handoff bundle (IDs 1, 4, 5, 6, 8, 10).
   Used by:
     - app/views/make_wizard/show.html.erb (generation_stream_controller#mountLoader)
     - app/views/seo_pages/_hero_animation_overlays.html.erb (the SEO hero loop)
   Picked at random by the consumer. Class prefix .cl-l<id>-* scopes
   each loader's internal classes. Local --l-* palette aliases keep
   the design's color tokens close to the rules that use them. */
.cl-loader {
  --l-blue-200:#bfdbfe; --l-blue-300:#93c5fd; --l-blue-500:#3b82f6; --l-blue-600:#2563eb;
  --l-indigo-500:#6366f1; --l-sky-500:#0ea5e9;
  --l-amber-400:#fbbf24; --l-amber-500:#f59e0b;
  --l-green-500:#22c55e; --l-pink-500:#ec4899;
  --l-g-200:#e5e7eb; --l-g-300:#d1d5db; --l-g-700:#374151;
  --l-sk:#eef1f7; /* skeleton track for the type-in document fill */
  --l-sh-sm:0 1px 3px rgba(0,0,0,.04);
  --l-sh-doc:0 1px 2px rgba(17,24,39,.05),0 28px 50px -28px rgba(17,24,39,.28),0 12px 24px -14px rgba(17,24,39,.12);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 22px;
  min-height: 220px;
}
.cl-loader-art {
  width: 150px; height: 120px;
  position: relative;
  display: flex; align-items: center; justify-content: center;
}
.cl-loader-caption {
  min-height: 22px;
  text-align: center;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--st-ink-2);
  letter-spacing: -.005em;
  max-width: 300px;
  transition: opacity .32s ease, transform .32s ease;
}

/* Generation-wait loader only (.cl-loader--gen, mounted by
   generation_stream_controller#mountLoader). Scaled up ~1.5× for
   presence in the wide stream canvas; the margin reserves the room the
   transform adds so the caption doesn't collide. The SEO hero loop
   (shared/_cute_loader) has no --gen modifier, so it stays small. */
.cl-loader--gen .cl-loader-art { transform: scale(1.5); margin: 30px 0; }

/* The doc-name line under the caption (seeded from doc_type, upgraded to
   the streamed <title>). Grouped with the caption so its spacing is
   independent of the larger art→text gap. */
.cl-loader-texts { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.cl-loader-title {
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--st-ink, #1f2937);
  letter-spacing: -.01em;
  line-height: 1.3;
  max-width: 320px;
}

/* Soft accent halo behind the art. Inherits --l-blue-600, so it sits at
   the default blue until the accent sniff repaints it. z-index:-1 keeps
   it behind the art content (the art's scale() transform makes
   .cl-loader-art a stacking context, so it can't slip behind the loader).
   It rides the art's scale() since it's a child — proportional halo. */
.cl-loader-glow {
  position: absolute;
  left: 50%; top: 50%;
  width: 138px; height: 138px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--l-blue-600) 0%, transparent 68%);
  filter: blur(22px);
  z-index: -1;
  pointer-events: none;
  animation: cl-glow-pulse 2.6s ease-in-out infinite;
}
@keyframes cl-glow-pulse {
  0%, 100% { opacity: .13; transform: translate(-50%, -50%) scale(.9); }
  50%      { opacity: .26; transform: translate(-50%, -50%) scale(1.08); }
}

/* The live % counter under the document. Driven from the controller
   (applyLoaderFill), it ticks in lockstep with the fill. */
.cl-loader-pct {
  text-align: center;
  font-size: 17px; font-weight: 750;
  color: var(--l-blue-600);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.cl-loader-pct small {
  display: block;
  font-size: 9px; font-weight: 600;
  color: var(--st-muted, #9aa3b8);
  letter-spacing: .05em; text-transform: uppercase;
  margin-top: 2px;
}

/* ─── Type-in document fill (generation loader only) ──────────────────
   Each loader's document carries skeleton placeholder lines; an accent
   fill "types in" left→right, line by line, top→down, driven per-line by
   the controller (applyLoaderFill). The deeper the fill, the further the
   generation. Scoped to .cl-loader--gen so the SEO hero loop, which has
   no fill markup, keeps its original looping animations untouched. */
.cl-loader--gen .cl-dlay {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  box-sizing: border-box;
}
.cl-loader--gen .cl-dlay .h,
.cl-loader--gen .cl-dlay .r {
  background: var(--l-sk); position: relative; overflow: hidden;
}
.cl-loader--gen .cl-dlay .h > i,
.cl-loader--gen .cl-dlay .r > i {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: var(--l-blue-600); border-radius: inherit;
  transition: width .18s linear;
}
.cl-loader--gen .cl-dlay .r > i { opacity: .92; }

/* Init shimmer — while the loader is initializing, the empty skeleton lines
   sweep a soft highlight (the familiar "preparing" cue) before the fill
   begins. Toggled by the .is-init class from applyLoaderFill. */
.cl-loader--gen.is-init .cl-dlay .h,
.cl-loader--gen.is-init .cl-dlay .r {
  background-image: linear-gradient(90deg, var(--l-sk) 0%, #fafbff 50%, var(--l-sk) 100%);
  background-size: 220% 100%;
  animation: cl-init-shimmer 1.25s ease-in-out infinite;
}
@keyframes cl-init-shimmer { 0% { background-position: 180% 0; } 100% { background-position: -120% 0; } }

/* L1 — the page becomes the document; lines type in as it floats */
.cl-loader--gen .cl-l1-page { position: relative; overflow: hidden; }
.cl-loader--gen .cl-l1-page .cl-dlay { padding: 13px 12px; gap: 8px; }
.cl-loader--gen .cl-l1-page .h { height: 9px; width: 60%; border-radius: 3px; }
.cl-loader--gen .cl-l1-page .r { height: 6px; border-radius: 3px; }
.cl-loader--gen .cl-l1-page .r:nth-child(4) { width: 92%; }
.cl-loader--gen .cl-l1-page .r:nth-child(5) { width: 80%; }

/* L4 — three bouncing documents fill together */
.cl-loader--gen .cl-l4-doc { overflow: hidden; }
.cl-loader--gen .cl-l4-doc::before { display: none; }
.cl-loader--gen .cl-l4-doc .cl-dlay { padding: 5px 4px; gap: 3px; }
.cl-loader--gen .cl-l4-doc .h { height: 3px; width: 62%; border-radius: 1px; }
.cl-loader--gen .cl-l4-doc .r { height: 2px; border-radius: 1px; }

/* L6 — the orbiting core fills; its built-in lines are replaced */
.cl-loader--gen .cl-l6-core { overflow: hidden; }
.cl-loader--gen .cl-l6-core::before { display: none; }
.cl-loader--gen .cl-l6-core .cl-dlay { padding: 11px 9px; gap: 7px; }
.cl-loader--gen .cl-l6-core .h { height: 6px; width: 58%; border-radius: 2px; }
.cl-loader--gen .cl-l6-core .r { height: 4px; border-radius: 2px; }

/* L5 — a larger document sits ON the belt (the .cl-dlay fill needs the
   document to STAY position:absolute, which the generic fill would
   otherwise not change here — its travel animation is stopped so it fills
   in place). Taller scene gives the star clear room above the doc. */
.cl-loader--gen.cl-loader-5 .cl-loader-art { height: 150px; }
.cl-loader--gen .cl-l5-scene { height: 126px; overflow: visible; }
.cl-loader--gen .cl-l5-doc {
  position: absolute; overflow: hidden; animation: none;
  width: 48px; height: 60px; left: 50%; margin-left: -24px; bottom: 14px;
  border-top: 3px solid var(--l-blue-600);
}
.cl-loader--gen .cl-l5-doc::before { display: none; }
.cl-loader--gen .cl-l5-doc .cl-dlay { padding: 7px 6px; gap: 5px; }
.cl-loader--gen .cl-l5-doc .h { height: 4px; width: 60%; border-radius: 2px; }
.cl-loader--gen .cl-l5-doc .r { height: 3px; border-radius: 2px; }
.cl-loader--gen .cl-l5-belt { bottom: 8px; }
.cl-loader--gen .cl-l5-stamp { top: 6px; animation: cl-l5stampg 2.4s cubic-bezier(.5, 0, .4, 1) infinite; }
@keyframes cl-l5stampg {
  0%, 36% { transform: translateY(0) scale(.9); }
  52%     { transform: translateY(40px) scale(1.06); }
  68%, 100% { transform: translateY(0) scale(.9); }
}

/* L8 — pixel rows light top→down; the blocks fill left→right (no loop) */
.cl-loader--gen .cl-l8-blk { animation: none; background: var(--l-sk); }
.cl-loader--gen .cl-l8-blk.lit { background: var(--l-blue-600); }
.cl-loader--gen .cl-l8-prow { fill: var(--l-sk); }
.cl-loader--gen .cl-l8-prow.lit { fill: var(--l-blue-600); }

/* L10 — the shuffle stops; cards fan out and complete one by one */
.cl-loader--gen .cl-l10-card { animation: none; padding: 0; overflow: hidden; }
.cl-loader--gen .cl-l10-deck .cl-l10-card:nth-child(1) { transform: translate(-22px, 7px) rotate(-12deg); z-index: 1; }
.cl-loader--gen .cl-l10-deck .cl-l10-card:nth-child(2) { transform: translate(-8px, 2px) rotate(-4deg); z-index: 2; }
.cl-loader--gen .cl-l10-deck .cl-l10-card:nth-child(3) { transform: translate(7px, 1px) rotate(4deg); z-index: 3; }
.cl-loader--gen .cl-l10-deck .cl-l10-card:nth-child(4) { transform: translate(21px, 6px) rotate(12deg); z-index: 4; }
.cl-loader--gen .cl-l10-card .cl-dlay { padding: 11px 10px; gap: 6px; }
.cl-loader--gen .cl-l10-card .h { height: 7px; width: 60%; border-radius: 3px; }
.cl-loader--gen .cl-l10-card .r { height: 4px; border-radius: 2px; }

/* LOADER 1 — Self-writing page */
.cl-l1-page {
  width:88px; height:112px; background:#fff; border:1px solid var(--l-g-200); border-radius:7px;
  box-shadow:var(--l-sh-doc); padding:13px 12px; display:flex; flex-direction:column; gap:8px;
  animation:cl-l1float 3.4s ease-in-out infinite;
}
@keyframes cl-l1float { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-6px)} }
.cl-l1-head { height:9px; width:60%; border-radius:3px; background:var(--l-blue-600); }
.cl-l1-row {
  height:6px; border-radius:3px; background:var(--l-g-200);
  transform:scaleX(0); transform-origin:left;
  animation:cl-l1write 3.2s cubic-bezier(.4,0,.2,1) infinite;
}
.cl-l1-row.b { background:var(--l-blue-200); }
.cl-l1-row:nth-child(2){ animation-delay:.1s; }
.cl-l1-row:nth-child(3){ animation-delay:.5s; width:92%; }
.cl-l1-row:nth-child(4){ animation-delay:.9s; width:80%; }
.cl-l1-row:nth-child(5){ animation-delay:1.3s; width:88%; }
@keyframes cl-l1write { 0%{transform:scaleX(0)} 28%,82%{transform:scaleX(1)} 100%{transform:scaleX(1)} }
.cl-l1-spark {
  position:absolute; top:8px; right:18px; width:26px; height:26px; color:var(--l-amber-400);
  animation:cl-l1twinkle 1.8s ease-in-out infinite;
}
@keyframes cl-l1twinkle { 0%,100%{transform:scale(.7) rotate(0);opacity:.5} 50%{transform:scale(1) rotate(20deg);opacity:1} }

/* LOADER 4 — Bouncy doc dots */
.cl-l4-row { display:flex; gap:14px; align-items:flex-end; height:60px; }
.cl-l4-doc {
  width:26px; height:33px; background:#fff; border:1.5px solid var(--l-g-200); border-radius:4px;
  position:relative; box-shadow:var(--l-sh-sm); animation:cl-l4bounce 1.1s cubic-bezier(.5,.05,.5,1) infinite;
}
.cl-l4-doc:nth-child(2){ animation-delay:.16s; }
.cl-l4-doc:nth-child(3){ animation-delay:.32s; }
.cl-l4-doc::before {
  content:""; position:absolute; left:5px; right:5px; top:7px;
  height:2px; border-radius:2px; background:var(--l-blue-300);
  box-shadow:0 5px 0 var(--l-g-200),0 10px 0 var(--l-g-200);
}
.cl-l4-doc:nth-child(1){ --tint:var(--l-blue-500); }
.cl-l4-doc:nth-child(2){ --tint:var(--l-indigo-500); }
.cl-l4-doc:nth-child(3){ --tint:var(--l-sky-500); }
.cl-l4-doc { border-top:3px solid var(--tint); }
@keyframes cl-l4bounce {
  0%,100%{ transform:translateY(0) scaleY(1) scaleX(1); }
  30%{ transform:translateY(-26px) scaleY(1.08) scaleX(.94); }
  55%{ transform:translateY(0) scaleY(.86) scaleX(1.12); }
  70%{ transform:translateY(0) scaleY(1); }
}

/* LOADER 5 — Assembly belt */
.cl-l5-scene { width:150px; height:104px; position:relative; overflow:hidden; }
.cl-l5-belt {
  position:absolute; left:0; right:0; bottom:18px; height:8px; border-radius:4px;
  background:repeating-linear-gradient(90deg,var(--l-g-300) 0 7px,var(--l-g-200) 7px 14px);
  background-size:14px 100%; animation:cl-l5belt .6s linear infinite;
}
@keyframes cl-l5belt { to { background-position:-14px 0; } }
.cl-l5-doc {
  position:absolute; bottom:26px; left:0; width:30px; height:38px; border-radius:4px;
  background:#fff; border:1.5px solid var(--l-g-200); box-shadow:var(--l-sh-sm);
  animation:cl-l5move 2.4s linear infinite;
}
.cl-l5-doc::before {
  content:""; position:absolute; left:5px; right:5px; top:6px; height:2px; background:var(--l-g-200);
  box-shadow:0 5px 0 var(--l-g-200),0 10px 0 var(--l-g-200); border-radius:2px;
}
@keyframes cl-l5move {
  0%{ left:-32px; border-top:1.5px solid var(--l-g-200); }
  49%{ border-top:1.5px solid var(--l-g-200); }
  56%{ border-top:4px solid var(--l-green-500); transform:translateY(0); }
  100%{ left:150px; border-top:4px solid var(--l-green-500); }
}
.cl-l5-stamp {
  position:absolute; left:50%; top:6px; width:34px; height:30px; margin-left:-17px;
  color:var(--l-blue-600);
  animation:cl-l5stamp 2.4s cubic-bezier(.5,0,.4,1) infinite;
}
@keyframes cl-l5stamp {
  0%,40%{ transform:translateY(-4px) scale(.9); }
  50%{ transform:translateY(34px) scale(1.05); }
  60%,100%{ transform:translateY(-4px) scale(.9); }
}

/* LOADER 6 — Orbiting sparkles */
.cl-l6-core {
  width:56px; height:70px; background:#fff; border:1px solid var(--l-g-200); border-radius:7px;
  box-shadow:var(--l-sh-doc); position:relative; z-index:2;
  animation:cl-l6pulse 2s ease-in-out infinite;
}
.cl-l6-core::before {
  content:""; position:absolute; left:9px; right:9px; top:12px; height:3px; border-radius:2px;
  background:var(--l-blue-600); box-shadow:0 8px 0 var(--l-g-200),0 16px 0 var(--l-g-200),0 24px 0 var(--l-g-200);
}
@keyframes cl-l6pulse { 0%,100%{ transform:scale(1); } 50%{ transform:scale(1.05); } }
.cl-l6-orbit { position:absolute; inset:0; display:grid; place-items:center; animation:cl-l6spin 4.6s linear infinite; }
.cl-l6-orbit.b { animation-duration:3.2s; animation-direction:reverse; }
.cl-l6-sat { position:absolute; color:var(--l-amber-400); width:18px; height:18px; animation:cl-l6twk 1.4s ease-in-out infinite; }
.cl-l6-orbit .cl-l6-sat:nth-child(1){ transform:translate(64px,0); }
.cl-l6-orbit .cl-l6-sat:nth-child(2){ transform:translate(-64px,0); color:var(--l-pink-500); }
.cl-l6-orbit.b .cl-l6-sat:nth-child(1){ transform:translate(0,-48px); color:var(--l-sky-500); }
@keyframes cl-l6spin { to { transform:rotate(360deg); } }
@keyframes cl-l6twk { 0%,100%{ opacity:.55; } 50%{ opacity:1; } }

/* LOADER 8 — Pixel quest (retro) */
.cl-l8-scene { display:flex; flex-direction:column; align-items:center; gap:14px; }
.cl-l8-svg {
  width:64px; height:64px; image-rendering:pixelated;
  animation:cl-l8hop 1.2s steps(2) infinite;
}
@keyframes cl-l8hop { 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-7px); } }
.cl-l8-bar { display:flex; gap:4px; }
.cl-l8-blk { width:11px; height:11px; background:var(--l-g-200); animation:cl-l8load 1.6s steps(1) infinite; }
.cl-l8-blk:nth-child(1){ animation-delay:0s }
.cl-l8-blk:nth-child(2){ animation-delay:.2s }
.cl-l8-blk:nth-child(3){ animation-delay:.4s }
.cl-l8-blk:nth-child(4){ animation-delay:.6s }
.cl-l8-blk:nth-child(5){ animation-delay:.8s }
.cl-l8-blk:nth-child(6){ animation-delay:1.0s }
@keyframes cl-l8load { 0%{ background:var(--l-g-200); } 50%,100%{ background:var(--l-blue-600); } }

/* LOADER 10 — Card shuffle deck */
.cl-l10-deck { position:relative; width:78px; height:100px; }
.cl-l10-card {
  position:absolute; inset:0; background:#fff; border:1px solid var(--l-g-200); border-radius:8px;
  box-shadow:var(--l-sh-sm); padding:11px 10px; display:flex; flex-direction:column; gap:6px;
  animation:cl-l10cycle 3.2s cubic-bezier(.5,0,.3,1) infinite;
}
.cl-l10-card .hd { height:7px; width:60%; border-radius:3px; }
.cl-l10-card .ln { height:4px; border-radius:2px; background:var(--l-g-200); }
.cl-l10-card .ln:nth-child(3){ width:88%; }
.cl-l10-card .ln:nth-child(4){ width:66%; }
.cl-l10-card:nth-child(1){ animation-delay:0s; }   .cl-l10-card:nth-child(1) .hd { background:var(--l-blue-600); }
.cl-l10-card:nth-child(2){ animation-delay:.8s; }  .cl-l10-card:nth-child(2) .hd { background:var(--l-indigo-500); }
.cl-l10-card:nth-child(3){ animation-delay:1.6s; } .cl-l10-card:nth-child(3) .hd { background:var(--l-amber-500); }
.cl-l10-card:nth-child(4){ animation-delay:2.4s; } .cl-l10-card:nth-child(4) .hd { background:var(--l-green-500); }
@keyframes cl-l10cycle {
  0%{   transform:translate(0,0) rotate(0) scale(1); z-index:4; }
  18%{  transform:translate(58px,-12px) rotate(11deg) scale(1.02); z-index:4; }
  36%{  transform:translate(0,8px) rotate(0) scale(.9); z-index:0; }
  100%{ transform:translate(0,0) rotate(0) scale(1); z-index:0; }
}
