/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   css/loading.css · PARTS 12 and 15 · the loading set: one definition for every wait, and the live dot (SH-UIUX 2026-10-19)
   Mike, 2026-10-19: "design a spinner… this will be the spinner or load graphic everywhere… if there are multiple
   spinner graphics needed lets create the various ones and reuse them across the web app appropriately."
   Linked on EVERY page, signed in and signed out, before any module's own sheet. Tokens only.
   The set (docs/06-loading.md says when to use which):
     1. .sh-spin                      inline: beside words, in a heading, inside a button. Sized to the text (1em, never under 14 px)
     2. .sh-loading + .sh-spin-lg     block: a panel whose shape isn't known yet (a viewer, a map). Appears only after 400 ms
     3. skeleton bars + .sh-wait      a list or record whose shape IS known (shell.css, already ruled; unchanged)
   And one that isn't a wait (Part 15):
     .sh-live                         something happening now (recording). Never used for loading
   Never a spinner without words beside it. The spinner is aria-hidden; the words carry role="status".
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */
@keyframes sh-turn { to { transform:rotate(360deg); } }
@keyframes sh-breathe { 50% { opacity:.35; } }
@keyframes sh-arrive { from { opacity:0; } to { opacity:1; } }

/* 1 · inline: a ring in the surrounding text's colour, one quarter drawn, turning once every 0.8 s */
.sh-spin { display:inline-block; flex:none; box-sizing:border-box; width:1em; height:1em; min-width:14px; min-height:14px;
  border-radius:50%; border:2px solid color-mix(in srgb, currentColor 22%, transparent); border-top-color:currentColor;
  vertical-align:-.15em; animation:sh-turn .8s linear infinite; }
/* inside a button it sits before the label; the button keeps its width and is disabled while it shows */
.btn .sh-spin { margin-right:var(--space-3); }
/* in a heading it follows the words, a gap after them */
h1 .sh-spin, h2 .sh-spin, h3 .sh-spin { margin-left:var(--space-4); width:.8em; height:.8em; color:var(--accent-fg, var(--blue-700, currentColor)); }

/* 2 · block: centred in the space it's waiting to fill, with its caption under it, after 400 ms (a fast read never flashes it) */
.sh-loading { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--space-4);
  min-height:120px; padding:var(--space-8) var(--space-6); color:var(--text-secondary); font-size:var(--text-sm); text-align:center;
  animation:sh-arrive .2s ease .4s both; }
.sh-spin-lg { width:28px; height:28px; border-width:3px; color:var(--accent-fg, var(--blue-700, currentColor)); }

/* reduced motion: nothing turns; the ring breathes slowly instead, so "working" still reads */
@media (prefers-reduced-motion:reduce) {
  .sh-spin { animation:sh-breathe 1.6s ease-in-out infinite; border-color:currentColor; }
  .sh-loading { animation:sh-arrive 0s linear .4s both; }   /* no fade, but still the 400 ms: a fast read never flashes it */
}

/* 4 · the live dot: something happening now (a recording). Not a loader: rule 5 keeps pulses away from waits.
   An 8 px dot in the danger colour that breathes every 1.6 s; with reduced motion it holds still and the words say "Recording". */
@keyframes sh-live { 50% { opacity:.3; } }
.sh-live { display:inline-block; flex:none; width:8px; height:8px; border-radius:50%; background:var(--danger-fg, currentColor);
  vertical-align:middle; animation:sh-live 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion:reduce) { .sh-live { animation:none; } }

/* 5 · the brand loader (Part 24): a record tab's FIRST read. Mike, 2026-10-19: "replace it with the stratahawk logo
   animation and there it can say 'loading units'". No box, no card: the mark and its words on the page itself,
   centred where the list will be, after 400 ms. The three strokes of the mark draw left to right, hold, and sweep on,
   over a faint copy of themselves so the mark always reads. Built by ShBrandLoad.html(noun) in js/brand-load.js. */
@keyframes sh-wing { 0% { stroke-dashoffset:1; } 42%, 62% { stroke-dashoffset:0; } 100% { stroke-dashoffset:-1; } }
.sh-brandload { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--space-5);
  min-height:min(46vh, 420px); padding:var(--space-8) var(--space-6); text-align:center; animation:sh-arrive .25s ease .4s both; }
.sh-brandload-mark { width:64px; height:64px; display:block; flex:none; border-radius:13px;
  box-shadow:0 6px 18px rgba(13,42,68,.28); }
.sh-brandload-mark .pl { fill:#0d2a44; }                                  /* the plate: the logo's own navy, both themes */
.sh-brandload-mark path { fill:none; stroke:#e6e9ed; stroke-linecap:round; }
.sh-brandload-mark .gh path { opacity:.18; }                             /* the faint copy that keeps the mark readable */
.sh-brandload-mark .dr path { stroke-dasharray:1 1; stroke-dashoffset:1; animation:sh-wing 2.4s cubic-bezier(.45,.05,.25,1) infinite; }
.sh-brandload-mark .dr path:nth-child(2) { animation-delay:.14s; }
.sh-brandload-mark .dr path:nth-child(3) { animation-delay:.28s; }
.sh-brandload-msg { margin:0; font-size:var(--text-md, 15px); color:var(--text-secondary); }
.sh-brandload-slow { margin:calc(-1 * var(--space-3)) 0 0; font-size:var(--text-sm); color:var(--text-muted); }
@media (prefers-reduced-motion:reduce) {
  .sh-brandload { animation:sh-arrive 0s linear .4s both; }
  .sh-brandload-mark .dr path { animation:none; stroke-dashoffset:0; }
  .sh-brandload-mark { animation:sh-breathe 2.4s ease-in-out infinite; }  /* the whole mark breathes; nothing draws */
}
