/* =============================================================================
   Blue Design Effects - v1
   Reusable, copy-pasteable classes for the brand's moving parts: the orb's
   ambient life and states, the named gradients, and the glass recipe.

   Built from the current Blue brand assets (the aurora orb, the Blue Studio
   login card and panels, the onboarding mockup). To be refined once the Figma
   is available.

   Depends on design-tokens.css. Import both:
     @import "design-tokens.css";
     @import "design-effects.css";

   Timings come from the motion tokens already defined (--orb-breathe, etc.).
   Everything animated here is fully disabled under prefers-reduced-motion.

   Taste rules (from Farhan, important):
     - The real orb (orb.mp4 / blue-icon) is the living mark. Never recolor it.
     - Do NOT add hard rings expanding out, and do NOT add a hard linear
       shine/sweep across the orb. The orb already moves. Every ambient layer
       here is soft, radial, and barely-there.
   ========================================================================== */

/* =============================================================================
   1. THE ORB
   Structure (keep the real video on top; ambient glow sits behind it):

     <div class="orb orb--idle">
       <span class="orb__glow" aria-hidden="true"></span>   (soft bloom behind)
       <span class="orb__tint" aria-hidden="true"></span>   (state color wash)
       <video class="orb__media" src="orb.mp4" autoplay loop muted playsinline></video>
     </div>

   State is set by swapping the modifier class on .orb:
     .orb--idle  .orb--listening  .orb--thinking  .orb--speaking
   ========================================================================== */

.orb {
  position: relative;
  display: grid;
  place-items: center;
  width: 172px;
  height: 172px;
  isolation: isolate;
}
.orb--md { width: 92px; height: 92px; }
.orb--sm { width: 48px; height: 48px; }

/* The real mark, always on top, always circular, never recolored. */
.orb__media {
  position: relative;
  z-index: 3;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  box-shadow:
    0 18px 44px -18px rgba(11, 46, 219, 0.55),
    0 0 0 1px rgba(136, 164, 255, 0.16);
}

/* Soft breathing bloom behind the orb. Radial, no edges, barely-there. */
.orb__glow {
  position: absolute;
  z-index: 1;
  width: 210%;
  height: 210%;
  border-radius: 50%;
  background: var(--gradient-orb-bloom);
  opacity: 0.5;
  pointer-events: none;
  will-change: opacity, transform;
}

/* Optional state color wash. Transparent by default; states tint it softly.
   This is a soft radial haze, NOT a ring. */
.orb__tint {
  position: absolute;
  z-index: 2;
  width: 150%;
  height: 150%;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    currentColor 0%,
    transparent 62%
  );
  color: transparent;   /* set per state below */
  opacity: 0;           /* raised per state below */
  mix-blend-mode: screen;
  pointer-events: none;
  will-change: opacity, transform;
}

/* --- ambient keyframes (all soft opacity/scale, no hard motion) --- */
@keyframes orb-breathe {
  0%, 100% { opacity: 0.42; transform: scale(1); }
  50%      { opacity: 0.74; transform: scale(1.05); }
}
@keyframes orb-breathe-listen {
  0%, 100% { opacity: 0.30; transform: scale(1); }
  50%      { opacity: 0.60; transform: scale(1.06); }
}
@keyframes orb-pulse-slow {
  0%, 100% { opacity: 0.34; transform: scale(1); }
  50%      { opacity: 0.52; transform: scale(1.03); }
}
@keyframes orb-swell {
  0%, 100% { opacity: 0.45; transform: scale(1); }
  40%      { opacity: 0.82; transform: scale(1.09); }
  70%      { opacity: 0.60; transform: scale(1.04); }
}

/* --- state treatments (distinct but all calm) --- */

/* Idle: the resting default. Gentle breathing bloom, no tint. */
.orb--idle .orb__glow {
  animation: orb-breathe var(--orb-breathe) var(--ease-standard) infinite;
}
.orb--idle .orb__tint { opacity: 0; }

/* Listening: attentive. A soft green-tinted haze breathing a touch quicker.
   Still soft and radial, never a ring. */
.orb--listening .orb__glow {
  animation: orb-breathe-listen 5.5s var(--ease-standard) infinite;
}
.orb--listening .orb__tint {
  color: var(--color-good);
  opacity: 0.28;
  animation: orb-breathe-listen 5.5s var(--ease-standard) infinite;
}

/* Thinking: quiet work. A slow, low-amplitude pulse. */
.orb--thinking .orb__glow {
  animation: orb-pulse-slow 3.6s var(--ease-standard) infinite;
}
.orb--thinking .orb__tint {
  color: var(--blue-300);
  opacity: 0.22;
  animation: orb-pulse-slow 3.6s var(--ease-standard) infinite;
}

/* Speaking: soft glow swell, in gentle waves. */
.orb--speaking .orb__glow {
  animation: orb-swell 2.8s var(--ease-standard) infinite;
}
.orb--speaking .orb__tint {
  color: var(--blue-100);
  opacity: 0.30;
  animation: orb-swell 2.8s var(--ease-standard) infinite;
}

/* Coarse-pointer devices (phones, tablets): the blurred glow/tint layers are NOT
   animated. Four of these opacity+scale animations on 210%-size layers cost about
   one CPU core on a Pixel while the feed sat idle (QA 2026-10-30); the WebGL orb
   itself still moves. Calm static halo; the state tint stays, just still. */
@media (pointer: coarse) {
  .orb__glow,
  .orb__tint {
    animation: none !important;
    will-change: auto;
  }
  .orb__glow { opacity: 0.5; transform: none; }
}

/* Reduced motion: the real orb video may remain, but every ADDED ambient
   animation stops. Glow settles to a calm static halo; tint hides. */
@media (prefers-reduced-motion: reduce) {
  .orb__glow,
  .orb__tint {
    animation: none !important;
  }
  .orb__glow { opacity: 0.5; transform: none; }
  .orb__tint { opacity: 0; }
}

/* =============================================================================
   2. GRADIENTS  (utility classes over the named tokens)
   ========================================================================== */

/* Primary button fill. SOLID cobalt (no gradient, operator call 2026-10-29).
   Depth = a faint 1px top inner highlight + a soft blue-tinted drop shadow.
   Pair with --glow-accent for a stronger lift on hero CTAs. */
.gradient-button {
  background: var(--gradient-button);
  color: var(--color-ink-on-accent);
  box-shadow: var(--button-sheen), 0 6px 18px rgba(11, 46, 219, 0.28);
}
.gradient-button:hover { background: var(--gradient-button-hover); }
.gradient-button:active { box-shadow: var(--button-sheen), 0 3px 10px rgba(11, 46, 219, 0.24); }

/* Soft page bloom. Put on the body or a full-bleed backdrop layer. */
.bg-bloom {
  background-color: var(--color-bg);
  background-image: var(--gradient-bloom);
  background-repeat: no-repeat;
}

/* The orb halo as a standalone decorative bloom (e.g. behind a hero mark). */
.gradient-orb-bloom { background: var(--gradient-orb-bloom); }

/* Accent glow blob - decorative only, low opacity, never behind text. */
.gradient-accent-glow { background: var(--gradient-accent-glow); }

/* Brand gradient as text fill (use rarely, for a single hero word). */
.gradient-text {
  background: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* =============================================================================
   3. GLASS
   Translucent surface + backdrop blur/saturate + 1px top hairline highlight
   + soft blue-tinted shadow. Solid fallback when backdrop-filter is missing.
   Works in both themes via the glass tokens. Use sparingly.
   ========================================================================== */

.glass {
  position: relative;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--glass-shadow);
}

/* 1px top hairline highlight via a masked gradient border (::before trick).
   A gradient fills the element, a mask punches out the interior so only a
   1px ring remains, then we fade it so the top edge is bright and it falls
   off downward. No hard line, no sweep. */
.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--glass-highlight);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

/* Fallback: if backdrop-filter is unavailable, use a solid surface so the
   content behind never shows through unreadably. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .glass {
    background: var(--glass-bg-solid);
  }
}
