/* ==========================================================
   LANDJOURNEY UNIVERSAL LOADERS
   Pure CSS/SVG. Size-driven by --lj-size (default 40px).
   Color-driven by currentColor OR --lj-color (default brand green).
   Drop-in for Angular — no JS required.
   ========================================================== */

.lj-loader {
  --lj-size: 40px;
  --lj-color: var(--brand-primary-500, #2b9663);
  --lj-color-soft: var(--brand-primary-300, #bcdbb4);
  --lj-color-highlight: var(--accent-highlight-600, #88ffc0);
  --lj-duration: 1.4s;

  width: var(--lj-size);
  height: var(--lj-size);
  display: inline-block;
  position: relative;
  color: var(--lj-color);
  flex-shrink: 0;
}

/* Force SVGs inside to inherit */
.lj-loader svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* Respect reduced motion globally */
@media (prefers-reduced-motion: reduce) {
  .lj-loader * { animation-duration: 4s !important; animation-timing-function: ease-in-out !important; }
}

/* ======================================================
   01 — Stacked Fill
   The logo's three-tone "L" fills itself bottom→top, loops.
   Brand-rooted, most on-brand choice.
   ====================================================== */
.lj-stacked-fill .lj-sf-a,
.lj-stacked-fill .lj-sf-b,
.lj-stacked-fill .lj-sf-c {
  transform-origin: center bottom;
  animation: lj-sf var(--lj-duration) cubic-bezier(.65,.05,.36,1) infinite;
}
.lj-stacked-fill .lj-sf-a { animation-delay: 0s;     fill: var(--lj-color); }
.lj-stacked-fill .lj-sf-b { animation-delay: .18s;   fill: var(--lj-color); opacity: .62; }
.lj-stacked-fill .lj-sf-c { animation-delay: .36s;   fill: var(--lj-color); opacity: .32; }
@keyframes lj-sf {
  0%        { transform: scaleY(0);   opacity: 0; }
  25%       { opacity: 1; }
  55%, 70%  { transform: scaleY(1);   }
  100%      { transform: scaleY(1);   opacity: 0; }
}

/* ======================================================
   02 — Sweep Arc
   A soft arc sweeps around a ring. Minimal, universal.
   The ring has a faint track — feels considered, not mechanical.
   ====================================================== */
.lj-sweep-arc .lj-sa-track { stroke: var(--lj-color); opacity: .14; }
.lj-sweep-arc .lj-sa-arc {
  stroke: var(--lj-color);
  transform-origin: 50% 50%;
  stroke-dasharray: 60 160;
  animation:
    lj-sa-rot var(--lj-duration) linear infinite,
    lj-sa-dash calc(var(--lj-duration) * 1.6) ease-in-out infinite;
}
@keyframes lj-sa-rot { to { transform: rotate(360deg); } }
@keyframes lj-sa-dash {
  0%   { stroke-dasharray: 1 200;  stroke-dashoffset: 0; }
  50%  { stroke-dasharray: 110 90; stroke-dashoffset: -40; }
  100% { stroke-dasharray: 1 200;  stroke-dashoffset: -200; }
}

/* ======================================================
   03 — Tri-Stack Pulse
   Three nested rounded-bottom shapes (the logo's silhouette)
   pulse in sequence. Quieter than Stacked Fill.
   ====================================================== */
.lj-tri-pulse path {
  transform-origin: 50% 100%;
  transform-box: fill-box;
  animation: lj-tp var(--lj-duration) cubic-bezier(.34,1.56,.64,1) infinite;
}
.lj-tri-pulse .lj-tp-1 { fill: var(--lj-color); animation-delay: 0s; }
.lj-tri-pulse .lj-tp-2 { fill: var(--lj-color); opacity: .6;  animation-delay: .12s; }
.lj-tri-pulse .lj-tp-3 { fill: var(--lj-color); opacity: .28; animation-delay: .24s; }
@keyframes lj-tp {
  0%, 100% { transform: translateY(0)     scale(1);    }
  35%      { transform: translateY(-18%)  scale(1.12); }
  60%      { transform: translateY(3%)    scale(.94);  }
  80%      { transform: translateY(-2%)   scale(1.02); }
}

/* ======================================================
   04 — Breathing Dot
   Single dot that breathes — soft concentric ripple.
   The calmest loader. Ideal for inline / small contexts.
   ====================================================== */
.lj-breathe .lj-br-core {
  fill: var(--lj-color);
  transform-origin: 50% 50%;
  animation: lj-br-core calc(var(--lj-duration) * 1.2) ease-in-out infinite;
}
.lj-breathe .lj-br-ring {
  fill: none;
  stroke: var(--lj-color);
  stroke-width: 2;
  transform-origin: 50% 50%;
  animation: lj-br-ring calc(var(--lj-duration) * 1.2) ease-out infinite;
}
.lj-breathe .lj-br-ring-2 { animation-delay: calc(var(--lj-duration) * 0.6); }
@keyframes lj-br-core {
  0%, 100% { transform: scale(.9);  opacity: 1;   }
  50%      { transform: scale(1.15); opacity: .85; }
}
@keyframes lj-br-ring {
  0%   { transform: scale(.6); opacity: .7;  stroke-width: 3; }
  100% { transform: scale(1.6); opacity: 0;   stroke-width: 1; }
}

/* ======================================================
   05 — Soft Orbit
   Three dots orbit a center with trailing opacity.
   Organic, has weight and momentum.
   ====================================================== */
.lj-orbit { animation: lj-orbit-spin calc(var(--lj-duration) * 1.4) linear infinite; }
.lj-orbit circle {
  fill: var(--lj-color);
  transform-origin: 50% 50%;
  animation: lj-orbit-pulse var(--lj-duration) ease-in-out infinite;
}
.lj-orbit circle:nth-child(1) { animation-delay: 0s;   }
.lj-orbit circle:nth-child(2) { animation-delay: .15s; opacity: .7; }
.lj-orbit circle:nth-child(3) { animation-delay: .3s;  opacity: .4; }
@keyframes lj-orbit-spin  { to { transform: rotate(360deg); } }
@keyframes lj-orbit-pulse {
  0%, 100% { transform: scale(.85); }
  50%      { transform: scale(1.1);  }
}

/* ======================================================
   06 — Wave Bar
   Three vertical bars breathing like a waveform.
   Natural, biological — suggests "thinking" not "computing".
   ====================================================== */
.lj-wave { display: inline-flex; align-items: center; justify-content: center; gap: calc(var(--lj-size) * .1); }
.lj-wave span {
  display: inline-block;
  width: calc(var(--lj-size) * .12);
  height: 100%;
  background: var(--lj-color);
  border-radius: calc(var(--lj-size) * .06);
  transform-origin: center;
  animation: lj-wave var(--lj-duration) ease-in-out infinite;
}
.lj-wave span:nth-child(1) { animation-delay: 0s;    }
.lj-wave span:nth-child(2) { animation-delay: .12s;  }
.lj-wave span:nth-child(3) { animation-delay: .24s;  }
.lj-wave span:nth-child(4) { animation-delay: .36s;  }
.lj-wave span:nth-child(5) { animation-delay: .48s;  }
@keyframes lj-wave {
  0%, 100% { transform: scaleY(.35); opacity: .55; }
  50%      { transform: scaleY(1);   opacity: 1;   }
}

/* ======================================================
   07 — Leaf Sway
   A rounded leaf/seed shape gently sways with tonal ripple.
   Most "organic" loader — references growth (the green brand).
   ====================================================== */
.lj-leaf .lj-leaf-shape {
  fill: var(--lj-color);
  transform-origin: 50% 90%;
  animation: lj-leaf-sway calc(var(--lj-duration) * 1.8) ease-in-out infinite;
}
.lj-leaf .lj-leaf-shadow {
  fill: var(--lj-color);
  opacity: .22;
  transform-origin: 50% 90%;
  animation: lj-leaf-sway calc(var(--lj-duration) * 1.8) ease-in-out infinite;
  animation-delay: .18s;
}
@keyframes lj-leaf-sway {
  0%, 100% { transform: rotate(-8deg)  scale(.96); }
  50%      { transform: rotate(8deg)   scale(1);   }
}

/* ======================================================
   08 — Leaf Trail
   A leaf sways with a wider arc; blurred ghost copies lag
   behind it, creating a soft motion trail.
   ====================================================== */
.lj-leaf-trail .lj-lt-shape,
.lj-leaf-trail .lj-lt-ghost {
  fill: var(--lj-color);
  transform-origin: 50% 90%;
  transform-box: view-box;
  animation: lj-lt-sway calc(var(--lj-duration) * 2.1) cubic-bezier(.6,-0.35,.4,1.35) infinite;
}
.lj-leaf-trail .lj-lt-ghost-1 { opacity: .38; animation-delay: -0.11s; }
.lj-leaf-trail .lj-lt-ghost-2 { opacity: .22; animation-delay: -0.24s; }
.lj-leaf-trail .lj-lt-ghost-3 { opacity: .12; animation-delay: -0.39s; }

@keyframes lj-lt-sway {
  0%       { transform: rotate(-28deg) scale(.94); }
  15%      { transform: rotate(-32deg) scale(.93); }
  50%      { transform: rotate( 28deg) scale(1);   }
  65%      { transform: rotate( 32deg) scale(1.01); }
  100%     { transform: rotate(-28deg) scale(.94); }
}

/* ======================================================
   08 — Dotted Ring
   12 dots around a ring fade sequentially. A classic form
   given Landjourney restraint — no harsh drop, soft fade.
   ====================================================== */
.lj-dotted-ring { animation: lj-dr-rot calc(var(--lj-duration) * 1.5) steps(12) infinite; }
.lj-dotted-ring circle { fill: var(--lj-color); }
@keyframes lj-dr-rot { to { transform: rotate(360deg); } }

/* ======================================================
   09 — Progress Strand
   Indeterminate linear bar — for page/section loads.
   Two soft pulses that chase across; quieter than Material's.
   ====================================================== */
.lj-strand {
  --lj-size: 240px;
  width: var(--lj-size);
  height: 3px;
  background: color-mix(in srgb, var(--lj-color) 12%, transparent);
  border-radius: 999px;
  overflow: hidden;
  position: relative;
}
.lj-strand::before,
.lj-strand::after {
  content: "";
  position: absolute; top: 0; left: 0;
  height: 100%;
  background: var(--lj-color);
  border-radius: 999px;
}
.lj-strand::before {
  width: 40%;
  animation: lj-strand-a 2.1s cubic-bezier(.4,0,.2,1) infinite;
}
.lj-strand::after {
  width: 25%;
  animation: lj-strand-b 2.1s cubic-bezier(.4,0,.2,1) infinite;
  animation-delay: 1.05s;
  opacity: .55;
}
@keyframes lj-strand-a {
  0%   { left: -40%; }
  60%  { left: 100%; }
  100% { left: 100%; }
}
@keyframes lj-strand-b {
  0%   { left: -25%; }
  80%  { left: 100%; }
  100% { left: 100%; }
}

/* Overlay variant used by the demo modal */
.lj-overlay {
  position: absolute; inset: 0;
  background: rgba(255,255,255,.78);
  backdrop-filter: blur(2px);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 16px;
  z-index: 10;
}
.lj-overlay-label {
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14px;
  color: var(--brand-primary-700, #104502);
  letter-spacing: .01em;
}
