/* hero3d.css — 3D product heroes for voice / aibox / call.
 *
 * CSS transforms only. No three.js, no canvas, no WebGL, no images: a rotating ring and a fanned card stack
 * are transforms, and shipping a 600 KB 3D library to draw them would cost more than the whole page.
 * Everything here is GPU-composited (transform + opacity only), so it does not repaint or reflow.
 *
 * Two things deliberately NOT simplified away:
 *   - prefers-reduced-motion: all animation stops. Spinning rings are a real vestibular trigger.
 *   - the hero is decorative, so it is aria-hidden in the markup and carries no information the page
 *     does not also state in text.
 */

.scene3d { perspective: 900px; perspective-origin: 50% 45%; }
.spin3d  { transform-style: preserve-3d; }

/* ---- voice: an agent listening. Concentric rings orbiting a core, each on its own axis. ---- */
.voice-orb { position: relative; width: 260px; height: 260px; margin: 0 auto; transform-style: preserve-3d; }
.voice-orb .ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, .13);
  transform-style: preserve-3d;
}
.voice-orb .ring:nth-child(1) { animation: orbA 14s linear infinite; border-color: rgba(99, 102, 241, .45); }
.voice-orb .ring:nth-child(2) { inset: 26px; animation: orbB 11s linear infinite; border-color: rgba(168, 85, 247, .40); }
.voice-orb .ring:nth-child(3) { inset: 52px; animation: orbC  9s linear infinite; border-color: rgba(236, 72, 153, .35); }
@keyframes orbA { from { transform: rotateX(72deg) rotateZ(0deg);   } to { transform: rotateX(72deg) rotateZ(360deg); } }
@keyframes orbB { from { transform: rotateY(68deg) rotateZ(0deg);   } to { transform: rotateY(68deg) rotateZ(-360deg); } }
@keyframes orbC { from { transform: rotateX(24deg) rotateY(56deg) rotateZ(0deg); } to { transform: rotateX(24deg) rotateY(56deg) rotateZ(360deg); } }

/* The core "breathes" — it is the only thing on the page that says listening without a word of copy. */
.voice-orb .core {
  position: absolute; left: 50%; top: 50%; width: 74px; height: 74px; margin: -37px 0 0 -37px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #a5b4fc, #6366f1 45%, #7c3aed 75%);
  box-shadow: 0 0 44px 6px rgba(124, 58, 237, .45), inset 0 -8px 18px rgba(0, 0, 0, .35);
  animation: breathe 3.4s ease-in-out infinite;
}
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.11); } }

/* Language chips ride the outer orbit — the three-language claim, shown rather than listed. */
.voice-orb .chip {
  position: absolute; left: 50%; top: 50%; font-size: 11px; letter-spacing: .04em;
  padding: 3px 9px; border-radius: 999px; white-space: nowrap;
  background: rgba(10, 10, 15, .85); border: 1px solid rgba(255, 255, 255, .14); color: #c7d2fe;
  animation: chipOrbit 16s linear infinite;
}
.voice-orb .chip:nth-of-type(2) { animation-delay: -5.33s; }
.voice-orb .chip:nth-of-type(3) { animation-delay: -10.66s; }
/* Counter-rotate inside the orbit so the text never turns upside down. */
@keyframes chipOrbit {
  from { transform: rotate(0deg)   translateX(132px) rotate(0deg)   translate(-50%, -50%); }
  to   { transform: rotate(360deg) translateX(132px) rotate(-360deg) translate(-50%, -50%); }
}

/* ---- aibox: a message arrives and answers itself. Cards fanned in depth, the front one flips. ---- */
.box-stack { position: relative; width: 260px; height: 190px; margin: 0 auto; transform-style: preserve-3d;
  animation: stackSway 9s ease-in-out infinite; }
@keyframes stackSway {
  0%, 100% { transform: rotateX(14deg) rotateY(-19deg); }
  50%      { transform: rotateX(14deg) rotateY(-6deg); }
}
.box-stack .msg {
  position: absolute; inset: 0; border-radius: 14px; padding: 14px;
  background: rgba(255, 255, 255, .05); border: 1px solid rgba(255, 255, 255, .12);
  backdrop-filter: blur(2px); font-size: 12px; color: #cbd5e1;
  box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .9);
}
.box-stack .msg:nth-child(1) { transform: translateZ(-58px) translateY(20px) scale(.9);  opacity: .38; }
.box-stack .msg:nth-child(2) { transform: translateZ(-29px) translateY(10px) scale(.95); opacity: .62; }

/* The front card is two faces of one flipping plane: the question, then the automatic answer. */
.box-stack .flip { position: absolute; inset: 0; transform-style: preserve-3d; animation: flipCard 8s ease-in-out infinite; }
@keyframes flipCard {
  0%, 40%   { transform: rotateY(0deg); }
  55%, 92%  { transform: rotateY(180deg); }
  100%      { transform: rotateY(360deg); }
}
.box-stack .face { position: absolute; inset: 0; backface-visibility: hidden; border-radius: 14px; padding: 14px;
  border: 1px solid rgba(255, 255, 255, .16); box-shadow: 0 22px 46px -20px rgba(0, 0, 0, .95); }
.box-stack .face.q { background: linear-gradient(160deg, rgba(30, 30, 45, .96), rgba(17, 17, 28, .96)); }
.box-stack .face.a { background: linear-gradient(160deg, rgba(49, 30, 96, .96), rgba(24, 20, 52, .96));
  transform: rotateY(180deg); }
.box-stack .who { font-size: 10px; letter-spacing: .05em; text-transform: uppercase; color: #818cf8; margin-bottom: 6px; }
.box-stack .txt { font-size: 12.5px; line-height: 1.45; color: #e2e8f0; }
.box-stack .tag { position: absolute; left: 14px; bottom: 12px; font-size: 9.5px; letter-spacing: .05em;
  color: #a5b4fc; background: rgba(99, 102, 241, .16); border: 1px solid rgba(99, 102, 241, .3);
  padding: 2px 7px; border-radius: 999px; }

/* ---- call: the existing phone frame, given real depth instead of a new hero. ---- */
/* perspective() as a transform FUNCTION, so the frame needs no wrapper element around it. */
.phone3d { transform: perspective(1400px) rotateY(-15deg) rotateX(6deg);
  transition: transform .5s cubic-bezier(.2, .7, .3, 1); will-change: transform; }
.phone3d:hover { transform: perspective(1400px) rotateY(0deg) rotateX(0deg) scale(1.02); }

/* Any card picks up depth-on-hover by adding one class — perspective() is in the transform, so this needs
   no .scene3d parent and works wherever it is dropped. */
.tilt3d { transition: transform .35s cubic-bezier(.2, .7, .3, 1); }
.tilt3d:hover { transform: perspective(800px) translateY(-4px) rotateX(5deg) rotateY(-5deg); }

/* Vestibular safety: none of the above carries information, so stopping it costs the page nothing. */
@media (prefers-reduced-motion: reduce) {
  .voice-orb .ring, .voice-orb .core, .voice-orb .chip,
  .box-stack, .box-stack .flip { animation: none !important; }
  .box-stack { transform: rotateX(12deg) rotateY(-14deg); }
  .tilt3d:hover { transform: none; }
  .tilt3d, .phone3d { transition: none; }
  .phone3d, .phone3d:hover { transform: perspective(1400px) rotateY(-8deg); }
}

/* ---- generated hero art (Zemith / GPT Image 2) ----
 * The renders are on near-black, so a mask fades them into the page instead of ending on a hard rectangle
 * edge. width/height are on the <img> so the browser reserves the box and the headline never jumps (CLS).
 */
.hero-art { max-width: 620px; margin-inline: auto; }
.hero-art img {
  width: 100%; height: auto; border-radius: 18px; display: block;
  /* The gradient must reach transparent INSIDE the box or there is no fade at all: at the previous 120%
     extent the edges were still ~83% opaque, which read as a hard rectangle against the page. */
  -webkit-mask-image: radial-gradient(68% 68% at 50% 48%, #000 38%, transparent 100%);
          mask-image: radial-gradient(68% 68% at 50% 48%, #000 38%, transparent 100%);
}
