/* Nova v3: the orb, copied as it is from public/styles.css lines 148-474 (the molten glass, the orb is
   alive, the moods and the moods part two; R12: every libraries.dev piece kept) so the v3 shell never
   loads the old stylesheet. Only the three Home status lines (styles.css 247-249) are left out. Do not
   edit here: change public/styles.css's copy first (frozen, D1) or, after the old shell is gone, here.
   The tokens these rules read (--brand, --orb-*, --ease, --spring, --ink-soft, --ink-faint, --display)
   are defined in v3.css with the same values. */

/* ---------- the molten glass orb (demo-ui .cv-orb-glass, colour from --brand) ---------- */
.orb { position: relative; display: block; flex: none; border-radius: 50%; user-select: none; }
.orb .glass {
  position: absolute; inset: 0; border-radius: 50%; isolation: isolate; overflow: hidden;
  background: radial-gradient(circle at 50% 58%, var(--orb-0) 0%, var(--orb-42) 42%, var(--orb-76) 76%, var(--orb-92) 92%, rgba(255, 255, 255, .42) 100%);
  filter: saturate(1.3) contrast(1.06);
  -webkit-backdrop-filter: blur(7px) saturate(1.35) brightness(1.04); backdrop-filter: blur(7px) saturate(1.35) brightness(1.04);
  box-shadow:
    0 26px 54px -18px rgba(150, 62, 20, .5),
    0 6px 16px -6px rgba(150, 62, 20, .34),
    0 0 26px 5px var(--orb-glow),
    inset 0 0 0 1px rgba(255, 255, 255, .42),
    inset -7px -12px 26px var(--orb-light),
    inset 9px 13px 32px var(--orb-shade);
  transition: box-shadow .35s var(--ease), filter .35s var(--ease);
}
.orb .core { position: absolute; inset: 5%; border-radius: 50%; overflow: hidden; opacity: .8; }
.orb .core::before, .orb .core::after { content: ""; position: absolute; border-radius: 50%; filter: blur(7px); }
.orb .core::before { inset: 4% 20% 34% 2%; background: radial-gradient(circle, var(--orb-core-a) 0%, var(--orb-core-a2) 45%, transparent 72%); }
.orb .core::after { inset: 32% 4% 2% 26%; background: radial-gradient(circle, var(--orb-core-b) 0%, var(--orb-core-b2) 48%, transparent 74%); }
.orb .sheen {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background:
    radial-gradient(circle at 50% 90%, var(--orb-sheen) 0%, transparent 34%),
    radial-gradient(circle at 78% 76%, var(--orb-sheen2) 0%, transparent 38%),
    linear-gradient(200deg, rgba(255, 255, 255, .26) 0%, rgba(255, 255, 255, 0) 30%);
  box-shadow: inset 0 -3px 11px var(--orb-sheen), inset 0 7px 18px var(--orb-shade), inset 0 0 14px rgba(255, 255, 255, .26);
}
.orb .spec { position: absolute; left: 21%; top: 14%; width: 25%; height: 17%; border-radius: 50%; pointer-events: none; rotate: -26deg; filter: blur(.6px);
  background: radial-gradient(ellipse at 44% 40%, #fff 0%, rgba(255, 255, 255, .86) 30%, rgba(255, 255, 255, .28) 58%, rgba(255, 255, 255, 0) 76%); }
.orb .spec2 { position: absolute; right: 16%; bottom: 19%; width: 16%; height: 11%; border-radius: 50%; pointer-events: none; filter: blur(1.2px);
  background: radial-gradient(circle, rgba(255, 244, 228, .8), rgba(255, 244, 228, 0) 70%); }
.orb::before { content: ""; position: absolute; inset: -34%; border-radius: 50%; pointer-events: none; z-index: -1;
  background: radial-gradient(50% 50% at 50% 50%, color-mix(in srgb, var(--brand) 22%, transparent), transparent 70%);
  transition: opacity .35s var(--ease), scale .35s var(--spring); }
/* Interactive orbs (demo-ui cv-neo-orb): lift on hover, sink on press, the halo swells and the glass
   brightens. A tap also sends one ring out from the rim. */
.orbbtn:hover .orb::before, .fab:hover .orb::before { scale: 1.12; }
.orbbtn:hover .orb .glass, .fab:hover .orb .glass { filter: saturate(1.4) contrast(1.06) brightness(1.04); box-shadow:
    0 30px 60px -18px color-mix(in srgb, var(--brand-deep) 56%, transparent),
    0 6px 16px -6px color-mix(in srgb, var(--brand-deep) 34%, transparent),
    0 0 34px 8px var(--orb-glow),
    inset 0 0 0 1px rgba(255, 255, 255, .5),
    inset -7px -12px 26px color-mix(in srgb, var(--brand-hi) 52%, transparent),
    inset 9px 13px 32px color-mix(in srgb, var(--brand-deep) 46%, transparent); }
.orb .ring { position: absolute; inset: 0; border-radius: 50%; pointer-events: none; border: 2px solid color-mix(in srgb, var(--brand) 70%, white); opacity: 0; }
.orb.tapped .ring { animation: ring .7s var(--ease) both; }
@keyframes ring { from { opacity: .9; scale: 1; } to { opacity: 0; scale: 1.55; } }
.orb::after { content: ""; position: absolute; left: 12%; right: 12%; bottom: -13%; height: 13%; border-radius: 50%; z-index: -1; pointer-events: none;
  background: radial-gradient(50% 50% at 50% 50%, color-mix(in srgb, var(--brand-deep) 35%, transparent), transparent 72%); }
.orb .name { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; font-family: var(--display); font-weight: 500; letter-spacing: .01em; text-shadow: 0 1px 6px color-mix(in srgb, var(--brand-deep) 60%, transparent); }
.orb.xs { width: 22px; height: 22px; } .orb.xs::before, .orb.xs::after { display: none; }
.orb.xs .glass, .orb.sm .glass { -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: 0 4px 10px -4px rgba(150, 62, 20, .5), 0 0 8px 1px var(--orb-glow), inset 0 0 0 1px rgba(255, 255, 255, .4), inset -2px -3px 6px var(--orb-light), inset 2px 3px 8px var(--orb-shade); }
.orb.xs .core::before, .orb.xs .core::after, .orb.sm .core::before, .orb.sm .core::after { filter: blur(2.5px); }
.orb.sm { width: 40px; height: 40px; }
.orb.md { width: 48px; height: 48px; }
.orb.lg { width: 88px; height: 88px; }
/* ---------- the orb is alive (bot-avatars behaviours on the Nutch orb, no face) ----------
   idle: breathes and floats, looks from corner to corner (the highlight glides), and now and then
   hops with a full turn. working: hops in rhythm, spins every third hop, glows brighter, the cores
   race. listening: leans in, breathes faster. waiting: nudges you every few seconds. done: one
   cheer (two quick bounces and a flash). error: a shake. Only the big orb, the floating orb and a
   busy orb move; reduced motion turns it all off. */
@media (prefers-reduced-motion: no-preference) {
  .orb.lg .glass, .fab .orb .glass { animation: breathe 4.6s ease-in-out infinite alternate, float 5.5s ease-in-out .5s infinite alternate; }
  .orb.lg .name { animation: float 5.5s ease-in-out .5s infinite alternate; }
  .orb.lg .spec, .fab .orb .spec { animation: look 9s ease-in-out infinite; }
  .orb.lg .core, .fab .orb .core { animation: hop-turn 11s cubic-bezier(.34, 1.4, .4, 1) infinite; }
  .orb.lg .sheen, .orb.working .sheen { animation: shine 3.4s ease-in-out infinite alternate; }
  .orb.lg .core::before, .orb.working .core::before { animation: core-a 11s ease-in-out infinite alternate; }
  .orb.lg .core::after, .orb.working .core::after { animation: core-b 14s ease-in-out infinite alternate; }
  /* busy */
  .orb.working .glass { animation: hop 1.1s cubic-bezier(.36, 0, .2, 1) infinite, spin 3.3s cubic-bezier(.6, 0, .3, 1) infinite; filter: saturate(1.45) contrast(1.06) brightness(1.04); }
  .orb.working .core { animation: spin 3.3s cubic-bezier(.6, 0, .3, 1) infinite; }
  .orb.working .core::before { animation-duration: 4s; } .orb.working .core::after { animation-duration: 5s; }
  .orb.working .sheen { animation-duration: 1.1s; }
  .orb.working::after { animation: hop-shadow 1.1s cubic-bezier(.36, 0, .2, 1) infinite; }
  .orb.working::before { opacity: 1; scale: 1.15; }
  /* listening (the input has focus): lean in, breathe faster */
  .stage.listening .orb.lg .glass, .stage.listening .fab .orb .glass { animation: lean 2.2s ease-in-out infinite alternate, breathe 2.2s ease-in-out infinite alternate; }
  /* waiting on you: a nudge every few seconds */
  .orb.waiting .glass { animation: nudge 5s ease-in-out infinite; }
  /* one-shot states */
  .orb.done .glass { animation: cheer .9s cubic-bezier(.34, 1.56, .64, 1) 1; }
  .orb.done .core { animation: spin .9s cubic-bezier(.6, 0, .3, 1) 1; }
  .orb.error .glass { animation: shake .55s ease-in-out 1; }
}
@keyframes breathe { from { scale: .985; } to { scale: 1.025; } }
@keyframes shine { from { opacity: .75; } to { opacity: 1; } }
@keyframes float { from { translate: 0 -5px; } to { translate: 0 6px; } }
@keyframes look { 0%, 18% { translate: 0 0; } 24%, 46% { translate: 34% 4%; } 52%, 72% { translate: 30% 46%; } 78%, 94% { translate: -6% 40%; } 100% { translate: 0 0; } }
@keyframes hop-turn { 0%, 86% { translate: 0 0; rotate: 0deg; } 89% { translate: 0 -9%; } 96% { translate: 0 2%; rotate: 360deg; } 100% { translate: 0 0; rotate: 360deg; } }
@keyframes hop { 0%, 100% { translate: 0 0; scale: 1.05 .95; } 35% { translate: 0 -13%; scale: .96 1.05; } 70% { translate: 0 -3%; scale: 1 1; } }
@keyframes hop-shadow { 0%, 100% { scale: 1.05 1; opacity: 1; } 35% { scale: .82 .9; opacity: .55; } }
@keyframes spin { 0%, 62% { rotate: 0deg; } 100% { rotate: 360deg; } }
@keyframes lean { from { rotate: -5deg; translate: -2px 0; } to { rotate: 4deg; translate: 2px 0; } }
@keyframes nudge { 0%, 84%, 100% { rotate: 0deg; } 88% { rotate: -7deg; } 92% { rotate: 6deg; } 96% { rotate: -3deg; } }
@keyframes cheer { 0% { translate: 0 0; } 25% { translate: 0 -12%; scale: .96 1.06; filter: brightness(1.18); } 45% { translate: 0 0; scale: 1.05 .95; } 65% { translate: 0 -7%; scale: 1 1; filter: brightness(1.1); } 100% { translate: 0 0; scale: 1; filter: brightness(1); } }
@keyframes shake { 0%, 100% { translate: 0 0; } 20% { translate: -6px 0; } 40% { translate: 6px 0; } 60% { translate: -4px 0; } 80% { translate: 3px 0; } }
@keyframes core-b { 0% { translate: 0 0; scale: 1; } 50% { translate: -7% -8%; scale: 1.12; } 100% { translate: 6% -4%; scale: .96; } }
@keyframes core-a { 0% { translate: 0 0; scale: 1; } 50% { translate: 8% 6%; scale: 1.1; } 100% { translate: -4% 7%; scale: .95; } }

/* ---------- orb moods: the orb with a face ----------
   Orbs of 40px and up get two eyes (.face), a thinking swirl and an fx layer (sparkles, a pulse
   ring, z's), added by app.js addFace(). The xs orb (22px) stays faceless. One attribute drives
   it: data-mood = hello | idle | listening | working | done | needs | offline | oops. Motion is
   transform and opacity only; reduced motion keeps the still poses; a hidden app pauses loops.
   Never a sad or pleading face: oops is a shake and a quick blink, needs is attention only. */
.orb.has-face { --eye: #fffaf2; }
.orb.has-face .glass { container-type: size; }
.orb .swirl { position: absolute; inset: 7%; border-radius: 50%; pointer-events: none; opacity: 0;
  background: conic-gradient(from 0deg, transparent 0 12%, color-mix(in srgb, var(--orb-core-a) 90%, transparent) 26%, transparent 44%,
    transparent 55%, color-mix(in srgb, var(--brand-hi) 55%, transparent) 70%, transparent 86%);
  -webkit-mask: radial-gradient(circle, transparent 18%, #000 46%, #000 62%, transparent 74%);
          mask: radial-gradient(circle, transparent 18%, #000 46%, #000 62%, transparent 74%); }
.orb .face { position: absolute; inset: 0; pointer-events: none; translate: calc(var(--px, 0) * 7cqw) calc(var(--py, 0) * 6cqw); transition: translate .45s var(--ease); }
.orb .eyes { position: absolute; left: 50%; top: 45%; width: 32cqw; height: 13cqw; margin: -6.5cqw 0 0 -16cqw; display: flex; justify-content: space-between; }
.orb .eye { position: relative; width: 9.5cqw; height: 13cqw; transform-origin: 50% 60%; }
.orb .eye::before { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--eye); box-shadow: 0 0 3cqw rgba(255, 250, 240, .55); }
.orb .eye::after { content: ""; position: absolute; left: -22%; right: -22%; top: 12%; aspect-ratio: 1; border-radius: 50%; opacity: 0;
  border: 2.6cqw solid transparent; border-top-color: var(--eye); filter: drop-shadow(0 0 1.5cqw rgba(255, 250, 240, .5)); }
.orb.xs .face, .orb.xs .fx, .orb.xs .swirl { display: none; }
.orb .fx { position: absolute; inset: 0; pointer-events: none; }
.orb .fx > i { position: absolute; opacity: 0; }
.orb .spark { width: 20%; aspect-ratio: 1; background: color-mix(in srgb, var(--brand) 70%, #fff);
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%);
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--brand) 60%, transparent)); }
.orb .spark.a { left: 88%; top: 2%; } .orb .spark.b { left: -10%; top: 12%; width: 14%; } .orb .spark.c { left: 98%; top: 46%; width: 13%; }
.orb .pulse { inset: 0; border-radius: 50%; box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 55%, white), 0 0 18px 2px var(--orb-glow); }
.orb .z { font: 600 16px/1 var(--display); color: var(--ink-soft); left: 84%; top: 4%; font-style: normal; }
.orb .z.b { font-size: 12px; left: 96%; top: -12%; }
/* still poses (also what reduced motion shows) */
.orb.has-face[data-mood="listening"]::before { scale: 1.1; }
.orb.has-face[data-mood="working"] .swirl { opacity: .9; rotate: 40deg; }
.orb.has-face[data-mood="working"] .eyes { translate: 4cqw -5cqw; }
.orb.has-face[data-mood="working"]::before { scale: 1.15; }
.orb.has-face[data-mood="done"] .eye::before { opacity: 0; }
.orb.has-face[data-mood="done"] .eye::after { opacity: 1; }
.orb.has-face[data-mood="needs"] .pulse.a { opacity: .45; scale: 1.14; }
.orb.has-face[data-mood="needs"] .eye { scale: 1.12; }
.orb.has-face[data-mood="offline"] .glass { filter: saturate(.55) brightness(.97); }
.orb.has-face[data-mood="offline"]::before { opacity: .35; }
.orb.has-face[data-mood="offline"] .eye { scale: 1 .16; }
.orb.has-face[data-mood="offline"] .z.a { opacity: .8; }
.orb.has-face[data-mood="oops"] .glass { filter: saturate(.8); }
@media (prefers-reduced-motion: no-preference) {
  /* with a face the highlight stays put and the eyes do the looking */
  .orb.has-face .spec { animation: none; }
  .orb.has-face .core::before { animation: core-a 11s ease-in-out infinite alternate; }
  .orb.has-face .core::after { animation: core-b 14s ease-in-out infinite alternate; }
  /* idle: breathe and float; eyes blink and drift */
  .orb.has-face[data-mood="idle"] .glass { animation: breathe 4.6s ease-in-out infinite alternate, float 5.5s ease-in-out .5s infinite alternate; }
  .orb.has-face[data-mood="idle"] .eye { animation: blink 5s ease-in-out infinite; }
  .orb.has-face[data-mood="idle"] .eyes { animation: drift 9s ease-in-out infinite; }
  /* hello (first open of the day): pops in, a small tilt, a wink that turns into a smile */
  .orb.has-face[data-mood="hello"] .glass { animation: greet 4s var(--ease) 1 both; }
  .orb.has-face[data-mood="hello"]::before { animation: halo-bloom 4s var(--ease) 1 both; }
  .orb.has-face[data-mood="hello"] .eye { animation: greet-eye 4s ease-in-out 1; }
  .orb.has-face[data-mood="hello"] .eye::before { animation: dot-off 4s ease-in-out 1; }
  .orb.has-face[data-mood="hello"] .eye::after { animation: arc-on 4s ease-in-out 1; }
  /* listening: leans in, breathes faster, eyes on the field (app.js sets --px/--py) */
  .orb.has-face[data-mood="listening"] .glass { animation: lean-in 3.6s ease-in-out infinite, breathe 1.8s ease-in-out infinite alternate; }
  .orb.has-face[data-mood="listening"] .eye { animation: blink 3.6s ease-in-out .9s infinite; }
  /* working: the core swirls, a soft hop, the halo breathes; eyes ponder (the body never spins) */
  .orb.has-face[data-mood="working"] .swirl { animation: swirl 2.4s linear infinite; }
  .orb.has-face[data-mood="working"] .glass { animation: soft-hop 1.2s cubic-bezier(.36, 0, .2, 1) infinite; }
  .orb.has-face[data-mood="working"]::after { animation: hop-shadow 1.2s cubic-bezier(.36, 0, .2, 1) infinite; }
  .orb.has-face[data-mood="working"]::before { animation: halo-breathe 2.4s ease-in-out infinite alternate; }
  .orb.has-face[data-mood="working"] .core { animation: spin 3.3s cubic-bezier(.6, 0, .3, 1) infinite; }
  .orb.has-face[data-mood="working"] .eyes { animation: ponder 4.8s ease-in-out infinite; }
  .orb.has-face[data-mood="working"] .eye { animation: slow-blink 4.8s ease-in-out infinite; }
  /* done: two bounces, three sparkles, eyes smile; plays once */
  .orb.has-face[data-mood="done"] .glass { animation: happy 2.8s cubic-bezier(.34, 1.56, .64, 1) 1; }
  .orb.has-face[data-mood="done"]::after { animation: happy-shadow 2.8s cubic-bezier(.34, 1.56, .64, 1) 1; }
  .orb.has-face[data-mood="done"] .spark { animation: spark 2.8s var(--ease) 1; }
  .orb.has-face[data-mood="done"] .spark.b { animation-delay: .12s; } .orb.has-face[data-mood="done"] .spark.c { animation-delay: .24s; }
  /* needs you: a soft ring goes out, the halo swells, a small wiggle; eyes widen at you */
  .orb.has-face[data-mood="needs"] .pulse { animation: pulse-out 3.2s var(--ease) infinite; }
  .orb.has-face[data-mood="needs"] .pulse.b { animation-delay: .5s; }
  .orb.has-face[data-mood="needs"] .glass { animation: wiggle 3.2s ease-in-out infinite; }
  .orb.has-face[data-mood="needs"]::before { animation: halo-breathe 1.6s ease-in-out infinite alternate; }
  .orb.has-face[data-mood="needs"] .eye { animation: widen 3.2s ease-in-out infinite; }
  /* offline: a slow, low breath; z's drift up; the eyes are lines that half open */
  .orb.has-face[data-mood="offline"] .glass { animation: doze 6s ease-in-out infinite alternate; }
  .orb.has-face[data-mood="offline"] .z { animation: zee 4s ease-out infinite; }
  .orb.has-face[data-mood="offline"] .z.b { animation-delay: 2s; }
  .orb.has-face[data-mood="offline"] .eye { animation: drowsy 6s ease-in-out infinite; }
  /* oops: a small shake, the glow cools, a quick blink and a glance aside, then it recovers */
  .orb.has-face[data-mood="oops"] .glass { animation: oops 3.2s ease-in-out 1; }
  .orb.has-face[data-mood="oops"]::before { animation: halo-dim 3.2s ease-in-out 1; }
  .orb.has-face[data-mood="oops"] .eyes { animation: oops-look 3.2s ease-in-out 1; }
  .orb.has-face[data-mood="oops"] .eye { animation: oops-eye 3.2s ease-in-out 1; }
}
.orbs-paused .orb, .orbs-paused .orb *, .orbs-paused .orb::before, .orbs-paused .orb::after,
.orbs-paused .orb *::before, .orbs-paused .orb *::after { animation-play-state: paused !important; }
@keyframes blink { 0%, 90%, 100% { scale: 1 1; } 93% { scale: 1.05 .08; } 96% { scale: 1 1; } }
@keyframes slow-blink { 0%, 44%, 56%, 100% { scale: 1 1; } 50% { scale: 1.05 .1; } }
@keyframes drift { 0%, 20% { translate: 0 0; } 30%, 48% { translate: 5cqw 1cqw; } 58%, 78% { translate: -5cqw 2cqw; } 88%, 100% { translate: 0 0; } }
@keyframes greet { 0% { scale: .7; translate: 0 8%; opacity: 0; } 12% { scale: 1.07; translate: 0 -4%; opacity: 1; } 20% { scale: .98 1.02; translate: 0 0; }
  26% { scale: 1; rotate: 0deg; } 34% { rotate: -9deg; } 42% { rotate: 7deg; } 50% { rotate: -4deg; } 58%, 100% { rotate: 0deg; scale: 1; translate: 0 0; opacity: 1; } }
@keyframes halo-bloom { 0% { opacity: 0; scale: .6; } 14% { opacity: 1; scale: 1.25; } 40%, 100% { opacity: 1; scale: 1; } }
@keyframes greet-eye { 0%, 14%, 20%, 24%, 30%, 100% { scale: 1 1; } 17% { scale: 1.05 .08; } 27% { scale: 1.05 .08; } }
@keyframes dot-off { 0%, 32% { opacity: 1; } 36%, 66% { opacity: 0; } 70%, 100% { opacity: 1; } }
@keyframes arc-on { 0%, 32% { opacity: 0; } 36%, 66% { opacity: 1; } 70%, 100% { opacity: 0; } }
@keyframes lean-in { 0%, 100% { rotate: -3deg; translate: -2px 2px; } 50% { rotate: 4deg; translate: 3px 3px; } }
@keyframes swirl { to { rotate: 360deg; } }
@keyframes soft-hop { 0%, 100% { translate: 0 0; scale: 1.04 .96; } 35% { translate: 0 -8%; scale: .97 1.04; } 70% { translate: 0 -2%; scale: 1 1; } }
@keyframes halo-breathe { from { scale: 1; opacity: .7; } to { scale: 1.2; opacity: 1; } }
@keyframes ponder { 0%, 10% { translate: -5cqw -5cqw; } 40%, 60% { translate: 5cqw -6cqw; } 90%, 100% { translate: -5cqw -5cqw; } }
@keyframes happy { 0% { translate: 0 0; scale: 1; } 9% { translate: 0 -14%; scale: .95 1.07; } 18% { translate: 0 0; scale: 1.07 .93; }
  26% { translate: 0 -8%; scale: .98 1.03; } 34% { translate: 0 0; scale: 1.03 .97; } 42%, 100% { translate: 0 0; scale: 1; } }
@keyframes happy-shadow { 0%, 34%, 100% { scale: 1; opacity: 1; } 9% { scale: .75 .85; opacity: .5; } 26% { scale: .88; opacity: .7; } }
@keyframes spark { 0%, 6% { opacity: 0; scale: .2; rotate: 0deg; translate: 0 0; } 16% { opacity: 1; scale: 1.1; } 40% { opacity: 1; scale: .9; translate: 20% -30%; rotate: 45deg; } 55%, 100% { opacity: 0; scale: .4; translate: 30% -50%; rotate: 70deg; } }
@keyframes pulse-out { 0% { opacity: .75; scale: 1; } 60%, 100% { opacity: 0; scale: 1.55; } }
@keyframes wiggle { 0%, 72%, 100% { rotate: 0deg; translate: 0 0; } 76% { rotate: -8deg; translate: 0 -3%; } 81% { rotate: 7deg; translate: 0 -3%; } 86% { rotate: -4deg; translate: 0 -1%; } 91% { rotate: 2deg; translate: 0 0; } }
@keyframes widen { 0%, 70%, 96%, 100% { scale: 1 1; } 76%, 90% { scale: 1.2 1.25; } }
@keyframes doze { from { scale: 1.01 .97; translate: 0 5%; rotate: 5deg; } to { scale: .99 1; translate: 0 2%; rotate: 3deg; } }
@keyframes zee { 0% { opacity: 0; translate: 0 0; scale: .7; } 20% { opacity: .85; } 100% { opacity: 0; translate: 90% -160%; scale: 1.2; } }
@keyframes drowsy { 0%, 30% { scale: 1 .14; } 45%, 55% { scale: 1 .5; } 70%, 100% { scale: 1 .14; } }
@keyframes oops { 0% { translate: 0 0; rotate: 0deg; } 4% { translate: -6% 0; } 8% { translate: 6% 0; } 12% { translate: -4% 0; } 16% { translate: 3% 0; }
  22%, 64% { translate: 0 2%; rotate: -3deg; } 78%, 100% { translate: 0 0; rotate: 0deg; } }
@keyframes halo-dim { 0%, 16% { opacity: 1; } 24%, 64% { opacity: .5; } 80%, 100% { opacity: 1; } }
@keyframes oops-look { 0%, 18% { translate: 0 0; } 26%, 62% { translate: -4cqw 1cqw; } 78%, 100% { translate: 0 0; } }
@keyframes oops-eye { 0%, 2%, 9%, 100% { scale: 1 1; } 5% { scale: 1.05 .08; } }
/* ---------- orb moods, part two (2026-10-01): a mouth, blush, voice, and the moods of places ----------
   The mouth is a tiny curve in dark brand ink: a smile on hello, done, happy, proud and heard,
   flat while working, a small o when she needs you, a sleepy line offline, a small wobble on oops
   (never a frown), soft otherwise. Blush only when she is pleased (done, happy, proud, heard).
   Mouth and blush hide on orbs of 40px and less. voice: a voice message is recording, the ears
   and halo swell with --lvl (0..1, set by app.js on the root). Place moods: careful (a payment
   waits on the user), patient (a group plan waits on others), proud (a page went live), happy
   (all clear), heard (a voice message became text). Orbs with data-pin keep their own mood. */
.orb.has-face .mouth { position: absolute; left: 50%; top: 64%; width: 16cqw; height: 8cqw; margin: -4cqw 0 0 -8cqw;
  --m: color-mix(in srgb, color-mix(in srgb, var(--brand-deep) 55%, #1a0c04) 74%, transparent); }
.orb.has-face .mouth::before { content: ""; position: absolute; left: -1cqw; top: -5cqw; width: 18cqw; height: 11cqw; border-radius: 50%;
  border: 3cqw solid transparent; border-bottom-color: var(--m); transform-origin: 50% 85%; scale: .82 .84;
  transition: scale .35s var(--ease), opacity .25s; }
.orb.has-face .mouth::after { content: ""; position: absolute; left: 50%; top: 50%; width: 13cqw; height: 3.3cqw; margin: -1.65cqw 0 0 -6.5cqw;
  border-radius: 50%; background: var(--m); opacity: 0; transition: scale .35s var(--ease), opacity .25s; }
.orb.has-face .blush { position: absolute; top: 55%; width: 13cqw; height: 6.5cqw; border-radius: 50%; opacity: 0; transition: opacity .4s;
  background: radial-gradient(closest-side, rgba(255, 70, 110, .8), rgba(255, 70, 110, 0)); }
.orb.has-face .blush.l { left: 17%; } .orb.has-face .blush.r { right: 17%; }
@container (max-width: 40px) { .orb .mouth, .orb .blush { display: none; } }
.orb.has-face[data-mood="hello"] .mouth::before { scale: 1.1 1.15; }
.orb.has-face:is([data-mood="listening"], [data-mood="voice"]) .mouth::before { scale: .72 .8; }
.orb.has-face:is([data-mood="done"], [data-mood="happy"]) .mouth::before { scale: 1.28 1.4; }
.orb.has-face[data-mood="proud"] .mouth::before { scale: 1.36 1.5; }
.orb.has-face[data-mood="heard"] .mouth::before { scale: 1.2 1.3; }
.orb.has-face[data-mood="patient"] .mouth::before { scale: .66 .7; }
.orb.has-face:is([data-mood="working"], [data-mood="needs"], [data-mood="offline"], [data-mood="careful"]) .mouth::before { opacity: 0; }
.orb.has-face:is([data-mood="working"], [data-mood="needs"], [data-mood="offline"], [data-mood="careful"]) .mouth::after { opacity: 1; }
.orb.has-face[data-mood="working"] .mouth::after { scale: .8 1; }
.orb.has-face[data-mood="needs"] .mouth::after { scale: .5 2.3; }
.orb.has-face[data-mood="offline"] .mouth { translate: 0 2cqw; }
.orb.has-face[data-mood="offline"] .mouth::after { opacity: .7; scale: .55 .7; }
.orb.has-face[data-mood="careful"] .mouth::after { scale: .55 1; }
.orb.has-face[data-mood="oops"] .mouth { translate: -1.5cqw 2.5cqw; }
.orb.has-face[data-mood="oops"] .mouth::before { scale: .6 .5; rotate: -9deg; }
.orb.has-face:is([data-mood="done"], [data-mood="happy"], [data-mood="proud"], [data-mood="heard"]) .blush { opacity: 1; }
.orb.has-face[data-mood="heard"] .blush { opacity: .9; }
/* eyes that smile */
.orb.has-face:is([data-mood="happy"], [data-mood="proud"], [data-mood="heard"]) .eye::before { opacity: 0; }
.orb.has-face:is([data-mood="happy"], [data-mood="proud"], [data-mood="heard"]) .eye::after { opacity: 1; }
/* fx: the ear rings (voice) and the waiting dots (patient) */
.orb .fx > .ear { inset: 0; border-radius: 50%; box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--brand) 55%, white), 0 0 14px 1px var(--orb-glow); }
.orb .dots { position: absolute; left: -34%; top: -6%; display: flex; gap: 3px; opacity: 0; transition: opacity .4s; }
.orb .dots b { width: 5px; height: 5px; border-radius: 50%; background: color-mix(in srgb, var(--brand) 55%, var(--ink-faint)); }
.orb .dots b:nth-child(2) { opacity: .7; } .orb .dots b:nth-child(3) { opacity: .4; }
/* still poses (also what reduced motion shows) */
.orb.has-face[data-mood="voice"]::before { scale: 1.12; }
.orb.has-face[data-mood="voice"] .glass { rotate: 3deg; }
.orb.has-face[data-mood="voice"] .eye { scale: 1.06 1.1; }
.orb.has-face[data-mood="voice"] .ear.a { opacity: .45; scale: 1.16; }
.orb.has-face[data-mood="voice"] .ear.b { opacity: .2; scale: 1.36; }
.orb.has-face[data-mood="heard"] .glass { translate: 0 5%; rotate: 4deg; scale: 1.02 .98; }
.orb.has-face[data-mood="careful"] .face { translate: -5cqw 4cqw; }
.orb.has-face[data-mood="careful"] .eye { scale: 1.02 .72; }
.orb.has-face[data-mood="careful"] .pulse.a { opacity: .3; scale: 1.08; }
.orb.has-face[data-mood="careful"]::before { opacity: .7; scale: .95; }
.orb.has-face[data-mood="patient"] .eyes { translate: 3cqw -4cqw; }
.orb.has-face[data-mood="patient"] .eye { scale: 1 .82; }
.orb.has-face[data-mood="patient"] .glass { rotate: 4deg; }
.orb.has-face[data-mood="patient"] .dots { opacity: 1; }
.orb.has-face[data-mood="proud"] .glass { translate: 0 -10%; scale: .97 1.04; }
.orb.has-face[data-mood="proud"]::after { scale: .78 .85; opacity: .5; }
.orb.has-face:is([data-mood="proud"], [data-mood="happy"]) .spark { opacity: 1; }
.orb.has-face:is([data-mood="proud"], [data-mood="happy"]) .spark.a { translate: 10% -20%; rotate: 30deg; }
@media (prefers-reduced-motion: no-preference) {
  /* voice: the halo and ears follow the voice level; eyes wide on the field, a small tilt */
  .orb.has-face[data-mood="voice"]::before { scale: calc(1.04 + var(--lvl, .2) * .3); opacity: calc(.75 + var(--lvl, .2) * .25); transition: scale .12s linear, opacity .12s linear; }
  .orb.has-face[data-mood="voice"] .glass { animation: float 5.5s ease-in-out infinite alternate; scale: calc(1 + var(--lvl, .2) * .035); rotate: calc(2deg + var(--lvl, .2) * 5deg); transition: scale .12s linear, rotate .2s linear; }
  .orb.has-face[data-mood="voice"] .ear.a { opacity: calc(.25 + var(--lvl, .2) * .5); scale: calc(1.1 + var(--lvl, .2) * .16); transition: scale .12s linear, opacity .12s linear; }
  .orb.has-face[data-mood="voice"] .ear.b { opacity: calc(.08 + var(--lvl, .2) * .3); scale: calc(1.26 + var(--lvl, .2) * .3); transition: scale .15s linear, opacity .15s linear; }
  .orb.has-face[data-mood="voice"] .eye { animation: blink 4s ease-in-out 1s infinite; }
  /* heard: a happy nod once */
  .orb.has-face[data-mood="heard"] .glass { animation: nod 2.4s var(--ease) 1 both; }
  /* oops: the mouth wobbles once */
  .orb.has-face[data-mood="oops"] .mouth::before { animation: wobble 1.2s ease-in-out .3s 1; }
  /* careful: very still; slow, deliberate blinks */
  .orb.has-face[data-mood="careful"] .eye { animation: careful-blink 5s ease-in-out infinite; }
  /* patient: a slow sway, the dots take turns */
  .orb.has-face[data-mood="patient"] .glass { animation: sway 5s ease-in-out infinite alternate; }
  .orb.has-face[data-mood="patient"] .dots b { animation: wait-dot 1.8s ease-in-out infinite; }
  .orb.has-face[data-mood="patient"] .dots b:nth-child(2) { animation-delay: .3s; } .orb.has-face[data-mood="patient"] .dots b:nth-child(3) { animation-delay: .6s; }
  .orb.has-face[data-mood="patient"] .eye { animation: slow-blink 6s ease-in-out infinite; }
  /* proud: bounces up and stays a little lifted; sparkles twinkle */
  .orb.has-face[data-mood="proud"] .glass { animation: proud 2.8s cubic-bezier(.34, 1.56, .64, 1) 1 both; }
  .orb.has-face[data-mood="proud"]::after { animation: proud-shadow 2.8s cubic-bezier(.34, 1.56, .64, 1) 1 both; }
  /* happy: breathes and floats, sparkles twinkle */
  .orb.has-face[data-mood="happy"] .glass { animation: breathe 4.6s ease-in-out infinite alternate, float 5.5s ease-in-out .5s infinite alternate; }
  .orb.has-face:is([data-mood="proud"], [data-mood="happy"]) .spark { animation: twinkle 2.6s ease-in-out infinite; }
  .orb.has-face:is([data-mood="proud"], [data-mood="happy"]) .spark.b { animation-delay: .6s; }
  .orb.has-face:is([data-mood="proud"], [data-mood="happy"]) .spark.c { animation-delay: 1.2s; }
}
@keyframes nod { 0% { translate: 0 0; rotate: 0deg; scale: 1; } 18% { translate: 0 7%; rotate: 5deg; scale: 1.03 .96; } 34% { translate: 0 -3%; rotate: -1deg; scale: .99 1.02; }
  50% { translate: 0 5%; rotate: 4deg; scale: 1.02 .98; } 100% { translate: 0 0; rotate: 0deg; scale: 1; } }
@keyframes wobble { 0%, 100% { rotate: -9deg; } 25% { rotate: 5deg; } 50% { rotate: -7deg; } 75% { rotate: 2deg; } }
@keyframes careful-blink { 0%, 86%, 100% { scale: 1.02 .72; } 91% { scale: 1.05 .08; } }
@keyframes sway { from { rotate: 2deg; } to { rotate: 6deg; } }
@keyframes wait-dot { 0%, 100% { translate: 0 0; } 30% { translate: 0 -3px; } 60% { translate: 0 0; } }
@keyframes proud { 0% { translate: 0 0; scale: 1; } 14% { translate: 0 -16%; scale: .95 1.07; } 28% { translate: 0 0; scale: 1.06 .94; }
  42% { translate: 0 -12%; scale: .98 1.03; } 56% { translate: 0 -2%; scale: 1.02 .98; } 100% { translate: 0 -10%; scale: .97 1.04; } }
@keyframes proud-shadow { 0% { scale: 1; opacity: 1; } 14% { scale: .75 .85; opacity: .5; } 28% { scale: 1; opacity: 1; } 100% { scale: .78 .85; opacity: .5; } }
@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
