/* SPDX-FileCopyrightText: 2026 Jorge Pérez Burgueño and Nodus contributors
 * SPDX-License-Identifier: AGPL-3.0-only
 *
 * The Nodi components, as the homepage hero figure uses them. Generated by
 * scripts/build-what-nodi.mjs (npm run site:what-nodi): the two stylesheets below
 * are verbatim copies of src/components/nodi/nodiOrb.css and nodi.css, so the
 * figure on the site and the mascot in the app stay one thing. Do not edit by hand.
 *
 * Loaded only by the homepage. The demo pages load the ported orb inside nodi.js,
 * and a page must never load both. */
/* Nodi "orb" — the alternative, soberer mascot: a glass sphere holding a galaxy.
 *
 * Two rules run through the whole file:
 *
 *  • ONE HUE. Every cool colour is `hsl(calc(var(--nodi-hue) + Xdeg) …)`, where the
 *    offsets are relative to Nodi's own blue (hue 210). Recolouring the orb to a vault
 *    is a single custom property. The golds stay literal — they're the brand constant.
 *  • ADDITIVE LIGHT. Glows are composited with `mix-blend-mode: screen`, the way light
 *    actually adds up, which is what keeps the orb from reading as flat vector art.
 *    `isolation: isolate` on the root keeps that blending inside the SVG so the orb
 *    never screens against the app behind it.
 *
 * Class names are scoped under `.nodi-orb` and keyframes are prefixed `nodiorb-`, so
 * this file can never collide with the classic mascot's nodi.css.
 */

.nodi-orb {
  --nodi-hue: 210deg;
  /* Per-state multiplier on every orbital/rotation duration. */
  --spd: 1;
  height: 200px;
  width: auto;
  overflow: visible;
  display: block;
  -webkit-user-select: none;
  user-select: none;
  isolation: isolate;
  transition: filter .8s ease;
}
.nodi-orb.nodi-draggable { cursor: grab; touch-action: none; }
.nodi-orb.nodi-draggable.dragging { cursor: grabbing; }

.nodi-orb .add { mix-blend-mode: screen; }

/* ── themed gradient stops (stop-color is CSS-settable, so the gradients recolour
      with the hue exactly like the plain elements do) ─────────────────────────── */
.nodi-orb .st-deep1 { stop-color: hsl(calc(var(--nodi-hue) + 12deg) 58% 25%); }
.nodi-orb .st-deep2 { stop-color: hsl(calc(var(--nodi-hue) + 16deg) 63% 17%); }
.nodi-orb .st-deep3 { stop-color: hsl(calc(var(--nodi-hue) + 18deg) 67% 12%); }
.nodi-orb .st-deep4 { stop-color: hsl(calc(var(--nodi-hue) + 19deg) 69% 9%); }
.nodi-orb .st-core1 { stop-color: hsl(calc(var(--nodi-hue) - 6deg) 100% 96%); }
.nodi-orb .st-core2 { stop-color: hsl(calc(var(--nodi-hue) - 6deg) 100% 81%); }
.nodi-orb .st-core3 { stop-color: hsl(var(--nodi-hue) 74% 61%); }
.nodi-orb .st-halo1 { stop-color: hsl(calc(var(--nodi-hue) + 7deg) 72% 56%); }
.nodi-orb .st-halo2 { stop-color: hsl(calc(var(--nodi-hue) + 10deg) 64% 47%); }
.nodi-orb .st-bot1  { stop-color: hsl(calc(var(--nodi-hue) - 20deg) 86% 59%); }
.nodi-orb .st-bot2  { stop-color: hsl(calc(var(--nodi-hue) - 12deg) 66% 49%); }
.nodi-orb .st-rim2  { stop-color: hsl(calc(var(--nodi-hue) + 3deg) 100% 81%); }
.nodi-orb .st-rim3  { stop-color: hsl(calc(var(--nodi-hue) - 18deg) 88% 67%); }
.nodi-orb .st-satc1 { stop-color: hsl(calc(var(--nodi-hue) - 16deg) 100% 92%); }
.nodi-orb .st-satc2 { stop-color: hsl(calc(var(--nodi-hue) - 16deg) 79% 64%); }
.nodi-orb .st-satv1 { stop-color: hsl(calc(var(--nodi-hue) + 48deg) 100% 92%); }
.nodi-orb .st-satv2 { stop-color: hsl(calc(var(--nodi-hue) + 48deg) 89% 76%); }
.nodi-orb .st-ringc1 { stop-color: hsl(calc(var(--nodi-hue) - 17deg) 92% 80%); }
.nodi-orb .st-ringc2 { stop-color: hsl(calc(var(--nodi-hue) - 14deg) 56% 55%); }
.nodi-orb .st-ringc3 { stop-color: hsl(calc(var(--nodi-hue) - 12deg) 52% 36%); }
.nodi-orb .st-load1 { stop-color: hsl(calc(var(--nodi-hue) - 18deg) 89% 70%); }
.nodi-orb .st-load2 { stop-color: hsl(calc(var(--nodi-hue) - 18deg) 100% 96%); }
.nodi-orb .st-ped1  { stop-color: hsl(calc(var(--nodi-hue) - 17deg) 81% 57%); }
.nodi-orb .st-ped2  { stop-color: hsl(calc(var(--nodi-hue) - 10deg) 66% 46%); }

/* ── themed elements ───────────────────────────────────────────────────────────── */
.nodi-orb .neb-arm1  { stroke: hsl(calc(var(--nodi-hue) + 7deg) 72% 56%); }
.nodi-orb .neb-arm1b { stroke: hsl(calc(var(--nodi-hue) - 21deg) 73% 53%); }
.nodi-orb .neb-arm2  { stroke: hsl(calc(var(--nodi-hue) + 48deg) 75% 65%); }
.nodi-orb .neb-cloud { fill:   hsl(calc(var(--nodi-hue) + 12deg) 63% 44%); }
.nodi-orb .mln       { stroke: hsl(calc(var(--nodi-hue) - 2deg) 100% 81%); }
.nodi-orb .n-c       { fill:   hsl(calc(var(--nodi-hue) - 16deg) 88% 71%); }
.nodi-orb .n-v       { fill:   hsl(calc(var(--nodi-hue) + 48deg) 90% 76%); }
.nodi-orb .n-g       { fill:   #ffe9a8; }
.nodi-orb .flare-el  { fill:   hsl(calc(var(--nodi-hue) - 6deg) 100% 94%); }
.nodi-orb .core-mid  { fill:   hsl(calc(var(--nodi-hue) - 6deg) 100% 87%); }
.nodi-orb .rim-glow-in  { stroke: hsl(calc(var(--nodi-hue) - 4deg) 100% 77% / .28); }
.nodi-orb .rim-glow-out { stroke: hsl(calc(var(--nodi-hue) - 2deg) 100% 74% / .3); }
.nodi-orb .rim-bounce   { fill:   hsl(calc(var(--nodi-hue) - 8deg) 100% 81% / .28); }
.nodi-orb .rim-base-arc { stroke: hsl(calc(var(--nodi-hue) - 18deg) 89% 70% / .5); }
.nodi-orb .ped-ln1 { stroke: hsl(calc(var(--nodi-hue) - 18deg) 89% 70% / .35); }
.nodi-orb .ped-ln2 { stroke: hsl(calc(var(--nodi-hue) - 14deg) 100% 83% / .3); }
.nodi-orb .think-ring { stroke: hsl(calc(var(--nodi-hue) + 3deg) 100% 89% / .45); }
.nodi-orb .load-track { stroke: hsl(calc(var(--nodi-hue) - 18deg) 89% 70% / .13); }
.nodi-orb .load-arc-glow { stroke: hsl(calc(var(--nodi-hue) - 18deg) 89% 70% / .5); }
.nodi-orb .link-base  { stroke: hsl(calc(var(--nodi-hue) - 18deg) 89% 70% / .18); }
.nodi-orb .link-pulse { stroke: hsl(calc(var(--nodi-hue) - 14deg) 91% 87%); }
.nodi-orb .link-node  { fill:   hsl(calc(var(--nodi-hue) - 16deg) 100% 92%); }
.nodi-orb .rgB { stroke: hsl(calc(var(--nodi-hue) - 16deg) 80% 66% / .3); }

/* celebration confetti: colour + its own glow, via currentColor */
.nodi-orb .pc0 { fill: #ffe9a8; color: #ffe9a8; }
.nodi-orb .pc1 { fill: hsl(calc(var(--nodi-hue) - 16deg) 88% 71%); color: hsl(calc(var(--nodi-hue) - 16deg) 88% 71%); }
.nodi-orb .pc2 { fill: hsl(calc(var(--nodi-hue) + 48deg) 90% 76%); color: hsl(calc(var(--nodi-hue) + 48deg) 90% 76%); }
.nodi-orb .pc3 { fill: #dff1ff; color: #dff1ff; }
.nodi-orb .pc4 { fill: #e8c66a; color: #e8c66a; }
.nodi-orb .pc5 { fill: hsl(calc(var(--nodi-hue) - 40deg) 80% 70%); color: hsl(calc(var(--nodi-hue) - 40deg) 80% 70%); }
.nodi-orb .party { filter: drop-shadow(0 0 4px currentColor); }

/* ── base motion ───────────────────────────────────────────────────────────────── */
.nodi-orb .float {
  animation: nodiorb-float 7s ease-in-out infinite;
  transform-box: view-box; transform-origin: 160px 160px;
}
@keyframes nodiorb-float {
  0%,100% { transform: translateY(0); }
  50%     { transform: translateY(-7px); }
}

/* Pedestal: a restrained light pool, without a contact shadow below Nodi. */
.nodi-orb .ped-glow   { transition: opacity .5s ease; }
.light .nodi-orb .ped-glow   { opacity: .25; }
.nodi-orb .ped-pulse { transform-box: view-box; transform-origin: 160px 298px; animation: nodiorb-ped 4.6s ease-in-out infinite; }
@keyframes nodiorb-ped {
  0%,100% { opacity: .5; transform: scaleX(1); }
  50%     { opacity: .95; transform: scaleX(1.06); }
}

.nodi-orb .halo { animation: nodiorb-halo 7s ease-in-out infinite; transform-box: view-box; transform-origin: 160px 160px; }
@keyframes nodiorb-halo {
  0%,100% { opacity: .75; transform: scale(1); }
  50%     { opacity: 1;   transform: scale(1.04); }
}

.nodi-orb .ring { fill: none; transition: opacity .5s ease, stroke .5s ease, stroke-width .5s ease; }
/* Light theme: additive glow all but vanishes on white, so the rings get their body
   back from a darker, thicker line and a normally-blended glow. */
.light .nodi-orb .ring-glow { mix-blend-mode: normal; opacity: .55; }
.light .nodi-orb .ring-gold-line { stroke: rgba(158,113,28,.85); stroke-width: 1.5; }
.light .nodi-orb .ring-cyan-line { stroke: hsl(calc(var(--nodi-hue) - 14deg) 55% 40% / .8); stroke-width: 1.3; }
.light .nodi-orb .ring-dim-line  { stroke: rgba(158,124,52,.6); stroke-width: 1.1; opacity: 1; }

.nodi-orb .sat {
  offset-rotate: 0deg;
  animation:
    nodiorb-orbit calc(var(--dur) * var(--spd)) linear infinite,
    nodiorb-depth calc(var(--dur) * var(--spd)) linear infinite;
  animation-delay: var(--delay, 0s), var(--delay, 0s);
}
@keyframes nodiorb-orbit { from { offset-distance: 0%; } to { offset-distance: 100%; } }
/* First half of the path is the near face, second half the far one. */
@keyframes nodiorb-depth {
  0%   { opacity: .95; }
  25%  { opacity: 1;   }
  50%  { opacity: .55; }
  75%  { opacity: .35; }
  100% { opacity: .95; }
}

.nodi-orb .neb-spin  { animation: nodiorb-rot calc(46s * var(--spd)) linear infinite; transform-box: view-box; transform-origin: 160px 160px; }
.nodi-orb .neb-spin2 { animation: nodiorb-rot calc(64s * var(--spd)) linear infinite reverse; transform-box: view-box; transform-origin: 160px 160px; }
.nodi-orb .mesh      { animation: nodiorb-rot calc(75s * var(--spd)) linear infinite reverse; transform-box: view-box; transform-origin: 160px 160px; }
@keyframes nodiorb-rot { to { transform: rotate(360deg); } }

.nodi-orb .tw { animation: nodiorb-tw 3.8s ease-in-out infinite; }
@keyframes nodiorb-tw { 0%,100% { opacity: .3; } 50% { opacity: 1; } }
.nodi-orb .star-tw { animation: nodiorb-startw 4.5s ease-in-out infinite; }
@keyframes nodiorb-startw { 0%,100% { opacity: .25; } 50% { opacity: .9; } }
.nodi-orb .accent { transform-box: fill-box; transform-origin: center; animation: nodiorb-accent 3.2s ease-in-out infinite; }
@keyframes nodiorb-accent {
  0%,100% { transform: scale(1);   opacity: .75; }
  50%     { transform: scale(1.3); opacity: 1;   }
}
.nodi-orb .dust { animation: nodiorb-dust 5s ease-in-out infinite; }
@keyframes nodiorb-dust { 0%,100% { opacity: .1; } 50% { opacity: .8; } }

.nodi-orb .core { transform-box: view-box; transform-origin: 160px 160px; animation: nodiorb-core 5s ease-in-out infinite; }
@keyframes nodiorb-core {
  0%,100% { transform: scale(1);   opacity: .92; }
  50%     { transform: scale(1.1); opacity: 1;   }
}
.nodi-orb .flare { transform-box: view-box; transform-origin: 160px 160px; animation: nodiorb-flare 5s ease-in-out infinite; }
@keyframes nodiorb-flare {
  0%,100% { opacity: .55; transform: scale(.94); }
  50%     { opacity: .95; transform: scale(1.06); }
}

.nodi-orb.nodi-draggable:hover .halo { opacity: 1; }
.nodi-orb.dragging .float { animation: none; }

/* ── state layers ──────────────────────────────────────────────────────────────── */
.nodi-orb .fx { opacity: 0; visibility: hidden; transition: opacity .35s ease, visibility 0s linear .35s; }
.nodi-orb[data-state="loading"]     .fx-loading,
.nodi-orb[data-state="thinking"]    .fx-thinking,
.nodi-orb[data-state="connecting"]  .fx-connecting,
.nodi-orb[data-state="discovering"] .fx-discovering,
.nodi-orb[data-state="celebrating"] .fx-celebrating,
.nodi-orb[data-state="sleeping"]    .fx-sleeping,
.nodi-orb.arm-up                    .fx-notify {
  opacity: 1; visibility: visible; transition-delay: 0s;
}

/* thinking */
.nodi-orb[data-state="thinking"] { --spd: .6; }
.nodi-orb[data-state="thinking"] .core  { animation-duration: 1.6s; }
.nodi-orb[data-state="thinking"] .flare { animation-duration: 1.6s; }
.nodi-orb[data-state="thinking"] .tw    { animation-duration: 1.2s; }
.nodi-orb .think-ring { fill: none; stroke-width: 1; stroke-dasharray: 3 10; stroke-linecap: round; }
.nodi-orb .fx-thinking { transform-box: view-box; transform-origin: 160px 160px; }
.nodi-orb[data-state="thinking"] .fx-thinking { animation: nodiorb-think 6s linear infinite; }
@keyframes nodiorb-think { to { transform: rotate(360deg); } }

/* loading */
.nodi-orb[data-state="loading"] { --spd: .5; }
.nodi-orb .load-group { transform-box: view-box; transform-origin: 160px 160px; }
.nodi-orb[data-state="loading"] .load-group { animation: nodiorb-sweep 1.35s linear infinite; }
@keyframes nodiorb-sweep { to { transform: rotate(360deg); } }
.nodi-orb .load-track { fill: none; stroke-width: 4; }
.nodi-orb .load-arc { fill: none; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 168 452; }
.nodi-orb .load-arc-glow { fill: none; stroke-width: 9; stroke-linecap: round; stroke-dasharray: 168 452; }
.nodi-orb .load-head { fill: #fff; }

/* notification (the orb's answer to the classic Nodi's raised arm) */
.nodi-orb .noti-star { transform-box: fill-box; transform-origin: center; fill: #ffe9a8; }
.nodi-orb .noti-halo { transform-box: fill-box; transform-origin: center; }
.nodi-orb.arm-up .noti-star,
.nodi-orb.arm-up .noti-halo { animation: nodiorb-noti .95s ease-in-out infinite; }
@keyframes nodiorb-noti {
  0%,100% { transform: scale(.85); opacity: .85; }
  50%     { transform: scale(1.18); opacity: 1; }
}
.nodi-orb .noti-ripple { fill: none; stroke: rgba(255,225,140,.75); stroke-width: 1.3; transform-box: fill-box; transform-origin: center; }
.nodi-orb.arm-up .noti-ripple { animation: nodiorb-ripple 1.9s ease-out infinite; }
@keyframes nodiorb-ripple {
  0%   { transform: scale(.3); opacity: .9; }
  70%  { transform: scale(1.7); opacity: 0; }
  100% { transform: scale(1.7); opacity: 0; }
}
.nodi-orb.arm-up .core { animation-duration: 1s; }

/* connecting */
.nodi-orb .link-base { fill: none; stroke-width: 1.1; stroke-linecap: round; }
.nodi-orb .link-pulse { fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-dasharray: 14 240; }
.nodi-orb[data-state="connecting"] .link-pulse    { animation: nodiorb-travel 1.5s linear infinite; }
.nodi-orb[data-state="connecting"] .link-pulse.p2 { animation-delay: .5s; }
.nodi-orb[data-state="connecting"] .link-pulse.p3 { animation-delay: .9s; }
@keyframes nodiorb-travel { from { stroke-dashoffset: 254; } to { stroke-dashoffset: 0; } }
.nodi-orb .link-node { transform-box: fill-box; transform-origin: center; }
.nodi-orb[data-state="connecting"] .link-node { animation: nodiorb-accent 1.5s ease-in-out infinite; }

/* discovering */
.nodi-orb .spk { transform-box: fill-box; transform-origin: center; fill: #ffe9a8; opacity: 0; }
.nodi-orb[data-state="discovering"] .spk    { animation: nodiorb-spark 2.2s ease-in-out infinite; }
.nodi-orb[data-state="discovering"] .spk.s2 { animation-delay: .55s; }
.nodi-orb[data-state="discovering"] .spk.s3 { animation-delay: 1.1s; }
.nodi-orb[data-state="discovering"] .spk.s4 { animation-delay: 1.65s; }
@keyframes nodiorb-spark {
  0%, 100% { opacity: 0; transform: scale(.2) rotate(0deg); }
  12%      { opacity: 1; transform: scale(1.15) rotate(18deg); }
  30%      { opacity: .9; transform: scale(.9) rotate(28deg); }
  48%      { opacity: 0; transform: scale(.3) rotate(40deg); }
}
.nodi-orb[data-state="discovering"] { --spd: .8; }
.nodi-orb[data-state="discovering"] .tw { animation-duration: 1.6s; }

/* waving */
.nodi-orb[data-state="waving"] .float { animation: nodiorb-rock 2.1s ease-in-out infinite; }
@keyframes nodiorb-rock {
  0%,100% { transform: translateY(0) rotate(-4.5deg); }
  50%     { transform: translateY(-6px) rotate(4.5deg); }
}
.nodi-orb .shimmer { opacity: 0; }
.nodi-orb[data-state="waving"] .shimmer { opacity: 1; animation: nodiorb-shimmer 2.1s ease-in-out infinite; }
@keyframes nodiorb-shimmer {
  0%   { transform: translateX(-135px) skewX(-18deg); }
  60%, 100% { transform: translateX(215px) skewX(-18deg); }
}

/* celebrating */
.nodi-orb[data-state="celebrating"] { --spd: .38; }
.nodi-orb .party { transform-box: fill-box; transform-origin: center; opacity: 0; }
.nodi-orb[data-state="celebrating"] .party {
  animation: nodiorb-burst 1.7s cubic-bezier(.15,.6,.4,1) infinite;
  animation-delay: var(--pd, 0s);
}
@keyframes nodiorb-burst {
  0%   { opacity: 0; transform: translate(0,0) scale(.3) rotate(0deg); }
  10%  { opacity: 1; }
  70%  { opacity: .9; }
  100% { opacity: 0; transform: translate(var(--px), var(--py)) scale(1) rotate(90deg); }
}
.nodi-orb[data-state="celebrating"] .core { animation: nodiorb-coreparty .85s ease-in-out infinite; }
@keyframes nodiorb-coreparty {
  0%,100% { transform: scale(1);   opacity: .95; }
  50%     { transform: scale(1.2); opacity: 1;   }
}
.nodi-orb[data-state="celebrating"] .ring-gold-line { stroke: rgba(255,228,150,1); }
.nodi-orb[data-state="celebrating"] .ring-cyan-line { stroke: hsl(calc(var(--nodi-hue) - 16deg) 85% 74% / .8); }

/* sleeping */
.nodi-orb[data-state="sleeping"] { --spd: 3.4; filter: brightness(.62) saturate(.8); }
.nodi-orb[data-state="sleeping"] .core  { animation: nodiorb-breathe 5.5s ease-in-out infinite; }
.nodi-orb[data-state="sleeping"] .flare { animation: none; opacity: .3; }
@keyframes nodiorb-breathe {
  0%,100% { transform: scale(.94); opacity: .6; }
  50%     { transform: scale(1.02); opacity: .85; }
}
.nodi-orb[data-state="sleeping"] .ped-glow { opacity: .35; }
.nodi-orb .moon { fill: rgba(232,198,106,.85); transform-box: fill-box; transform-origin: center; }
.nodi-orb[data-state="sleeping"] .moon { animation: nodiorb-moon 5.5s ease-in-out infinite; }
@keyframes nodiorb-moon {
  0%,100% { opacity: .4; transform: translateY(0); }
  50%     { opacity: .85; transform: translateY(-3px); }
}

/* closing — the right-click goodbye: a flash, then the orb collapses to a point */
.nodi-orb[data-state="closing"] { cursor: default; pointer-events: none; }
.nodi-orb[data-state="closing"] .float { animation: nodiorb-close 1.6s cubic-bezier(.3,.7,.3,1) both; }
@keyframes nodiorb-close {
  0%   { transform: scale(1); opacity: 1; }
  38%  { transform: scale(1.07); opacity: 1; }
  100% { transform: scale(.02); opacity: 0; }
}
.nodi-orb .close-flash {
  fill: none; stroke: rgba(200,230,255,.9); stroke-width: 2;
  transform-box: view-box; transform-origin: 160px 160px; opacity: 0;
}
.nodi-orb[data-state="closing"] .close-flash    { animation: nodiorb-closering 1.1s ease-out .3s both; }
.nodi-orb[data-state="closing"] .close-flash.c2 { animation-delay: .45s; stroke: rgba(232,198,106,.8); }
@keyframes nodiorb-closering {
  0%   { transform: scale(.6); opacity: 0; }
  20%  { opacity: .95; }
  100% { transform: scale(1.9); opacity: 0; }
}

/* ── at rest ───────────────────────────────────────────────────────────────────────
 * Nodi holds its pose when nothing is happening (see NodiAvatar's useAtRest).
 *
 * `animation-play-state: paused` and NOT `animation: none`: every keyframe above
 * stays exactly as authored, the orb freezes wherever in its cycle it happened to
 * be, and resuming picks up from there instead of snapping back to 0%. Nothing is
 * removed — flip the class off and the whole thing runs again.
 *
 * Why it is worth doing: an SVG subtree has no compositor layer of its own, so any
 * one animating property repaints the entire orb — turbulence clouds, gaussian
 * glows, blend modes and all — every frame. Measured idle on this corpus, the orb
 * cost ~50% CPU with all its animations and still ~23% with only one left running.
 * Zero is the only cheap number, which is why this is a switch rather than a diet.
 */
.nodi-orb.nodi-at-rest,
.nodi-orb.nodi-at-rest * { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
  .nodi-orb, .nodi-orb * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

.nodi-svg {
  height: 200px;
  width: auto;
  overflow: visible;
  display: block;
  -webkit-user-select: none;
  user-select: none;
}
.nodi-svg.nodi-draggable { cursor: grab; touch-action: none; }
.nodi-svg.nodi-draggable.dragging { cursor: grabbing; }

.nodi-svg .thread { fill: none; stroke: #16294a; stroke-width: 4.5; stroke-linecap: round; }
.nodi-svg .hoverwrap { transform-box: view-box; transform-origin: 130px 142px; transition: transform .3s ease; }
.nodi-svg .deco,
.nodi-svg .role,
.nodi-svg .closing-smoke,
.nodi-svg .eyes-happy,
.nodi-svg .eyes-sleep,
.nodi-svg .eyes-surprised,
.nodi-svg .mouth-open,
.nodi-svg .mouth-surprised { display: none; }
.nodi-svg .sweatdrop { transform-box: fill-box; transform-origin: center; animation: nodi-sweat 1.1s ease-in-out infinite; }

.nodi-svg .nodi-core { animation: nodi-floaty 5s ease-in-out infinite; transform-box: view-box; transform-origin: 130px 152px; }
.nodi-svg .halo { animation: nodi-halo 5s ease-in-out infinite; transform-box: view-box; transform-origin: 130px 140px; }
.nodi-svg .eyes-open { animation: nodi-blink 5.4s ease-in-out infinite; transform-box: view-box; transform-origin: 130px 139px; }
.nodi-svg .limbs { opacity: 1; transform-box: view-box; transform-origin: 130px 140px; transition: opacity .3s ease, transform .48s cubic-bezier(.2,.8,.3,1); }
.nodi-svg .arm-l .hand { transform: translate(64px, 214px); }
.nodi-svg .arm-r .hand { transform: translate(196px, 214px); }
.nodi-svg .leg-l .hand { transform: translate(96px, 266px); }
.nodi-svg .leg-r .hand { transform: translate(170px, 276px); }
.nodi-svg .arm-r { animation: nodi-swayR 4.4s ease-in-out infinite; transform-box: view-box; transform-origin: 168px 150px; }
/* Right arm raised (e.g. an unread notification): held up with a gentle attention wave. */
.nodi-svg.arm-up .arm-r { animation: nodi-raisewave 1.6s ease-in-out infinite; transform-origin: 168px 150px; }
.nodi-svg.arm-up .arm-r .thread { d: path("M168 150 C 190 120 206 90 214 68"); }
.nodi-svg.arm-up .arm-r .hand { transform: translate(216px, 66px); }
.nodi-svg .arm-l { animation: nodi-swayL 5s ease-in-out infinite; transform-box: view-box; transform-origin: 94px 150px; }
.nodi-svg .leg-l { animation: nodi-legA 4.6s ease-in-out infinite; transform-box: view-box; transform-origin: 114px 190px; }
.nodi-svg .leg-r { animation: nodi-legB 4.9s ease-in-out infinite; transform-box: view-box; transform-origin: 150px 192px; }
.nodi-svg .mspark { animation: nodi-twinkle 2.4s ease-in-out infinite; }
.nodi-svg .thinkdot { animation: nodi-thinkdot 1.6s ease-in-out infinite; }
.nodi-svg .thinking-rotor {
  opacity: 0;
  visibility: hidden;
  filter: blur(.8px);
  animation: nodi-centrifuge 1.28s linear infinite;
  animation-play-state: paused;
  transform-box: view-box;
  transform-origin: 130px 140px;
  transition: opacity .3s ease, filter .42s ease, visibility 0s linear .42s;
}
.nodi-svg .thinking-ring {
  fill: none;
  stroke: #d4af37;
  stroke-width: 1.2;
  stroke-dasharray: 2 10;
  opacity: .32;
}
.nodi-svg .thinking-trail {
  fill: none;
  stroke: #e4c368;
  stroke-width: 2.2;
  stroke-linecap: round;
  opacity: .5;
  animation: nodi-thinking-trail 1.1s ease-in-out infinite;
}
.nodi-svg .thinking-limb .thread { stroke-width: 4; }
.nodi-svg .thinking-arm-l .hand { transform: translate(72px, 86px); }
.nodi-svg .thinking-arm-r .hand { transform: translate(190px, 86px); }
.nodi-svg .thinking-leg-r .hand { transform: translate(190px, 194px); }
.nodi-svg .thinking-leg-l .hand { transform: translate(70px, 194px); }
.nodi-svg .lline { stroke: #c9a24a; stroke-width: 1.4; fill: none; stroke-dasharray: 4 4; opacity: .6; animation: nodi-dash 1s linear infinite; }
.nodi-svg .lnode { animation: nodi-nodein 1.8s ease-in-out infinite; }
.nodi-svg .cline { fill: none; stroke: #16294a; stroke-width: 1.6; opacity: .6; stroke-dasharray: 5 5; animation: nodi-dash 1.1s linear infinite; }
.nodi-svg .spark { animation: nodi-pop .55s cubic-bezier(.2,1.5,.4,1) both; transform-box: fill-box; transform-origin: center; }
.nodi-svg .twinkle { animation: nodi-twinkle 1.5s ease-in-out infinite; }
.nodi-svg .waveline { opacity: 0; animation: nodi-waveline 1.6s ease-in-out infinite; }
.nodi-svg .zzz { fill: none; stroke: #1a2c4d; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; animation: nodi-zrise 3s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }

.nodi-svg.nodi-draggable:hover .hoverwrap { transform: scale(1.045); }
.nodi-svg.nodi-draggable:hover .halo { opacity: .92; }
.nodi-svg.dragging .hoverwrap { transform: scaleY(1.06) scaleX(.96); }
.nodi-svg.dragging .arm-r { animation: none; transform: rotate(-26deg); }
.nodi-svg.dragging .arm-l { animation: none; transform: rotate(24deg); }
.nodi-svg.dragging .leg-l,
.nodi-svg.dragging .leg-r { animation: nodi-dangle .6s ease-in-out infinite; }
/* Surprised, sweating face while being dragged */
.nodi-svg.dragging .eyes-open,
.nodi-svg.dragging .mouth-smile { display: none; }
.nodi-svg.dragging .eyes-surprised,
.nodi-svg.dragging .mouth-surprised,
.nodi-svg.dragging .deco-sweat { display: inline; }

.nodi-svg[data-state="discovering"] .eyes-open,
.nodi-svg[data-state="discovering"] .mouth-smile { display: none; }
.nodi-svg[data-state="discovering"] .eyes-happy,
.nodi-svg[data-state="discovering"] .mouth-open { display: inline; }
.nodi-svg[data-state="discovering"] .halo { animation: nodi-haloBright 1.4s ease-in-out infinite; }
.nodi-svg[data-state="discovering"] .nodi-core { animation: nodi-hop 1.6s ease-in-out infinite; }
.nodi-svg[data-state="discovering"] .deco-discover { display: inline; }
.nodi-svg[data-state="discovering"] .arm-r { animation: none; }
.nodi-svg[data-state="discovering"] .arm-r .thread { d: path("M172 116 C 196 122 212 138 228 152"); }
.nodi-svg[data-state="discovering"] .arm-r .hand { transform: translate(228px, 152px); }

.nodi-svg[data-state="thinking"] .deco-think { display: inline; }
.nodi-svg[data-state="thinking"] .eyes-open { display: none; }
.nodi-svg[data-state="thinking"] .eyes-sleep { display: inline; animation: nodi-thinking-eyes 1.28s ease-in-out infinite; transform-box: view-box; transform-origin: 130px 140px; }
.nodi-svg[data-state="thinking"] .limbs { opacity: 0; transform: scale(.7) rotate(-10deg); }
.nodi-svg[data-state="thinking"] .thinking-rotor {
  opacity: 1;
  visibility: visible;
  filter: blur(0);
  animation-play-state: running;
  transition-delay: 0s;
}
.nodi-svg[data-state="thinking"] .halo { animation: nodi-haloBright 1.28s ease-in-out infinite; }
.nodi-svg[data-state="thinking"] .mesh { animation: nodi-thinking-core 2.56s linear infinite; transform-box: view-box; transform-origin: 130px 140px; }

.nodi-svg[data-state="connecting"] .deco-connect { display: inline; }

.nodi-svg[data-state="waving"] .deco-wave { display: inline; }
.nodi-svg[data-state="waving"] .nodi-core { animation: nodi-leanfloat 5s ease-in-out infinite; }
.nodi-svg[data-state="waving"] .arm-r { animation: nodi-wave .78s ease-in-out infinite; transform-origin: 168px 150px; }
.nodi-svg[data-state="waving"] .arm-r .thread { d: path("M168 150 C 190 120 206 90 214 68"); }
.nodi-svg[data-state="waving"] .arm-r .hand { transform: translate(216px, 66px); }

.nodi-svg[data-state="celebrating"] .eyes-open,
.nodi-svg[data-state="celebrating"] .mouth-smile { display: none; }
.nodi-svg[data-state="celebrating"] .eyes-happy,
.nodi-svg[data-state="celebrating"] .mouth-open { display: inline; }
.nodi-svg[data-state="celebrating"] .nodi-core { animation: nodi-celebration-jump .72s cubic-bezier(.2,.8,.3,1) infinite; }
.nodi-svg[data-state="celebrating"] .arm-l .thread { d: path("M94 151 C 76 122 62 92 54 66"); }
.nodi-svg[data-state="celebrating"] .arm-l .hand { transform: translate(53px, 64px); }
.nodi-svg[data-state="celebrating"] .arm-r .thread { d: path("M166 151 C 184 122 198 92 206 66"); }
.nodi-svg[data-state="celebrating"] .arm-r .hand { transform: translate(207px, 64px); }

@keyframes nodi-celebration-jump {
  0%, 100% { transform: translateY(4px) rotate(-2deg); }
  45% { transform: translateY(-24px) rotate(2deg); }
  62% { transform: translateY(-20px) rotate(0deg); }
}

.nodi-svg[data-state="loading"] .limbs { animation: nodi-spin 1.9s cubic-bezier(.6,.15,.4,.85) infinite; transform-box: view-box; transform-origin: 130px 140px; }
.nodi-svg[data-state="loading"] .limb { animation: none; }
.nodi-svg[data-state="loading"] .halo { animation: nodi-halo 1.4s ease-in-out infinite; }

.nodi-svg[data-state="sleeping"] .eyes-open { display: none; }
.nodi-svg[data-state="sleeping"] .eyes-sleep { display: inline; }
.nodi-svg[data-state="sleeping"] .deco-sleep { display: inline; }
.nodi-svg[data-state="sleeping"] .nodi-core { animation: nodi-breathe 4.6s ease-in-out infinite; }
.nodi-svg[data-state="sleeping"] .halo { opacity: .42; animation: none; }
.nodi-svg[data-state="sleeping"] .arm-r,
.nodi-svg[data-state="sleeping"] .arm-l,
.nodi-svg[data-state="sleeping"] .leg-l,
.nodi-svg[data-state="sleeping"] .leg-r { animation: none; }

/* Right-click goodbye: retract each limb, puff away the active accessory,
 * remove the face, then dissolve the whole node in a larger cloud. */
.nodi-svg[data-state="closing"] { cursor: default; pointer-events: none; }
.nodi-svg[data-state="closing"] .nodi-core {
  animation: nodi-close-core 2.15s cubic-bezier(.2,.75,.25,1) both;
}
.nodi-svg[data-state="closing"] .halo { animation: nodi-close-halo 2.05s ease both; }
.nodi-svg[data-state="closing"] .limb { animation: nodi-close-limb .34s cubic-bezier(.55,0,.35,1) forwards; }
.nodi-svg[data-state="closing"] .arm-l { animation-delay: .04s; }
.nodi-svg[data-state="closing"] .arm-r { animation-delay: .22s; }
.nodi-svg[data-state="closing"] .leg-l { animation-delay: .40s; }
.nodi-svg[data-state="closing"] .leg-r { animation-delay: .58s; }
.nodi-svg[data-state="closing"] .role {
  animation: nodi-close-accessory .34s cubic-bezier(.5,0,.6,1) .88s forwards;
  transform-box: view-box;
  transform-origin: 130px 140px;
}
.nodi-svg[data-state="closing"] .face {
  animation: nodi-close-face .28s ease 1.27s forwards;
  transform-box: view-box;
  transform-origin: 130px 148px;
}
.nodi-svg[data-state="closing"] .closing-smoke { display: inline; fill: #fbf4e2; stroke: #d4af37; stroke-width: .8; }
.nodi-svg[data-state="closing"] .closing-smoke circle {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.nodi-svg[data-state="closing"] .closing-accessory-smoke circle { animation: nodi-close-smoke .58s ease-out .80s both; }
.nodi-svg[data-state="closing"] .closing-accessory-smoke circle:nth-child(2) { animation-delay: .86s; }
.nodi-svg[data-state="closing"] .closing-accessory-smoke circle:nth-child(3) { animation-delay: .91s; }
.nodi-svg[data-state="closing"] .closing-accessory-smoke circle:nth-child(4) { animation-delay: .84s; }
.nodi-svg[data-state="closing"] .closing-accessory-smoke circle:nth-child(5) { animation-delay: .92s; }
.nodi-svg[data-state="closing"] .closing-body-smoke circle { animation: nodi-close-smoke .68s ease-out 1.53s both; }
.nodi-svg[data-state="closing"] .closing-body-smoke circle:nth-child(2) { animation-delay: 1.58s; }
.nodi-svg[data-state="closing"] .closing-body-smoke circle:nth-child(3) { animation-delay: 1.62s; }
.nodi-svg[data-state="closing"] .closing-body-smoke circle:nth-child(4) { animation-delay: 1.67s; }
.nodi-svg[data-state="closing"] .closing-body-smoke circle:nth-child(5) { animation-delay: 1.71s; }

.nodi-svg[data-role="academic"] .role-academic { display: inline; }
.nodi-svg[data-role="genealogy"] .role-genealogy { display: inline; }
.nodi-svg[data-role="study"] .role-study { display: inline; }
.nodi-svg[data-role="study"] .arm-l { animation: none; }
.nodi-svg[data-role="study"] .arm-l .thread { d: path("M94 156 C 96 172 96 184 100 194"); }
.nodi-svg[data-role="study"] .arm-l .hand { transform: translate(100px, 198px); }
.nodi-svg[data-role="study"] .mouth-smile { transform: translateY(2px); }
.nodi-svg[data-state="closing"][data-role="study"] .arm-l { animation: nodi-close-limb .34s cubic-bezier(.55,0,.35,1) .04s forwards; }

@keyframes nodi-floaty { 0%,100%{transform:translateY(0) rotate(0deg)} 25%{transform:translateY(-6px) rotate(-1.2deg)} 50%{transform:translateY(-11px) rotate(0deg)} 75%{transform:translateY(-6px) rotate(1.2deg)} }
@keyframes nodi-leanfloat { 0%,100%{transform:translateY(0) rotate(3deg)} 50%{transform:translateY(-8px) rotate(5deg)} }
@keyframes nodi-hop { 0%{transform:translateY(0)} 30%{transform:translateY(-20px)} 55%{transform:translateY(-4px)} 75%{transform:translateY(-12px)} 100%{transform:translateY(0)} }
@keyframes nodi-breathe { 0%,100%{transform:translateY(8px) scale(1.012)} 50%{transform:translateY(13px) scale(.998)} }
@keyframes nodi-halo { 0%,100%{opacity:.55;transform:scale(1)} 50%{opacity:.85;transform:scale(1.05)} }
@keyframes nodi-haloBright { 0%,100%{opacity:.8;transform:scale(1.04)} 50%{opacity:1;transform:scale(1.13)} }
@keyframes nodi-blink { 0%,88%,100%{transform:scaleY(1)} 92%{transform:scaleY(.07)} 95%{transform:scaleY(1)} }
@keyframes nodi-swayR { 0%,100%{transform:rotate(-2deg)} 50%{transform:rotate(7deg)} }
@keyframes nodi-swayL { 0%,100%{transform:rotate(2deg)} 50%{transform:rotate(-6deg)} }
@keyframes nodi-legA { 0%,100%{transform:rotate(-4deg)} 50%{transform:rotate(5deg)} }
@keyframes nodi-legB { 0%,100%{transform:rotate(5deg)} 50%{transform:rotate(-4deg)} }
@keyframes nodi-dangle { 0%,100%{transform:rotate(-8deg)} 50%{transform:rotate(8deg)} }
@keyframes nodi-wave { 0%,100%{transform:rotate(-12deg)} 50%{transform:rotate(30deg)} }
@keyframes nodi-raisewave { 0%,100%{transform:rotate(-6deg)} 50%{transform:rotate(10deg)} }
@keyframes nodi-centrifuge { from{transform:rotate(0deg)} to{transform:rotate(360deg)} }
@keyframes nodi-thinking-core { from{transform:rotate(0deg)} to{transform:rotate(-360deg)} }
@keyframes nodi-thinking-eyes { 0%,100%{transform:scaleX(.96)} 50%{transform:scaleX(1.06) translateY(1px)} }
@keyframes nodi-thinking-trail { 0%,100%{opacity:.18;stroke-dasharray:2 12} 50%{opacity:.72;stroke-dasharray:15 5} }
@keyframes nodi-spin { to{transform:rotate(360deg)} }
@keyframes nodi-dash { from{stroke-dashoffset:20} to{stroke-dashoffset:0} }
@keyframes nodi-thinkdot { 0%,100%{opacity:.2;transform:translateY(0)} 50%{opacity:1;transform:translateY(-3px)} }
@keyframes nodi-nodein { 0%,100%{opacity:.2} 50%{opacity:1} }
@keyframes nodi-pop { 0%{transform:scale(0);opacity:0} 70%{transform:scale(1.25)} 100%{transform:scale(1);opacity:1} }
@keyframes nodi-twinkle { 0%,100%{opacity:.3;transform:scale(.8)} 50%{opacity:1;transform:scale(1.1)} }
@keyframes nodi-waveline { 0%,100%{opacity:0} 50%{opacity:.75} }
@keyframes nodi-zrise { 0%{opacity:0;transform:translateY(0) scale(.6)} 25%{opacity:.9} 100%{opacity:0;transform:translateY(-16px) scale(1.05)} }
@keyframes nodi-sweat { 0%{opacity:0;transform:translateY(-2px) scale(.5)} 25%{opacity:1;transform:translateY(0) scale(1)} 100%{opacity:0;transform:translateY(11px) scale(.9)} }
@keyframes nodi-close-limb { 0%{opacity:1;transform:scale(1)} 70%{opacity:.9} 100%{opacity:0;transform:scale(.04)} }
@keyframes nodi-close-accessory { 0%{opacity:1;filter:blur(0);transform:scale(1)} 100%{opacity:0;filter:blur(5px);transform:scale(.22)} }
@keyframes nodi-close-face { from{opacity:1;transform:scale(1)} to{opacity:0;transform:scale(.35)} }
@keyframes nodi-close-core { 0%,68%{opacity:1;transform:scale(1)} 78%{opacity:1;transform:scale(1.06)} 100%{opacity:0;transform:scale(.08)} }
@keyframes nodi-close-halo { 0%,68%{opacity:.7;transform:scale(1)} 84%{opacity:1;transform:scale(1.28)} 100%{opacity:0;transform:scale(1.65)} }
@keyframes nodi-close-smoke { 0%{opacity:0;transform:translateY(4px) scale(.2)} 32%{opacity:.92} 100%{opacity:0;transform:translateY(-18px) scale(1.8)} }

/* Holds the pose when nothing is happening — paused, not removed, so every keyframe
   above survives and resumes where it left off. See nodiOrb.css for the measurements
   that made this necessary; the classic Nodi pays the same per-frame SVG repaint. */
.nodi-svg.nodi-at-rest,
.nodi-svg.nodi-at-rest * { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
  .nodi-svg * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}
