/* ============================================================================
   OneQode Vault — brand motion
   The Gordian-knot symbol as (1) a self-drawing intro splash and (2) a looping
   loading mark. Theme-independent: reads the --ink/--bg/--head/--muted/--line
   tokens that BOTH app-classic.css and app-brand.css define, so it renders
   correctly under either live theme. Served as its own static stylesheet and
   linked directly (it must not depend on the cookie-driven /theme.css).
   ========================================================================== */

/* ---- shared keyframes ---------------------------------------------------- */
@keyframes oq-draw   { to   { stroke-dashoffset: 0; } }
@keyframes oq-fill   { from { fill-opacity: 0; } to { fill-opacity: 1; stroke-opacity: 0; } }
@keyframes oq-word   { from { opacity: 0; transform: translateY(9px); }
                       to   { opacity: 1; transform: translateY(0); } }
@keyframes oq-grow   { 0%   { transform: scale(.60); opacity: 0; }
                       24%  { opacity: 1; }
                       72%  { transform: scale(1.035); }
                       100% { transform: scale(1); } }
@keyframes oq-spin   { to   { transform: rotate(360deg); } }
/* draw the knot on, then keep pulling the dash through so it wipes back off —
   a continuous "drawing itself" trace rather than a plain rotate. */
@keyframes oq-trace  { 0%   { stroke-dashoffset: 1; }
                       48%  { stroke-dashoffset: 0; }
                       100% { stroke-dashoffset: -1; } }

/* ---- intro splash -------------------------------------------------------- */
/* Hidden by default; the head script adds .oq-splash-play to <html> BEFORE the
   body paints on the first load of a session, and .oq-splash-done to dismiss.
   A user who has already seen it this session gets neither play nor a flash. */
.oq-splash {
  position: fixed; inset: 0; z-index: 9999;
  display: none; flex-direction: column;
  align-items: center; justify-content: center; gap: 24px;
  background: var(--bg, #fff);
  transition: opacity .5s ease;
}
html.oq-splash-play          { overflow: hidden; }
html.oq-splash-play .oq-splash { display: flex; }
html.oq-splash-done .oq-splash { display: none !important; }
.oq-splash.oq-leaving        { opacity: 0; }

.oq-splash__knot {
  width: 104px; height: 104px; overflow: visible;
  transform: scale(.60); transform-origin: center;
  animation: oq-grow 1.7s cubic-bezier(.22,.68,.24,1) forwards;
}
.oq-splash__knot path {
  fill: var(--ink, #0B0B0C); fill-opacity: 0;
  stroke: var(--ink, #0B0B0C); stroke-width: .9;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1;      /* pathLength="1" normalises this */
  animation: oq-draw 1.5s cubic-bezier(.55,.08,.24,.98) forwards,
             oq-fill .7s ease 1.28s forwards;
}
.oq-splash__word {
  font-family: var(--head, sans-serif); font-weight: 600;
  font-size: 1.4rem; letter-spacing: .34em; text-indent: .34em; /* balance tracking */
  text-transform: uppercase; color: var(--ink, #0B0B0C);
  opacity: 0; animation: oq-word .7s ease 1.5s forwards;
}

/* ---- reusable loading mark ---------------------------------------------- */
.oq-loader { display: inline-flex; align-items: center; justify-content: center; }
.oq-loader svg { width: 34px; height: 34px; overflow: visible; animation: oq-spin 2s linear infinite; }
.oq-loader svg path {
  fill: none; stroke: var(--ink, #0B0B0C); stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: oq-trace 1.7s ease-in-out infinite;
}
/* block variant — centred with a label, for in-page content that's loading */
.oq-loader--block { flex-direction: column; gap: 14px; padding: 56px 0; }
.oq-loader--block svg { width: 46px; height: 46px; }
.oq-loader__label {
  font-family: var(--head, sans-serif); font-size: .72rem; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: var(--muted, #6E6E73);
}

/* ---- global navigation loader (server round-trips) ----------------------- */
/* A small knot mark that fades in bottom-right while the next page is fetched.
   Server-rendered on every shell; toggled by .oq-navloading on <html>. */
.oq-nav {
  position: fixed; z-index: 9998; right: 22px; bottom: 20px;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 15px 8px 11px;
  background: var(--bg, #fff); border: 1px solid var(--line, #E4E4E7);
  border-radius: 999px; box-shadow: 0 6px 22px rgba(0,0,0,.10);
  opacity: 0; transform: translateY(6px); pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
}
html.oq-navloading .oq-nav { opacity: 1; transform: translateY(0); }
.oq-nav svg { width: 22px; height: 22px; overflow: visible; animation: oq-spin 2s linear infinite; }
.oq-nav svg path {
  fill: none; stroke: var(--ink, #0B0B0C); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: oq-trace 1.7s ease-in-out infinite;
}
.oq-nav__label {
  font-family: var(--head, sans-serif); font-size: .7rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted, #6E6E73);
}

/* ---- reduced motion: keep the marks, drop the movement ------------------- */
@media (prefers-reduced-motion: reduce) {
  .oq-splash__knot { animation: none; transform: scale(1); }
  .oq-splash__knot path { animation: none; fill-opacity: 1; stroke-opacity: 0; stroke-dashoffset: 0; }
  .oq-splash__word { animation: none; opacity: 1; }
  .oq-loader svg, .oq-nav svg { animation: none; }
  .oq-loader svg path, .oq-nav svg path { animation: oq-trace 2.4s ease-in-out infinite; }
}
