/* LSense loader: the animated mark (LsLoaderMarkup) for the whole site — portal, admin and boot.
   Light by default; the portal's data-cp-theme="dark" and the admin's data-bs-theme="dark" flip it. */
:root {
  --ll-frame: #1b2840;
  --ll-accent: #1f66f2;
  --ll-node: #ffffff;
  --ll-text: #1b2840;
  --ll-muted: #66788f;
  --ll-veil: rgba(244, 247, 251, 0.86);
  --ll-glow: rgba(31, 102, 242, 0.28);
}

html[data-cp-theme="dark"],
html[data-bs-theme="dark"] {
  --ll-frame: #dbe6f7;
  --ll-accent: #4a9bff;
  --ll-node: #0b1524;
  --ll-text: #eef3fa;
  --ll-muted: #8ea3bb;
  --ll-veil: rgba(7, 15, 26, 0.86);
  --ll-glow: rgba(74, 155, 255, 0.35);
}

/* ---- The mark ------------------------------------------------------------ */
.ls-mark {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.ls-mark-frame {
  stroke: var(--ll-frame);
  stroke-width: 9;
  stroke-dasharray: 290;
  stroke-dashoffset: 290;
  animation: ll-frame 0.9s cubic-bezier(0.65, 0, 0.35, 1) forwards;
}

.ls-mark-bar {
  fill: var(--ll-frame);
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: ll-bar 1.25s ease-in-out infinite;
}

.ls-mark-bar.is-accent {
  fill: var(--ll-accent);
}

.ls-mark-bar.b2 { animation-delay: 0.12s; }
.ls-mark-bar.b3 { animation-delay: 0.24s; }
.ls-mark-bar.b4 { animation-delay: 0.36s; }
.ls-mark-bar.b5 { animation-delay: 0.48s; }

.ls-mark-line {
  stroke: var(--ll-accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 72;
  stroke-dashoffset: 72;
  animation: ll-line 2.4s ease-in-out infinite;
}

.ls-mark-nodes circle {
  fill: var(--ll-node);
  stroke: var(--ll-accent);
  stroke-width: 2.6;
  transform-box: fill-box;
  transform-origin: center;
  animation: ll-node 2.4s ease-in-out infinite;
}

.ls-mark-nodes .n2 { animation-delay: 0.18s; }
.ls-mark-nodes .n3 { animation-delay: 0.36s; }
.ls-mark-nodes .n4 { animation-delay: 0.54s; }
.ls-mark-nodes .n5 { animation-delay: 0.72s; }

.ls-mark-wave {
  stroke: var(--ll-accent);
  stroke-width: 5.5;
  animation: ll-wave 1.6s ease-in-out infinite;
}

.ls-mark-wave.w2 {
  animation-delay: 0.25s;
}

.ls-mark-base {
  fill: var(--ll-frame);
}

.ls-mark-dot {
  fill: var(--ll-accent);
  transform-box: fill-box;
  transform-origin: center;
  animation: ll-dot 1.6s ease-in-out infinite;
}

@keyframes ll-frame {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes ll-bar {
  0%,
  100% {
    transform: scaleY(0.4);
  }

  50% {
    transform: scaleY(1);
  }
}

@keyframes ll-line {
  0% {
    stroke-dashoffset: 72;
  }

  45%,
  75% {
    stroke-dashoffset: 0;
  }

  100% {
    stroke-dashoffset: -72;
  }
}

@keyframes ll-node {
  0%,
  10% {
    opacity: 0;
    transform: scale(0.3);
  }

  30%,
  75% {
    opacity: 1;
    transform: scale(1);
  }

  100% {
    opacity: 0;
    transform: scale(0.3);
  }
}

@keyframes ll-wave {
  0%,
  100% {
    opacity: 0.18;
  }

  45% {
    opacity: 1;
  }
}

@keyframes ll-dot {
  0%,
  100% {
    transform: scale(1);
    filter: drop-shadow(0 0 0 transparent);
  }

  50% {
    transform: scale(1.3);
    filter: drop-shadow(0 0 4px var(--ll-accent));
  }
}

/* ---- Block: mark + wordmark + progress line + caption --------------------- */
.ls-loader {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 0.6rem;
  min-height: 14rem;
  padding: 2rem 1rem;
  color: var(--ll-text);
  text-align: center;
}

.ls-loader-mark {
  position: relative;
  width: 5.5rem;
  height: 5.5rem;
}

.ls-loader-mark::before {
  content: "";
  position: absolute;
  inset: 12%;
  border-radius: 50%;
  background: var(--ll-glow);
  filter: blur(18px);
  animation: ll-glow 2.4s ease-in-out infinite;
}

.ls-loader-mark .ls-mark {
  position: relative;
}

.ls-loader-word {
  font-family: "Vazirmatn", "Segoe UI", system-ui, sans-serif;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1;
}

.ls-loader-word span {
  color: var(--ll-accent);
}

.ls-loader-track {
  position: relative;
  width: 7.5rem;
  height: 3px;
  overflow: hidden;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ll-frame) 14%, transparent);
}

.ls-loader-track span {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 40%;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, var(--ll-accent), transparent);
  animation: ll-track 1.4s ease-in-out infinite;
}

.ls-loader-text {
  margin: 0.2rem 0 0;
  color: var(--ll-muted);
  font-size: 0.85rem;
}

@keyframes ll-glow {
  0%,
  100% {
    opacity: 0.45;
    transform: scale(0.9);
  }

  50% {
    opacity: 1;
    transform: scale(1.1);
  }
}

@keyframes ll-track {
  from {
    transform: translateX(-110%);
  }

  to {
    transform: translateX(260%);
  }
}

/* Inline variant for small spaces (cards, buttons) */
.ls-loader.is-compact {
  min-height: 0;
  padding: 1rem;
}

.ls-loader.is-compact .ls-loader-mark {
  width: 3.4rem;
  height: 3.4rem;
}

.ls-loader.is-compact .ls-loader-word,
.ls-loader.is-compact .ls-loader-track {
  display: none;
}

/* ---- Full screen ---------------------------------------------------------- */
.ls-loader-screen {
  position: fixed;
  inset: 0;
  z-index: 2100;
  display: grid;
  place-items: center;
  padding: env(safe-area-inset-top, 0) 1rem env(safe-area-inset-bottom, 0);
  background: var(--ll-veil);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.22s ease, visibility 0s linear 0.22s;
}

.ls-loader-screen.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.22s ease, visibility 0s;
}

.ls-loader-screen .ls-loader {
  min-height: 0;
}

/* Opaque version for the very first paint, before anything else is on screen. */
.ls-loader-screen.is-solid {
  background:
    radial-gradient(ellipse 70% 45% at 50% 0%, color-mix(in srgb, var(--ll-accent) 16%, transparent), transparent 60%),
    var(--ll-veil);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

html[data-cp-theme="dark"] .ls-loader-screen.is-solid {
  background-color: #070f1a;
}

html[data-cp-theme="light"] .ls-loader-screen.is-solid {
  background-color: #f4f7fb;
}

@media (prefers-reduced-motion: reduce) {
  .ls-mark-frame,
  .ls-mark-line {
    stroke-dashoffset: 0;
    animation: none;
  }

  .ls-mark-bar,
  .ls-mark-nodes circle,
  .ls-mark-wave,
  .ls-mark-dot,
  .ls-loader-mark::before {
    animation: none;
  }

  .ls-loader-track span {
    animation: ll-fade 1.6s ease-in-out infinite;
    inset-inline: 0;
    width: auto;
  }
}

@keyframes ll-fade {
  50% {
    opacity: 0.35;
  }
}

/* ---- Portal boot screen (lsense-boot.js) ---------------------------------- */
.ls-boot.ls-loader-screen {
  align-content: center;
  gap: 0.75rem;
  font-family: "Vazirmatn", "Vazir", "Segoe UI", system-ui, -apple-system, sans-serif;
}

.ls-boot-fail {
  max-width: 26rem;
  margin: 0;
  color: #ef4444;
  font-size: 0.92rem;
}

html[data-cp-theme="dark"] .ls-boot-fail {
  color: #fca5a5;
}

.ls-boot-retry {
  justify-self: center;
  padding: 0.55rem 1.4rem;
  border: 1px solid color-mix(in srgb, var(--ll-accent) 45%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ll-accent) 12%, transparent);
  color: var(--ll-text);
  font: inherit;
  cursor: pointer;
}

/* Failed boot: the mark stops pumping so it does not look like it is still trying. */
.ls-boot.is-failed .ls-mark *,
.ls-boot.is-failed .ls-loader-track span,
.ls-boot.is-failed .ls-loader-mark::before {
  animation-play-state: paused;
}

.ls-boot.is-failed .ls-loader-text {
  display: none;
}

/* ---- Page loading state inside the portal --------------------------------- */
.cp-app.ls-page-loading {
  display: grid;
  place-items: center;
  min-height: 100dvh;
}

.cp-app.ls-page-loading .cp-app-inner {
  display: grid;
  justify-items: center;
}

/* ---- Reconnect dialog (App.razor) ----------------------------------------- */
.ls-reconnect {
  /* The dialog card is always dark. */
  --ll-frame: #dbe6f7;
  --ll-accent: #4a9bff;
  --ll-node: #101a28;
}

.ls-reconnect-mark {
  width: 4rem;
  height: 4rem;
}

#components-reconnect-modal.components-reconnect-failed .ls-reconnect-mark *,
#components-reconnect-modal.components-reconnect-paused .ls-reconnect-mark *,
#components-reconnect-modal.components-reconnect-rejected .ls-reconnect-mark * {
  animation-play-state: paused;
}

/* Admin: the veil takes the panel's own background (Vuexy light / dark). */
html[data-bs-theme] {
  --ll-veil: color-mix(in srgb, var(--bs-body-bg, #f8f7fa) 88%, transparent);
}
