/*
 * Rezolve homepage hero — plain-CSS port of rezolve-spa's Hero.module.scss
 * (Figma "Rezolve Design System" frame 1321315409, 1512 × 943) for the
 * [rezolve_hero] shortcode.
 *
 * The frame has no auto-layout: every element sits at a canvas coordinate,
 * so each canvas px value is multiplied by --rz-cq (1/1512 of the container
 * width) and the composition scales with the section. Needs container-type
 * on .rz-hero.
 *
 * Layers, back to front: BG Light → blurred arc → orb cluster + live orb →
 * glass speech bubble (transparent PNG) → headline → prompt chips → chat
 * input. The orb is this plugin's own live orb (the "Siri" conic-gradient
 * mesh, spun by hero.js) — the SPA copied it from here — reacting to
 * html[data-voice-state] set by the voice widget.
 */

/* Animatable angle for the live orb's conic gradients. Registration is
   global by nature. It must inherit: hero.js writes the angle on the orb
   element, and the gradients that read it sit on the orb's ::before. */
@property --rz-orb-angle {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}

.rz-hero {
  --rz-cq: calc(100cqw / 1512);
  /* The orb disc is 435 on this frame; the cluster geometry below was
     authored for a 364 disc, so it scales by 435/364 (the SPA's $k). */
  --rz-o: calc(var(--rz-cq) * 1.19505);
  /* Tablets (2026-10-05): the frame keeps 184 canvas px above the first
     chip for the site header, but the header is a fixed 132px and does not
     scale with the frame, so under ≈1184px it covered the top chips (seen
     on an iPad at 834: chips on the logo row). --rz-hero-nav-overlap is the
     header's height over the hero (inline script, hero-shortcode.php); the
     shortfall below "header + 40px" drops the whole composition and the
     stage grows by the same amount (40px: 16 read as cramped on a 768
     iPad, 2026-10-05; the canvas's own gap at 1512 is 52). 0 from ≈1413px
     up and where no header floats. Phones use the flow layout and ignore
     it. */
  --rz-t-shift: max(0px, calc(var(--rz-hero-nav-overlap, 0px) + 40px - 184 * var(--rz-cq)));
  --rz-page-bg: #f4f9ff;
  --rz-orb-base: #0099ff;
  --rz-orb-1: #3ac7ff;
  --rz-orb-2: #3af8ff;
  --rz-orb-3: #3a90ff;
  --rz-orb-4: #3a4bff;
  --rz-orb-5: #3ac4ff;
  --rz-accent: #0062d1;
  --rz-text-primary: #001442;
  --rz-font-display: "Red Hat Display", system-ui, sans-serif;
  --rz-font-text: "Red Hat Text", system-ui, sans-serif;

  position: relative;
  overflow: hidden;
  background: var(--rz-page-bg);
  container-type: inline-size;
  box-sizing: border-box;
}

.rz-hero *,
.rz-hero *::before,
.rz-hero *::after {
  box-sizing: border-box;
}

.rz-hero__stage {
  position: relative;
  width: 100%;
  /* 1512 × 943, plus the tablet shift (see --rz-t-shift). */
  height: calc(943 * var(--rz-cq) + var(--rz-t-shift));
}

/* ── Background ────────────────────────────────────────────────────────────
   BG Light.png then the blurred diagonal arc, both exported already clipped
   to the 1512 × 943 frame. Two classes: the theme's `.elementor img
   { height: auto }` outranks one, and once the stage is taller than the
   frame (tablet shift) the image stopped short and left a band of plain
   background under the tagline (2026-10-05). */
.rz-hero .rz-hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  pointer-events: none;
}

/* ── Glass speech bubble + orb (Group 427321761) ───────────────────────────
   The figure is the bubble's 930 × 928 box at (291, 0), so the orb and the
   voice mount keep their place in it when the layout reflows on phones. The
   orb disc (Blue orb group, 435 at canvas 539 / 163) is expressed as
   fractions of the box. */
.rz-hero__figure {
  position: absolute;
  left: calc(291 * var(--rz-cq));
  top: var(--rz-t-shift);
  width: calc(930 * var(--rz-cq));
  height: calc(928 * var(--rz-cq));
  /* No z-index: the orb (1) and glass (3) stack in the stage's context so
     the display headline (2) can sit between them. */
  pointer-events: none;
}

/* Frosted glass speech bubble (Glass_SpeechBubble_Frosted.png, 80% opacity
   baked in), exported clipped to the figure box. */
.rz-hero__bubble {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  z-index: 3;
  transform-origin: 50% 42%;
  transition: scale 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ── Orb ───────────────────────────────────────────────────────────────────
   Frame 1321315295: five blurred ellipses clipped to the disc, then the whole
   frame blurred 30px — a soft-edged disc, not a wide halo. Offsets are
   relative to the cluster origin, in --rz-o (see .rz-hero). */
.rz-hero__orb {
  position: absolute;
  left: 26.6667%;   /* (539 − 291) / 930 */
  top: 17.5647%;    /* 163 / 928 */
  width: 46.7742%;  /* 435 / 930 */
  aspect-ratio: 1;
  z-index: 1;
  pointer-events: none;
  transform-origin: 50% 50%;
  transition: scale 0.45s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.rz-hero__orb-cluster {
  position: absolute;
  inset: 0;
  filter: blur(calc(30 * var(--rz-o)));
}

.rz-hero__orb-cluster span {
  position: absolute;
  border-radius: 50%;
  filter: blur(calc(54 * var(--rz-o)));
}

.rz-hero__orb-clip {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  /* Safari on iOS does not clip blurred children to a rounded overflow box:
     the blobs filled the whole square and the disc showed as a soft square
     with blue corners behind the bubble (iPhone, 2026-10-02). clip-path and
     a circular mask are both honoured there; in other browsers they are the
     same circle the border-radius already cut. */
  -webkit-clip-path: circle(50%);
  clip-path: circle(50%);
  -webkit-mask-image: radial-gradient(circle closest-side, #000 99%, transparent 100%);
  mask-image: radial-gradient(circle closest-side, #000 99%, transparent 100%);
  background: var(--rz-orb-base);
}

.rz-hero__blob-1 { left: calc(129 * var(--rz-o)); top: calc(-24 * var(--rz-o)); width: calc(246 * var(--rz-o)); height: calc(368 * var(--rz-o)); background: var(--rz-orb-1); }
.rz-hero__blob-2 { left: calc(-23 * var(--rz-o)); top: calc(95 * var(--rz-o)); width: calc(371 * var(--rz-o)); height: calc(392 * var(--rz-o)); background: var(--rz-orb-2); }
.rz-hero__blob-3 { left: calc(-73 * var(--rz-o)); top: calc(-113 * var(--rz-o)); width: calc(271 * var(--rz-o)); height: calc(269 * var(--rz-o)); background: var(--rz-orb-3); }
.rz-hero__blob-4 { left: calc(67 * var(--rz-o)); top: calc(14 * var(--rz-o)); width: calc(332 * var(--rz-o)); height: calc(337 * var(--rz-o)); background: var(--rz-orb-4); }
.rz-hero__blob-5 { left: calc(64 * var(--rz-o)); top: calc(-106 * var(--rz-o)); width: calc(274 * var(--rz-o)); height: calc(291 * var(--rz-o)); background: var(--rz-orb-5); }

/* ── Live orb (the "Siri" conic-gradient technique), frosted variant ───────
   Over the cluster, filling the disc. The colour mesh, sheen, state rules
   and hero.js spin are unchanged from the previous hero; only the geometry
   moved with the design. */
.rz-hero__lens-orb {
  --rz-orb-speed: 1;
  --rz-orb-active-opacity: 0.9;
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-areas: "stack";
  border-radius: 50%;
  overflow: hidden;
  /* As on the cluster's clip: iOS Safari needs clip-path to keep the blurred
     mesh inside the disc. */
  -webkit-clip-path: circle(50%);
  clip-path: circle(50%);
  isolation: isolate;
  pointer-events: none;
  opacity: 0.8;
  mix-blend-mode: screen;
  -webkit-mask-image: radial-gradient(circle, #000 55%, transparent 100%);
  mask-image: radial-gradient(circle, #000 55%, transparent 100%);
  transition: opacity 0.6s ease, transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.rz-hero__lens-orb::before,
.rz-hero__lens-orb::after,
.rz-hero__lens-orb > span {
  content: "";
  display: block;
  grid-area: stack;
  width: 100%;
  height: 100%;
  border-radius: 50%;
}

/* Colour mesh. */
.rz-hero__lens-orb::before {
  background:
    conic-gradient(from calc(var(--rz-orb-angle) * 2) at 25% 70%, #3a4bff, transparent 20% 80%, #3a4bff),
    conic-gradient(from calc(var(--rz-orb-angle) * 2) at 45% 75%, #0099ff, transparent 30% 60%, #0099ff),
    conic-gradient(from calc(var(--rz-orb-angle) * -3) at 80% 20%, #3af8ff, transparent 40% 60%, #3af8ff),
    conic-gradient(from calc(var(--rz-orb-angle) * 1.5) at 60% 35%, #3ac7ff, transparent 25% 75%, #3ac7ff),
    conic-gradient(from calc(var(--rz-orb-angle) * 2) at 15% 5%, #0099ff, transparent 10% 90%, #0099ff),
    conic-gradient(from calc(var(--rz-orb-angle) * 1) at 20% 80%, #6a5cff, transparent 10% 90%, #6a5cff),
    conic-gradient(from calc(var(--rz-orb-angle) * -2) at 85% 10%, #3a4bff, transparent 20% 80%, #3a4bff),
    #0099ff;
  filter: blur(calc(28 * var(--rz-o))) contrast(1.4) saturate(1.35);
  /* Keyframe fallback only; with hero.js running (html.rz-orb-js) the angle
     is integrated in script so speed changes ramp instead of jumping. */
  animation: rz-orb-rotate calc(24s / var(--rz-orb-speed)) linear infinite;
}

html.rz-orb-js .rz-hero__lens-orb::before {
  animation: none;
}

/* Frosted: no crisp rim. */
.rz-hero__lens-orb::after {
  box-shadow: none;
}

/* Drifting specular sheen, softened. */
.rz-hero__lens-orb > span {
  background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.22), transparent 45%);
  filter: blur(calc(28 * var(--rz-o)));
  mix-blend-mode: screen;
  /* Fixed duration: tying it to --rz-orb-speed re-timed the animation on
     every speed change and made the sheen jump. */
  animation: rz-orb-drift 14s ease-in-out infinite alternate;
}

@keyframes rz-orb-rotate {
  to { --rz-orb-angle: 360deg; }
}

@keyframes rz-orb-drift {
  from { transform: translate(-6%, -4%) scale(1.05); }
  to { transform: translate(7%, 6%) scale(1.12); }
}

@keyframes rz-orb-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

/* Voice-agent states, set on <html> by the widget. */
html[data-voice-state="listening"] .rz-hero__lens-orb {
  --rz-orb-speed: calc(3 + var(--rz-user-level, 0) * 5);
  opacity: calc(var(--rz-orb-active-opacity, 1) + var(--rz-user-level, 0) * 0.2);
}

html[data-voice-state="bot-speaking"] .rz-hero__lens-orb {
  --rz-orb-speed: 8;
  opacity: 1;
  animation: rz-orb-breathe 1.1s ease-in-out infinite;
}

/* ── Display headline ("Let’s talk shop") ──────────────────────────────────
   Red Hat Display 700, centred across the canvas with its baseline at
   ≈ 420. It sits above the orb and under the frosted glass. The fill is a
   radial gradient centred on the orb (canvas 756, 380): blue where the
   bubble covers the letters, navy outside it, so "Let" and "hop" read solid
   and the middle reads as seen through the glass. */
.rz-hero .rz-hero__headline {
  position: absolute;
  left: 0;
  top: calc(300 * var(--rz-cq) + var(--rz-t-shift));
  width: 100%;
  margin: 0;
  padding: 0;
  z-index: 2;
  font-family: var(--rz-font-display);
  font-weight: 700;
  font-size: calc(162 * var(--rz-cq));
  line-height: 1;
  letter-spacing: -0.02em;
  text-align: center;
  white-space: nowrap;
  color: var(--rz-text-primary);
  background-image: radial-gradient(
    circle calc(300 * var(--rz-cq)) at 50% calc(80 * var(--rz-cq)),
    #4f93ff 0%,
    #2f5fe8 72%,
    var(--rz-text-primary) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  pointer-events: none;
}

/* ── Tagline ───────────────────────────────────────────────────────────────
   Red Hat Display 700 26/33, 3% tracking, centred, bottom-aligned in its
   box. With the display headline it drops to a 16px line over the chat
   input (top ≈ 756); on its own (headline="") it keeps the design's
   1173 × 33 slot at (170, 355) across the bubble. */
.rz-hero .rz-hero__title {
  position: absolute;
  left: calc(170 * var(--rz-cq));
  /* The box is one line tall and keeps the design's bottom edge (355 + 33).
     Its height used to scale with the canvas while the type floored, so on
     tablets the line overflowed a box shorter than itself and the gradient
     fill, which paints only inside the box, cut the glyph tops off
     (2026-10-05). */
  top: calc(388 * var(--rz-cq) + var(--rz-t-shift) - max(24px, calc(33 * var(--rz-cq))));
  width: calc(1173 * var(--rz-cq));
  height: max(24px, calc(33 * var(--rz-cq)));
  margin: 0;
  padding: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 3;
  font-family: var(--rz-font-display);
  font-weight: 700;
  /* Canvas-scaled, floored so tablets don't get 15px type. */
  font-size: max(18px, calc(26 * var(--rz-cq)));
  line-height: max(24px, calc(33 * var(--rz-cq)));
  letter-spacing: 0.03em;
  text-align: center;
  white-space: nowrap;
  pointer-events: none;
  background-image: linear-gradient(90deg, #00317f 0%, #0042d2 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.rz-hero .rz-hero__headline ~ .rz-hero__title {
  /* Bottom edge at 752 + 24; see above. */
  top: calc(776 * var(--rz-cq) + var(--rz-t-shift) - max(20px, calc(24 * var(--rz-cq))));
  height: max(20px, calc(24 * var(--rz-cq)));
  font-size: max(14px, calc(16 * var(--rz-cq)));
  line-height: max(20px, calc(24 * var(--rz-cq)));
  letter-spacing: 0.01em;
}

/* ── Voice-agent mount ─────────────────────────────────────────────────────
   Same disc as the orb, above the glass and the prompts so a click lands on
   the bubble. Inert until the widget portals a launcher into it. */
.rz-hero__voice-mount {
  position: absolute;
  left: 26.6667%;
  top: 17.5647%;
  width: 46.7742%;
  aspect-ratio: 1;
  border-radius: 50%;
  z-index: 5;
  pointer-events: none;
}

.rz-hero__voice-mount > * {
  pointer-events: auto;
}

/* The launcher paints a large white equalizer over the orb while the agent
   speaks; on this design that lands on the headline, so it stays off — the
   orb itself is the affordance. */
.rz-hero__figure .rzlv-hero-launcher__eq {
  display: none;
}

/* Hover affordance once a launcher is in the mount: the bubble swells. */
.rz-hero__stage:has(.rz-hero__voice-mount:hover) .rz-hero__bubble,
.rz-hero__stage:has(.rz-hero__voice-mount:hover) .rz-hero__orb {
  scale: 1.045;
}

/* While the widget's bubble is travelling, the hero's own steps aside so
   there is exactly one bubble on screen. */
html[data-voice-travel="on"] .rz-hero__bubble,
html[data-voice-travel="on"] .rz-hero__orb,
html[data-voice-travel="on"] .rz-hero__voice-mount {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}

/* ── Prompt chips ("Agent") ────────────────────────────────────────────────
   Hug × 40, padding 10/16, radius 43, white 60% with a 1px white border and
   a long soft shadow. Label is the Headline Blue Gradient across the text.
   Anchored on .rz-hero so theme button rules can't restyle them. */
.rz-hero .rz-hero__prompt {
  position: absolute;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: max(10px, calc(12 * var(--rz-cq)));
  width: auto;
  min-width: 0;
  min-height: 0;
  height: max(36px, calc(40 * var(--rz-cq)));
  margin: 0;
  padding: 0 max(14px, calc(16 * var(--rz-cq)));
  border: 1px solid #fff;
  border-radius: 43px;
  background: rgba(255, 255, 255, 0.6);
  box-shadow: 0 19px 29px rgba(30, 31, 34, 0.15);
  text-transform: none;
  text-decoration: none;
  letter-spacing: 0;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s ease, box-shadow 0.2s ease, translate 0.2s ease;
}

.rz-hero .rz-hero__prompt:hover,
.rz-hero .rz-hero__prompt:focus-visible {
  background: rgba(255, 255, 255, 0.85);
  translate: 0 -2px;
}

.rz-hero .rz-hero__prompt:focus-visible {
  outline: 2px solid var(--rz-accent);
  outline-offset: 2px;
}

/* While a typed question is in flight (hero[data-rz-busy], see hero.js). */
.rz-hero[data-rz-busy] .rz-hero__prompt {
  cursor: default;
  opacity: 0.6;
  translate: none;
}

.rz-hero__prompt-label {
  font-family: var(--rz-font-text);
  font-weight: 500;
  font-size: max(13px, calc(14 * var(--rz-cq)));
  line-height: max(18px, calc(20 * var(--rz-cq)));
  background-image: linear-gradient(90deg, #02188a 0%, #005ec9 50%, #18b2ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* "arrow circle" (42 × 42, #BED0E2) — in the component but not visible in
   the design's rest state, so it is a hover/focus reveal. */
.rz-hero__prompt-arrow {
  display: none;
  width: max(24px, calc(30 * var(--rz-cq)));
  height: max(24px, calc(30 * var(--rz-cq)));
  margin-right: max(-8px, calc(-8 * var(--rz-cq)));
  border-radius: 50%;
  background: #bed0e2;
  align-items: center;
  justify-content: center;
}

.rz-hero__prompt-arrow svg {
  width: 60%;
  height: 60%;
}

.rz-hero .rz-hero__prompt:hover .rz-hero__prompt-arrow,
.rz-hero .rz-hero__prompt:focus-visible .rz-hero__prompt-arrow {
  display: inline-flex;
}

/* The right-hand chips hang from the right edge (their canvas right gaps:
   1512 − (1069 + 277) and 1512 − (1037 + 228) at the design's labels), so
   on tablets, where the label keeps its 13px floor while the frame shrinks,
   they grow towards the bubble instead of off the screen (834px iPad: the
   top-right chip ran 12px past the edge, 2026-10-05). Identical on desktop. */
.rz-hero__prompt--1 { left: calc(216 * var(--rz-cq)); top: calc(184 * var(--rz-cq) + var(--rz-t-shift)); }
.rz-hero__prompt--2 { right: max(16px, calc(166 * var(--rz-cq))); top: calc(212 * var(--rz-cq) + var(--rz-t-shift)); }
.rz-hero__prompt--3 { left: calc(198 * var(--rz-cq)); top: calc(503 * var(--rz-cq) + var(--rz-t-shift)); }
.rz-hero__prompt--4 { right: max(16px, calc(247 * var(--rz-cq))); top: calc(491 * var(--rz-cq) + var(--rz-t-shift)); }

/* ── Chat input (Prompt Window) ────────────────────────────────────────────
   272 × 36.47 at (620.5, 768): white pill, 1px gradient border, padding
   5 / 6 / 5 / 16, gap 9, soft drop shadow. */
.rz-hero .rz-hero__chat {
  --rz-send-bg: #e2ebf5;
  --rz-send-fg: #929292;
  position: absolute;
  /* (620.5, 768), 272 wide: its centre is the canvas centre, so anchor there
     and let the floored width grow symmetrically on narrow screens. */
  left: 50%;
  top: calc(768 * var(--rz-cq) + var(--rz-t-shift));
  width: max(240px, calc(272 * var(--rz-cq)));
  height: max(36px, calc(36.47 * var(--rz-cq)));
  transform: translateX(-50%);
  z-index: 4;
  display: flex;
  align-items: center;
  gap: max(8px, calc(9 * var(--rz-cq)));
  margin: 0;
  padding: 5px 6px 5px max(14px, calc(16 * var(--rz-cq)));
  border-radius: 999px;
  border: 1.5px solid transparent;
  background:
    linear-gradient(#fff, #fff) padding-box,
    linear-gradient(90deg, #c9d4ff, #f4f4f4) border-box;
  box-shadow: 0 3.04px 7.67px rgba(0, 0, 0, 0.15);
  font-family: var(--rz-font-text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Under the display headline's tagline. */
.rz-hero .rz-hero__headline ~ .rz-hero__chat {
  top: calc(794 * var(--rz-cq) + var(--rz-t-shift));
}

/* Chat Input, State = Focused: accent border with a soft glow. */
.rz-hero .rz-hero__chat:focus-within {
  background: #fff;
  border-color: var(--rz-accent);
  box-shadow: 0 0 8px rgba(0, 98, 209, 0.25);
}

/* Filled: the send disc turns accent. */
.rz-hero .rz-hero__chat--ready {
  --rz-send-bg: #0062d1;
  --rz-send-fg: #ffffff;
}

/* Disabled (a turn in flight): the whole control fades. */
.rz-hero .rz-hero__chat--busy {
  opacity: 0.55;
  box-shadow: 0 3.04px 7.67px rgba(0, 0, 0, 0.08);
}

/* Error: red border + glow, red placeholder copy, red send disc. */
.rz-hero .rz-hero__chat--error {
  --rz-send-bg: #dc2626;
  --rz-send-fg: #ffffff;
  background: #fff;
  border-color: #dc2626;
  box-shadow: 0 0 8px rgba(220, 38, 38, 0.2);
}

.rz-hero .rz-hero__chat--error .rz-hero__chat-input::placeholder {
  color: #dc2626;
}

.rz-hero .rz-hero__chat-input {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-family: inherit;
  font-weight: 500;
  font-size: max(12px, calc(12 * var(--rz-cq)));
  line-height: max(20px, calc(20 * var(--rz-cq)));
  color: var(--rz-text-primary);
}

.rz-hero .rz-hero__chat-input::placeholder {
  color: #737373;
  opacity: 1;
}

.rz-hero .rz-hero__chat-input:focus {
  outline: none;
  box-shadow: none;
}

.rz-hero__chat-icons {
  display: inline-flex;
  align-items: center;
  gap: max(4px, calc(4.56 * var(--rz-cq)));
  flex: 0 0 auto;
}

.rz-hero .rz-hero__chat-button {
  display: inline-flex;
  width: max(26px, calc(27.35 * var(--rz-cq)));
  height: max(26px, calc(27.35 * var(--rz-cq)));
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  cursor: pointer;
}

.rz-hero .rz-hero__chat-button:disabled {
  cursor: default;
}

.rz-hero .rz-hero__chat-button:focus-visible {
  outline: 2px solid var(--rz-accent);
  outline-offset: 2px;
}
/* The theme draws a 3px crimson outline on any focused button; after a
   mouse click that ring sat on the pill's icons (seen on Stop, 2026-10-05).
   Keyboard focus keeps the accent ring above; mouse focus shows none. */
.rz-hero .rz-hero__chat-button:focus:not(:focus-visible) {
  outline: none;
  box-shadow: none;
}

.rz-hero .rz-hero__chat-button svg {
  width: 100%;
  height: 100%;
}

.rz-hero__chat-send-bg { fill: var(--rz-send-bg); transition: fill 0.15s ease; }
.rz-hero__chat-send-arrow { stroke: var(--rz-send-fg); transition: stroke 0.15s ease; }

/* Voice button: waveform at rest, a stop square while the voice session is
   on (html[data-voice-state] ≠ idle) — the same button ends it. */
.rz-chat-voice__stop { display: none; }
html[data-voice-state="connecting"] .rz-chat-voice__wave,
html[data-voice-state="listening"] .rz-chat-voice__wave,
html[data-voice-state="muted"] .rz-chat-voice__wave,
html[data-voice-state="bot-speaking"] .rz-chat-voice__wave { display: none; }
html[data-voice-state="connecting"] .rz-chat-voice__stop,
html[data-voice-state="listening"] .rz-chat-voice__stop,
html[data-voice-state="muted"] .rz-chat-voice__stop,
html[data-voice-state="bot-speaking"] .rz-chat-voice__stop { display: block; }

/* Muted (the ■ pressed, 2026-10-04): mic and the assistant's voice are both
   off, session kept — the disc goes pale red and the square red, matching
   the dock's button (AssistantDock VoiceIcon, MUTED_SQUARE / MUTED_DISC). */
html[data-voice-state="muted"] .rz-hero__chat-voice svg > rect:first-of-type { fill: #FFE1E3; }
html[data-voice-state="muted"] .rz-chat-voice__stop { fill: #E5484D; }

/* ── Controls A/B (?rzlv_controls=split, 2026-10-05) ──────────────────────
   split: while voice is live the pill is [send] [mute] [stop]. The Mute
   button (hidden otherwise) mutes mic + the assistant's voice and goes red
   when muted; the right button is a Stop that ends the session. The single
   variant never shows the Mute button. Mirrors the dock (AssistantDock
   MuteIcon / StopIcon). */
.rz-hero .rz-hero__chat-mute { display: none; }
.rz-chat-mute__slash { display: none; }
html[data-rz-controls="split"][data-voice-state="connecting"] .rz-hero__chat-mute,
html[data-rz-controls="split"][data-voice-state="listening"] .rz-hero__chat-mute,
html[data-rz-controls="split"][data-voice-state="muted"] .rz-hero__chat-mute,
html[data-rz-controls="split"][data-voice-state="bot-speaking"] .rz-hero__chat-mute { display: inline-flex; }
html[data-rz-controls="split"][data-voice-state="muted"] .rz-chat-mute__bg { fill: #FFE1E3; }
html[data-rz-controls="split"][data-voice-state="muted"] .rz-chat-mute__fg { fill: #E5484D; }
/* Muted: the struck-through mic replaces the plain one (Phosphor glyphs). */
html[data-rz-controls="split"][data-voice-state="muted"] .rz-chat-mute__on { display: none; }
html[data-rz-controls="split"][data-voice-state="muted"] .rz-chat-mute__slash { display: block; }
/* split: the right button is Stop (ends the session), not the mute — it
   keeps its blue in every live state, muted included. */
html[data-rz-controls="split"][data-voice-state="muted"] .rz-hero__chat-voice svg > rect:first-of-type { fill: url(#rz-hero-voice-bg); }
html[data-rz-controls="split"][data-voice-state="muted"] .rz-chat-voice__stop { fill: #0062D1; }

/* ── Tablets (768–1180): chips ────────────────────────────────────────────
   The chips keep their type floor while the frame shrinks, so on a 768
   iPad they were half the bubble wide, 50px apart across it, and almost
   half the headline's height (desktop: a quarter of the bubble, 560px
   apart; 2026-10-05). Here they drop to 12px type in a 34px pill (still a
   finger-sized target) and their outer edges run on a straight line from
   a 23px gutter at 768 to the canvas's own edges at 1180 (216/198 left,
   166/247 right, times cq), so each chip covers the bubble by about the
   desktop quarter all the way down and nothing jumps at the breakpoint.
   Vertical places are the canvas's (plus the shift). */
@media (min-width: 768px) and (max-width: 1180px) {
  .rz-hero .rz-hero__prompt {
    height: 34px;
    padding: 0 13px;
  }

  .rz-hero__prompt-label {
    font-size: 12px;
    line-height: 16px;
  }

  .rz-hero__prompt--1 { left: calc(35.4cqw - 249px); }
  .rz-hero__prompt--3 { left: calc(32cqw - 223px); }
  .rz-hero__prompt--2 { right: calc(25.7cqw - 174.6px); }
  .rz-hero__prompt--4 { right: calc(41cqw - 292px); }
}

/* ── Mobile: flow layout (Figma "Text input" › iPhone 17 - 1, 402 × 874) ──
   Stacks headline → bubble → chips → input. Canvas values: headline frame
   at 161 (27 under the 134 nav), padding 10/16, Red Hat Display 700 32/40,
   2% tracking; bubble group 296 × 317 at 278; chips 40 tall, gap 12, from
   578; input 272 × 36.47 with 16 above and 24 below, flush with the frame
   bottom. The nav is the theme's, so the stage starts 27px under it — when
   that nav floats over the page (fixed) the hero starts underneath it, and
   --rz-hero-nav-overlap (set by the hero's inline script) is the part of
   the hero it covers. */
@media (max-width: 767px) {
  /* The canvas units (cqw) are for the desktop composition; the phone layout
     is plain flow. As a size container the hero's height was mis-measured by
     the page builder's flex wrapper — 126px short, so the next section began
     on top of the tagline and the input (2026-10-02). Without a container,
     cqw falls back to the viewport width, which the full-bleed hero spans.
     Sizes: the Figma frame is 402 wide; on narrower phones its fixed sizes
     (44px+ headline, 296 bubble, 40px chips edge to edge) filled the screen,
     so the headline, the bubble and the chip text scale with the viewport. */
  .rz-hero {
    container-type: normal;
    --rz-m-head: clamp(34px, 11vw, 48px);
    --rz-m-bubble: min(250px, 64vw);
    --rz-m-top: calc(var(--rz-hero-nav-overlap, 0px) + 20px);
  }

  .rz-hero__stage {
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding: var(--rz-m-top) 0 32px;
  }

  .rz-hero .rz-hero__title {
    position: relative;
    left: auto;
    top: auto;
    width: 100%;
    height: auto;
    display: block;
    order: 1;
    padding: 10px 16px;
    font-size: 32px;
    line-height: 40px;
    letter-spacing: 0.02em;
    white-space: normal;
  }

  /* Display headline leads the stack; the tagline moves down to sit over
     the chat input, as on desktop. */
  .rz-hero .rz-hero__headline {
    position: relative;
    top: auto;
    order: 1;
    padding: 0 16px;
    font-size: var(--rz-m-head);
    line-height: 1.1;
    white-space: normal;
    /* Above the bubble here, not across it: solid navy. */
    background-image: none;
    -webkit-text-fill-color: currentColor;
  }

  .rz-hero .rz-hero__headline ~ .rz-hero__title {
    order: 4;
    top: auto;
    height: auto;
    margin-top: 20px;
    padding: 0 16px;
    font-size: 14px;
    line-height: 20px;
  }

  .rz-hero .rz-hero__headline ~ .rz-hero__chat {
    top: auto;
    margin-top: 12px;
  }

  .rz-hero__figure {
    position: relative;
    left: auto;
    top: auto;
    width: var(--rz-m-bubble);
    height: auto;
    aspect-ratio: 930 / 928;
    order: 2;
    /* 278 − (161 + 140) = −23 on a 296 bubble: the bubble box tucks under
       the headline frame. */
    margin-top: -18px;
  }

  .rz-hero__voice-mount {
    display: none;
  }

  /* Figma's mobile background is a 1243-wide glow centred on the bubble
     (Group 427321764 at −417 / −305; 1243 / 296 = 4.2 bubbles wide); scale
     the arc export to that and centre it on the bubble box instead of
     covering the stage. Two classes: the theme's `img { max-width: 100% }`
     outranked the single one and squeezed the glow to the screen width — a
     184px strip whose hard edges showed as seams across the bubble. */
  .rz-hero .rz-hero__bg {
    inset: auto;
    left: 50%;
    top: var(--rz-m-top);
    width: calc(var(--rz-m-bubble) * 4.2);
    height: auto;
    max-width: none;
    object-fit: unset;
    /* Centre on the bubble: one headline line, the tuck, half the bubble. */
    transform: translate(-50%, calc(var(--rz-m-head) * 1.1 - 18px + var(--rz-m-bubble) / 2 - 50%));
  }

  .rz-hero .rz-hero__prompt {
    position: static;
    order: 3;
    gap: 12px;
    height: 36px;
    padding: 0 14px;
    margin: 8px 0 0;
    /* A 16px gutter either side, as the headline and the input have. */
    max-width: calc(100% - 32px);
  }

  /* 578 − (278 + 295): first chip sits just under the bubble box. */
  .rz-hero .rz-hero__prompt--1 {
    margin-top: 5px;
  }

  .rz-hero__prompt-label {
    font-size: clamp(12px, 3.6vw, 14px);
    line-height: 18px;
  }

  .rz-hero__prompt-arrow {
    display: none !important;
  }

  .rz-hero .rz-hero__chat {
    position: relative;
    left: auto;
    top: auto;
    transform: none;
    order: 5;
    width: 272px;
    max-width: calc(100% - 32px);
    height: 36.47px;
    /* 24 gap + the wrapper's 16 top padding. */
    margin-top: 40px;
    gap: 9px;
    padding: 5px 6px 5px 16px;
  }

  /* iOS Safari zooms the whole page into a focused field whose font is
     under 16px, and stays zoomed. The field's real font is 16px and it is
     scaled back down to look 13px: laid out 1 / 0.8125 times wider than
     its room (the pill minus the two buttons, 27.35 × 2 + 4.56, and the
     9px gap), with the negative margin handing the surplus back. */
  .rz-hero .rz-hero__chat-input {
    --rz-in-scale: 0.8125;
    --rz-in-room: calc(100% - 68.3px);
    flex: 0 0 auto;
    width: calc(var(--rz-in-room) / var(--rz-in-scale));
    margin-right: calc(var(--rz-in-room) / var(--rz-in-scale) * (var(--rz-in-scale) - 1));
    font-size: 16px;
    line-height: 24px;
    transform: scale(var(--rz-in-scale));
    transform-origin: 0 50%;
  }

  /* Split controls while voice is live: three buttons (send, mute, stop)
     — 27.35 × 3 + 4.56 × 2 + the 9px gap — so the field gives up that
     much, or the Stop sat outside the pill (2026-10-06). */
  html[data-rz-controls="split"][data-voice-state="connecting"] .rz-hero .rz-hero__chat-input,
  html[data-rz-controls="split"][data-voice-state="listening"] .rz-hero .rz-hero__chat-input,
  html[data-rz-controls="split"][data-voice-state="muted"] .rz-hero .rz-hero__chat-input,
  html[data-rz-controls="split"][data-voice-state="bot-speaking"] .rz-hero .rz-hero__chat-input {
    --rz-in-room: calc(100% - 100.2px);
    /* Restated: Chrome kept the old width when only the variable changed. */
    width: calc(var(--rz-in-room) / var(--rz-in-scale));
    margin-right: calc(var(--rz-in-room) / var(--rz-in-scale) * (var(--rz-in-scale) - 1));
  }

  .rz-hero__chat-icons {
    gap: 4.56px;
  }

  .rz-hero .rz-hero__chat-button {
    width: 27.35px;
    height: 27.35px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rz-hero__bubble,
  .rz-hero__orb,
  .rz-hero .rz-hero__prompt,
  .rz-hero__lens-orb::before,
  .rz-hero__lens-orb > span,
  .rz-hero__lens-orb {
    transition: none;
    animation: none;
  }
}

/* ── Voice-agent hero launcher ─────────────────────────────────────────────
   The widget portals this into #voice-hero-mount when its launcher mode is
   "hero". It lives in the page, outside the widget's shadow root, so its
   styles ship here. The mount is the 364px orb disc; this fills it and only
   adds the hit area, equalizer and caption — the orb's colour and motion are
   the hero's own live orb reacting to html[data-voice-state]. */
.rzlv-hero-launcher {
  position: absolute;
  inset: 0;
  container-type: size;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Inter", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.rzlv-hero-launcher *,
.rzlv-hero-launcher *::before,
.rzlv-hero-launcher *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Anchored on the mount's id so theme button rules (padding, border,
   min-width, display) cannot collapse the hit area — on the Rezolve theme
   they shrank it to a 50px pill with a pink border. */
#voice-hero-mount .rzlv-hero-launcher__hit {
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  color: inherit;
  font: inherit;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}

#voice-hero-mount .rzlv-hero-launcher__hit:hover,
#voice-hero-mount .rzlv-hero-launcher__hit:focus {
  background: transparent;
  border: 0;
  box-shadow: none;
}

#voice-hero-mount .rzlv-hero-launcher__hit:hover {
  transform: scale(1.03);
}

#voice-hero-mount .rzlv-hero-launcher__hit:active {
  transform: scale(0.98);
}

#voice-hero-mount .rzlv-hero-launcher__hit:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.9);
  outline-offset: 6px;
}

#voice-hero-mount .rzlv-hero-launcher__hit:disabled {
  cursor: wait;
  opacity: 1;
}

/* Voice bars sized off the mount disc via container units:
   364px orb → ~95px tall bars, 16px wide, 11px apart. */
.rzlv-hero-launcher__eq {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3cqw;
  height: 26cqw;
}

/* Each bar is a full-height pill scaled on Y from its centre. Two modes:
   - live (html[data-voice-audio="on"]): the widget publishes per-band audio
     levels as --rz-bar-1..5 on the hero section (.rz-hero — not on <html>,
     see voiceLevels.ts) and each bar follows its band — the
     bot's voice while it speaks, the mic while listening;
   - fallback: no audio yet — each bar runs its own animation with a different
     length and curve, so they never line up into a left-to-right wave. */
.rzlv-hero-launcher__eq > span {
  display: block;
  width: 4.5cqw;
  height: 100%;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.95);
  box-shadow: 0 0 12px rgba(255, 255, 255, 0.45);
  transform-origin: center;
  transform: scaleY(0.25);
  will-change: transform;
}

.rzlv-hero-launcher__eq > span:nth-child(1) { animation: rzlv-bar-a 0.94s ease-in-out -0.30s infinite alternate; }
.rzlv-hero-launcher__eq > span:nth-child(2) { animation: rzlv-bar-b 0.71s ease-in-out -0.10s infinite alternate; }
.rzlv-hero-launcher__eq > span:nth-child(3) { animation: rzlv-bar-c 1.13s ease-in-out -0.62s infinite alternate; }
.rzlv-hero-launcher__eq > span:nth-child(4) { animation: rzlv-bar-d 0.83s ease-in-out -0.41s infinite alternate; }
.rzlv-hero-launcher__eq > span:nth-child(5) { animation: rzlv-bar-e 1.02s ease-in-out -0.05s infinite alternate; }

html[data-voice-audio="on"] .rzlv-hero-launcher__eq > span {
  animation: none;
  transition: transform 60ms linear;
}
html[data-voice-audio="on"] .rzlv-hero-launcher__eq > span:nth-child(1) { transform: scaleY(calc(0.12 + var(--rz-bar-1, 0) * 0.88)); }
html[data-voice-audio="on"] .rzlv-hero-launcher__eq > span:nth-child(2) { transform: scaleY(calc(0.12 + var(--rz-bar-2, 0) * 0.88)); }
html[data-voice-audio="on"] .rzlv-hero-launcher__eq > span:nth-child(3) { transform: scaleY(calc(0.12 + var(--rz-bar-3, 0) * 0.88)); }
html[data-voice-audio="on"] .rzlv-hero-launcher__eq > span:nth-child(4) { transform: scaleY(calc(0.12 + var(--rz-bar-4, 0) * 0.88)); }
html[data-voice-audio="on"] .rzlv-hero-launcher__eq > span:nth-child(5) { transform: scaleY(calc(0.12 + var(--rz-bar-5, 0) * 0.88)); }

@keyframes rzlv-bar-a {
  0% { transform: scaleY(0.2); }
  35% { transform: scaleY(0.75); }
  60% { transform: scaleY(0.4); }
  100% { transform: scaleY(1); }
}
@keyframes rzlv-bar-b {
  0% { transform: scaleY(0.55); }
  30% { transform: scaleY(0.25); }
  70% { transform: scaleY(0.9); }
  100% { transform: scaleY(0.35); }
}
@keyframes rzlv-bar-c {
  0% { transform: scaleY(0.3); }
  50% { transform: scaleY(1); }
  100% { transform: scaleY(0.45); }
}
@keyframes rzlv-bar-d {
  0% { transform: scaleY(0.8); }
  40% { transform: scaleY(0.3); }
  65% { transform: scaleY(0.65); }
  100% { transform: scaleY(0.2); }
}
@keyframes rzlv-bar-e {
  0% { transform: scaleY(0.4); }
  25% { transform: scaleY(0.95); }
  55% { transform: scaleY(0.5); }
  80% { transform: scaleY(0.7); }
  100% { transform: scaleY(0.25); }
}

/* Caption under the bubble (state, hint, or inline error). */
.rzlv-hero-launcher__label,
.rzlv-hero-launcher__hint {
  position: absolute;
  left: 50%;
  top: calc(100% + 28px);
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.2px;
  color: #1c2978;
  pointer-events: none;
  animation: rzlv-hero-fade 0.25s ease-out;
}

.rzlv-hero-launcher__hint {
  color: #4b587a;
}

.rzlv-hero-launcher__label--error {
  color: #ef4444;
}

@keyframes rzlv-hero-fade {
  from { opacity: 0; transform: translateX(-50%) translateY(4px); }
  to { opacity: 1; transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .rzlv-hero-launcher__eq > span {
    animation: none;
    transform: scaleY(0.6);
  }
}

/* Assistant switched off: the chips stay as labels — same pill, no hover
   lift, no pointer, no arrow (includes/assistant-switch.php). */
.rz-hero__prompt--static {
  cursor: default;
  pointer-events: none;
}

/* Optional drift on the prompt chips (Settings → Rezolve Assistant → "Float
   the prompt chips"). transform only: hover's lift uses `translate`, so the
   two compose. Each chip gets its own period and phase so they never bob in
   step. Knobs: the -8px amplitude and the 6–7.5s periods. */
.rz-hero--chips-float .rz-hero__prompt {
  animation: rz-hero-chip-float 6s ease-in-out infinite;
}
.rz-hero--chips-float .rz-hero__prompt--2 { animation-duration: 7s; animation-delay: -1.5s; }
.rz-hero--chips-float .rz-hero__prompt--3 { animation-duration: 6.5s; animation-delay: -3s; }
.rz-hero--chips-float .rz-hero__prompt--4 { animation-duration: 7.5s; animation-delay: -4.5s; }
@keyframes rz-hero-chip-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
  .rz-hero--chips-float .rz-hero__prompt { animation: none; }
}
