/* ===========================================================================
   loader.css — the app at work (loader.js cardLoader): a holographic card
   turning in 3D, a band of light sweeping its face, inside a spinning ring of
   light in the theme's accent; at the larger sizes a soft glow breathing
   behind and three sparks in orbit; the words shimmer and their dots rise in
   turn.

   Sizes: sm (inline, beside a line of text: the ring and the card), md, lg
   (centred in a space: everything). Full motion plays it; Reduced lets it
   breathe (no movement); Off holds it still. Only transform and opacity
   animate (the shimmer moves a gradient's position: the text is short).
   =========================================================================== */

.card-loader {
  --cl-s: 20px;               /* the stage: the ring's diameter */
  --cl-t: 2.6s;               /* one turn of the card */
  --cl-a: var(--accent);
  --cl-b: var(--accent-2, #a78bfa);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  font-size: 13px;
  color: var(--ink-3);
  vertical-align: middle;
}
.card-loader.is-md { --cl-s: 40px; gap: 12px; font-size: 13.5px; }
.card-loader.is-lg { --cl-s: 116px; gap: 18px; font-size: 14.5px; }
.card-loader.is-block {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  padding: 30px 12px;
  text-align: center;
}

/* ---------------------------------------------------------------- the stage */
.cl-stage {
  position: relative; flex: none; display: grid; place-items: center;
  width: var(--cl-s); height: var(--cl-s);
  perspective: calc(var(--cl-s) * 4);
}
.cl-stage > * { grid-area: 1 / 1; }

/* the glow behind it all */
.cl-halo {
  width: 150%; height: 150%; border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--cl-a) 34%, transparent), color-mix(in srgb, var(--cl-b) 14%, transparent) 55%, transparent 72%);
  filter: blur(calc(var(--cl-s) * .06));
  opacity: .9;
}

/* the ring: an arc of light, bright at its head and fading round to nothing */
.cl-ring {
  width: 100%; height: 100%; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 18%, color-mix(in srgb, var(--cl-b) 70%, transparent) 55%, var(--cl-a) 92%, #fff 98%, transparent 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - max(2px, var(--cl-s) * .055)), #000 calc(100% - max(2px, var(--cl-s) * .055) + .5px));
          mask: radial-gradient(farthest-side, transparent calc(100% - max(2px, var(--cl-s) * .055)), #000 calc(100% - max(2px, var(--cl-s) * .055) + .5px));
  filter: drop-shadow(0 0 calc(var(--cl-s) * .05) color-mix(in srgb, var(--cl-a) 70%, transparent));
}
/* a faint track under the arc */
.cl-stage::before {
  content: ""; grid-area: 1 / 1; width: 100%; height: 100%; border-radius: 50%;
  box-shadow: inset 0 0 0 max(2px, calc(var(--cl-s) * .055)) color-mix(in srgb, var(--ink) 8%, transparent);
}

/* at the larger sizes, a fine dashed ring inside, turning the other way */
.card-loader:is(.is-md, .is-lg) .cl-stage::after {
  content: ""; grid-area: 1 / 1; width: 80%; height: 80%; border-radius: 50%;
  border: max(1px, calc(var(--cl-s) * .012)) dashed color-mix(in srgb, var(--cl-b) 40%, transparent);
}

/* three sparks on an orbit a little outside the ring */
.cl-orbit { width: 124%; height: 124%; }
.cl-orbit i {
  position: absolute; left: 50%; top: 0;
  width: calc(var(--cl-s) * .07); height: calc(var(--cl-s) * .07); margin-left: calc(var(--cl-s) * -.035);
  border-radius: 50%; background: #fff;
  box-shadow: 0 0 calc(var(--cl-s) * .08) calc(var(--cl-s) * .02) var(--cl-a);
  transform-origin: 50% calc(var(--cl-s) * .62);
}
.cl-orbit i:nth-child(2) { transform: rotate(120deg); width: calc(var(--cl-s) * .05); height: calc(var(--cl-s) * .05); box-shadow: 0 0 calc(var(--cl-s) * .08) var(--cl-b); }
.cl-orbit i:nth-child(3) { transform: rotate(240deg); opacity: .7; }

/* the card: a face and a back, turning; a band of light across it */
.cl-card {
  position: relative;
  width: calc(var(--cl-s) * .44); aspect-ratio: .714;
  transform-style: preserve-3d;
  transform: rotateY(-22deg) rotateX(8deg);
}
.cl-face, .cl-back, .cl-sheen {
  position: absolute; inset: 0; border-radius: 11% / 8%;
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
}
/* the face: a holographic foil, an art window and two lines of text */
.cl-face {
  overflow: hidden;
  background:
    conic-gradient(from 210deg at 30% 30%, #ff9ad5, #ffe08a, #8affc1, #8ad8ff, #c79bff, #ff9ad5);
  box-shadow:
    inset 0 0 0 max(1px, calc(var(--cl-s) * .018)) rgba(255, 255, 255, .85),
    0 calc(var(--cl-s) * .05) calc(var(--cl-s) * .12) rgba(0, 0, 0, .35);
}
.cl-face::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(160deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, 0) 45%, rgba(0, 0, 0, .12));
}
.cl-art {
  position: absolute; left: 12%; right: 12%; top: 11%; height: 44%; border-radius: 6%;
  background: linear-gradient(135deg, var(--cl-a), var(--cl-b));
  box-shadow: inset 0 0 0 max(1px, calc(var(--cl-s) * .012)) rgba(255, 255, 255, .7);
}
.cl-line {
  position: absolute; left: 14%; right: 14%; top: 64%; height: 6%; border-radius: 99px;
  background: rgba(20, 24, 32, .38);
}
.cl-line.is-short { top: 76%; right: 38%; background: rgba(20, 24, 32, .22); }
/* the back: the accent, a ring emblem in the middle, a fine weave */
.cl-back {
  transform: rotateY(180deg);
  background:
    radial-gradient(circle at 50% 50%, transparent 0 17%, rgba(255, 255, 255, .7) 18% 23%, transparent 24%),
    repeating-linear-gradient(45deg, rgba(255, 255, 255, .12) 0 1px, transparent 1px 4px),
    linear-gradient(150deg, color-mix(in srgb, var(--cl-a) 80%, #fff), var(--cl-a) 45%, color-mix(in srgb, var(--cl-b) 70%, #000));
  box-shadow:
    inset 0 0 0 max(1px, calc(var(--cl-s) * .018)) rgba(255, 255, 255, .6),
    0 calc(var(--cl-s) * .05) calc(var(--cl-s) * .12) rgba(0, 0, 0, .35);
}
/* the band of light, sweeping across whichever side is to the front */
.cl-sheen {
  overflow: hidden; pointer-events: none;
  -webkit-backface-visibility: visible; backface-visibility: visible;
}
.cl-sheen::before {
  content: ""; position: absolute; top: -20%; bottom: -20%; left: -60%; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .85), transparent);
  transform: translateX(-30%) skewX(-12deg);
  opacity: 0;
}

/* ------------------------------------------------------------- the words */
.cl-label { display: inline-flex; align-items: baseline; min-width: 0; max-width: 100%; }
.cl-words { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-loader.is-block .cl-label { justify-content: center; }
.card-loader.is-block .cl-words { white-space: normal; }
.card-loader.is-lg .cl-label { font-weight: 600; letter-spacing: .01em; }
.cl-dots { display: inline-flex; flex: none; }
.cl-dots i { font-style: normal; display: inline-block; }

/* ------------------------------------------------------------- the sizes */
/* inline: the ring and the card, nothing round them */
.card-loader.is-sm .cl-halo, .card-loader.is-sm .cl-orbit { display: none; }
.card-loader.is-sm .cl-card { width: calc(var(--cl-s) * .5); }
.card-loader.is-md .cl-orbit { display: none; }

/* ---------------------------------------------------------------- motion */
:root[data-motion="full"] .cl-ring { animation: cl-spin 1.15s linear infinite; }
:root[data-motion="full"] .cl-orbit { animation: cl-spin 3.6s linear infinite reverse; }
:root[data-motion="full"] .card-loader:is(.is-md, .is-lg) .cl-stage::after { animation: cl-spin 9s linear infinite reverse; }
:root[data-motion="full"] .cl-halo { animation: cl-glow var(--cl-t) ease-in-out infinite; }
:root[data-motion="full"] .cl-card { animation: cl-turn var(--cl-t) cubic-bezier(.55, .05, .3, 1) infinite; }
:root[data-motion="full"] .cl-sheen::before { animation: cl-sweep var(--cl-t) ease-in-out infinite; }
:root[data-motion="full"] .card-loader:is(.is-md, .is-lg) .cl-words {
  background: linear-gradient(90deg, var(--ink-3) 0%, var(--ink-3) 35%, var(--ink) 50%, var(--ink-3) 65%, var(--ink-3) 100%) 0 0 / 300% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: cl-shimmer 2.4s linear infinite;
}
:root[data-motion="full"] .cl-dots i { animation: cl-dot 1.2s ease-in-out infinite; }
:root[data-motion="full"] .cl-dots i:nth-child(2) { animation-delay: .15s; }
:root[data-motion="full"] .cl-dots i:nth-child(3) { animation-delay: .3s; }

@keyframes cl-spin { to { transform: rotate(360deg); } }
/* a whole turn with a pause face-on, floating up a little as it goes */
@keyframes cl-turn {
  0%   { transform: translateY(0) rotateY(-22deg) rotateX(8deg); }
  45%  { transform: translateY(-6%) rotateY(158deg) rotateX(-6deg); }
  55%  { transform: translateY(-6%) rotateY(158deg) rotateX(-6deg); }
  100% { transform: translateY(0) rotateY(338deg) rotateX(8deg); }
}
@keyframes cl-sweep {
  0%, 18%  { opacity: 0; transform: translateX(-30%) skewX(-12deg); }
  30%      { opacity: 1; }
  44%, 100% { opacity: 0; transform: translateX(380%) skewX(-12deg); }
}
@keyframes cl-glow {
  0%, 100% { opacity: .55; transform: scale(.9); }
  50%      { opacity: 1; transform: scale(1.06); }
}
@keyframes cl-shimmer { from { background-position: 100% 0; } to { background-position: -50% 0; } }
@keyframes cl-dot {
  0%, 60%, 100% { transform: translateY(0); opacity: .45; }
  30%           { transform: translateY(-35%); opacity: 1; }
}

/* Reduced: no movement, only a slow breath. Off: still. */
:root[data-motion="reduced"] .cl-stage { animation: cl-breathe 1.8s ease-in-out infinite; }
@keyframes cl-breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: .5; }
}

/* In a button (Show more, Load more), it sits small beside its words, in their colour. */
.btn .card-loader { --cl-s: 15px; gap: 8px; font-size: inherit; color: inherit; }
.btn .card-loader .cl-card { display: none; }
@media print { .card-loader { display: none; } }

/* ------------------------------------------------------------- skeletons
   The placeholders the pages stand up while they load (design.css .skeleton)
   catch the same light: a soft band in the accent sweeping across. */
.skeleton::after {
  background: linear-gradient(100deg,
    transparent 30%,
    color-mix(in srgb, var(--accent) 10%, transparent) 42%,
    color-mix(in srgb, #fff 10%, transparent) 50%,
    color-mix(in srgb, var(--accent-2, #a78bfa) 9%, transparent) 58%,
    transparent 70%);
  animation-duration: 1.6s;
  animation-timing-function: cubic-bezier(.45, 0, .35, 1);
}
:root[data-theme="light"] .skeleton::after {
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .7) 50%, transparent 70%);
}
