/* Shared portal VoiceOrb styling from packages/shared/src/components/voice-orb/voiceOrbStyles.ts. */
/* ============================================================
   VoiceOrb : animated assistant orb  ·  sage/black edition
   States: standby | idle | listening | processing | speaking | muted
   Pure CSS. No JS animation loop, no dependencies.
   Drive it with:  data-state="listening"  and  style="--level: 0.7"
   ============================================================ */

/* Registered so the gradient angle can be animated smoothly.
   Browsers without @property fall back to a static angle. */
@property --grad-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 90deg;
}

.vo {
  --size: 260px;

  /* ---- palette: the two stops everything is built from ---- */
  --sage:      rgb(98, 122, 101);
  --sage-lite: rgb(146, 172, 149);
  --sage-deep: rgb(58, 74, 60);
  --void:      rgb(0, 0, 0);

  /* the gradient itself : stops fixed, endpoints swappable per state */
  --g1: var(--sage);
  --g2: var(--void);
  --grad:
    linear-gradient(
      var(--grad-angle),
      var(--g1) 0.17%,
      var(--g2) 27.965%,
      var(--g2) 47.658%,
      var(--g1) 76.266%
    );

  /* per-state knobs, defaults = standby */
  --rim-a: var(--sage-lite);
  --rim-b: var(--sage);
  --glow: rgba(98, 122, 101, 0.34);
  --mark-color: rgb(226, 234, 227);
  --mark-opacity: 0.92;
  --spec: 0.14;

  --angle-speed: 16s;
  --rim-speed: 7s;
  --blob-speed: 12s;
  --breathe-speed: 4.5s;
  --breathe-amp: 0.03;
  --rim-width: 5px;
  --rim-blur: 3px;
  --glow-scale: 1;
  --base-scale: 1;

  /* live audio amplitude, 0..1 : set from JS */
  --level: 0;

  position: relative;
  display: grid;
  place-items: center;
  width: var(--size);
  height: var(--size);
  border: 0;
  padding: 0;
  background: none;
  isolation: isolate;
  transform: scale(calc(var(--base-scale) + var(--level) * 0.10));
  transition: transform 120ms ease-out;
  animation: vo-angle var(--angle-speed) linear infinite;
}

/* ---------- layer 1: ambient bloom behind the orb ---------- */
.vo__ambient {
  position: absolute;
  inset: -26%;
  border-radius: 50%;
  background:
    radial-gradient(40% 40% at 34% 34%, var(--glow), transparent 70%),
    radial-gradient(44% 44% at 66% 64%, var(--glow), transparent 72%);
  filter: blur(40px);
  transform: scale(var(--glow-scale));
  transition: background 600ms ease, transform 600ms ease;
  animation: vo-drift 11s ease-in-out infinite alternate;
}

/* ---------- layer 2: the sphere ---------- */
.vo__body {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: var(--grad);
  box-shadow:
    inset 0 -22px 44px -20px rgba(0, 0, 0, 0.85),
    inset 0 16px 34px -20px rgba(255, 255, 255, 0.55),
    0 26px 60px -26px rgba(98, 122, 101, 0.55);
  transition: box-shadow 600ms ease;
  animation: vo-breathe var(--breathe-speed) ease-in-out infinite;
}

/* ---------- layer 2b: the fluid interior (WebGL) ---------- */
.vo__fluid {
  position: absolute;
  inset: -20%;          /* larger than the sphere so particles have room */
  width: 140%;
  height: 140%;
  display: block;
  pointer-events: none;
  animation: vo-breathe var(--breathe-speed) ease-in-out infinite;
}

/* When the shader is live it owns the interior: the CSS gradient
   underneath becomes a flat black backing (it still shows if WebGL
   is unavailable), the inner blob steps aside, and the sphere's
   shading comes from the shader's own lighting term. */
.vo[data-fluid="on"] .vo__body {
  background: #000;
  box-shadow: 0 26px 60px -26px rgba(98, 122, 101, 0.55);
}
.vo[data-fluid="on"] .vo__blob { display: none; }
.vo[data-fluid="on"] .vo__spec { --spec: calc(var(--spec-base, 0.14) * 0.5); }

/* ---------- layer 3: inner light, drifting across the black ---------- */
.vo__blob {
  position: absolute;
  inset: 12%;
  border-radius: 46% 54% 58% 42% / 52% 44% 56% 48%;
  background:
    radial-gradient(56% 56% at 38% 38%, var(--sage-lite), transparent 68%),
    radial-gradient(60% 60% at 68% 66%, var(--sage), transparent 70%);
  filter: blur(22px);
  opacity: calc(0.35 + var(--level) * 0.35);
  mix-blend-mode: screen;
  transition: opacity 200ms ease;
  animation:
    vo-spin var(--blob-speed) linear infinite,
    vo-morph calc(var(--blob-speed) * 0.7) ease-in-out infinite alternate;
}

/* ---------- layer 4: sweeping rim light ---------- */
.vo__rim {
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    var(--rim-b) 40deg,
    var(--rim-a) 110deg,
    var(--rim-b) 165deg,
    transparent 230deg,
    transparent 360deg
  );
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - var(--rim-width)), #000 calc(100% - var(--rim-width) + 1px));
  mask: radial-gradient(closest-side, transparent calc(100% - var(--rim-width)), #000 calc(100% - var(--rim-width) + 1px));
  filter: blur(var(--rim-blur));
  animation: vo-spin var(--rim-speed) linear infinite;
}

/* faint second rim, counter-rotating : the "glass edge" read */
.vo__rim--soft {
  inset: 2%;
  --rim-width: 11px;
  opacity: 0.4;
  filter: blur(12px);
  animation-direction: reverse;
  animation-duration: calc(var(--rim-speed) * 1.9);
}

/* ---------- layer 5: specular highlight ---------- */
.vo__spec {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: radial-gradient(28% 22% at 33% 24%, rgba(255, 255, 255, var(--spec)), transparent 70%);
  pointer-events: none;
}

/* ---------- layer 7: the mark ---------- */
.vo__mark {
  position: relative;   /* above the gradient layers */
  z-index: 1;
  font: 500 calc(var(--size) * 0.30) / 1 var(--vo-mark-font, ui-serif, Georgia, "Times New Roman", serif);
  letter-spacing: -0.02em;
  color: var(--mark-color);
  opacity: var(--mark-opacity);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
  user-select: none;
  pointer-events: none;
  transform: translateY(-0.02em) scale(calc(1 + var(--level) * 0.04));
  transition: opacity 600ms ease, color 600ms ease, transform 120ms ease-out;
}

/* ============================================================
   STATES : the two colours never change; tempo, brightness
   and scale carry the meaning.
   ============================================================ */

.vo[data-state="standby"] {
  --g1: var(--sage-deep);
  --glow: rgba(98, 122, 101, 0.26);
  --mark-opacity: 0.7;
  --angle-speed: 22s;
  --rim-speed: 9s;
  --breathe-speed: 5s;
  --breathe-amp: 0.025;
  --spec: 0.10;
  --base-scale: 0.94;
  --glow-scale: 0.95;
}

.vo[data-state="idle"] {
  --g1: var(--sage);
  --glow: rgba(98, 122, 101, 0.34);
  --mark-opacity: 0.85;
  --angle-speed: 16s;
  --rim-speed: 7s;
  --breathe-speed: 3.6s;
  --breathe-amp: 0.035;
  --base-scale: 0.90;
  --glow-scale: 1;
}

.vo[data-state="listening"] {
  --g1: var(--sage-lite);
  --rim-a: rgb(196, 216, 199);
  --rim-b: var(--sage-lite);
  --glow: rgba(146, 172, 149, 0.42);
  --mark-color: rgb(240, 247, 241);
  --mark-opacity: 1;
  --angle-speed: 9s;
  --rim-speed: 3.4s;
  --breathe-speed: 2.2s;
  --breathe-amp: 0.05;
  --rim-width: 6px;
  --spec: 0.20;
  --base-scale: 1.02;
  --glow-scale: 1.08;
}

.vo[data-state="processing"] {
  --g1: var(--sage-lite);
  --rim-a: rgb(214, 230, 216);
  --rim-b: var(--sage);
  --glow: rgba(98, 122, 101, 0.40);
  --mark-opacity: 0.55;      /* mark recedes while it thinks */
  --angle-speed: 2.4s;       /* gradient itself starts turning */
  --rim-speed: 1.15s;
  --blob-speed: 4s;
  --breathe-speed: 1.6s;
  --breathe-amp: 0.03;
  --base-scale: 0.97;
  --glow-scale: 1.04;
}

.vo[data-state="speaking"] {
  --g1: var(--sage-lite);
  --rim-a: rgb(226, 240, 228);
  --rim-b: var(--sage-lite);
  --glow: rgba(146, 172, 149, 0.44);
  --mark-color: rgb(244, 250, 245);
  --mark-opacity: 1;
  --angle-speed: 7s;
  --rim-speed: 2.6s;
  --blob-speed: 6s;
  --breathe-speed: 1.1s;
  --breathe-amp: 0.055;
  --spec: 0.22;
  --base-scale: 1;
  --glow-scale: 1.05;
}

.vo[data-state="muted"] {
  --g1: rgb(86, 90, 87);
  --rim-a: rgb(130, 136, 131);
  --rim-b: rgb(96, 101, 97);
  --glow: rgba(110, 115, 111, 0.16);
  --mark-opacity: 0.38;
  --angle-speed: 40s;
  --rim-speed: 14s;
  --breathe-amp: 0.012;
  --spec: 0.06;
  --base-scale: 0.86;
  --glow-scale: 0.8;
  filter: saturate(0.2);
}

/* ============================================================
   LABEL : letters fade/rise in one after another
   ============================================================ */

.vo-label {
  display: flex;
  justify-content: center;
  gap: 0.02em;
  font: 600 clamp(22px, 4.6vw, 40px) / 1.1 Archivo, Arial, sans-serif;
  letter-spacing: -0.02em;
  color: var(--vo-label-color, rgb(38, 46, 39));
  min-height: 1.2em;
  user-select: none;
}

.vo-label__ch {
  display: inline-block;
  white-space: pre;
  opacity: 0;
  transform: translateY(0.35em);
  filter: blur(6px);
  animation: vo-char-in 460ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/* ============================================================
   KEYFRAMES
   ============================================================ */

@keyframes vo-angle {
  to { --grad-angle: 450deg; }
}

@keyframes vo-spin {
  to { transform: rotate(360deg); }
}

@keyframes vo-breathe {
  0%, 100% { transform: scale(calc(1 - var(--breathe-amp))); }
  50%      { transform: scale(calc(1 + var(--breathe-amp))); }
}

@keyframes vo-morph {
  0%   { border-radius: 46% 54% 58% 42% / 52% 44% 56% 48%; }
  50%  { border-radius: 58% 42% 44% 56% / 44% 58% 42% 56%; }
  100% { border-radius: 42% 58% 52% 48% / 58% 42% 58% 42%; }
}

@keyframes vo-drift {
  0%   { transform: scale(var(--glow-scale)) translate3d(-2%, 1%, 0); }
  100% { transform: scale(calc(var(--glow-scale) * 1.06)) translate3d(2%, -2%, 0); }
}

@keyframes vo-char-in {
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* ============================================================
   ACCESSIBILITY
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .vo, .vo *, .vo-label__ch {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .vo-label__ch { opacity: 1; transform: none; filter: none; }
}

@media (prefers-color-scheme: dark) {
  .vo-label { color: var(--vo-label-color, rgb(232, 240, 233)); }
}

.agent-portal .vo{--size:150px}
@media(max-width:560px){.agent-portal .vo{--size:120px}}
