/*
 * Shared chat widget styling — common visual canon for the three public
 * widgets (#lsc-root landing, #scc-root onboarding, #pac-root panel) and
 * the three hotline inboxes that mount the shared admin composer
 * (admin/landing_chat.php, admin/panel_chat.php, admin/support_chat.php).
 *
 * Plan 2026-05-20_chats_attachments_voice_email_gate.md, Batch 11. Loaded
 * BEFORE each widget's own CSS so per-widget overrides still win the cascade;
 * loaded AFTER chat_composer.css in the admin inboxes for the same reason.
 *
 * Sections:
 *   §1  Icon canon — paper-airplane RTL mirror, common icon sizing
 *   §2  Mobile FAB launcher (≤640 px) for the three customer widgets
 *   §3  Action-sheet popover (desktop) + bottom-sheet (mobile) shell
 *   §4  Recording-bar polish — composer replacement semantics
 *   §5  Bubble polish — image radius/border/shadow + voice pill
 *   §6  Customer sent-bubble "delivered" checkmark
 *
 * Everything inherits theme tokens (--surface, --text, --primary*) so dark
 * mode follows automatically; literal fallbacks keep the surface visible
 * even where the token sheet is absent.
 */

/* ─────────────────────────────────────────────────────────────────────
 * §1  Icon canon
 * ───────────────────────────────────────────────────────────────────── */

.gz-chat-icon--send {
  /* paper-airplane is authored LTR; RTL surfaces mirror only this glyph.
     We anchor on html-level dir / lang so the rule fires even when the
     send button lives inside an aside/dialog that escaped a sub-section
     scope (admin-side bottom sheets, mobile portals). */
}

html[dir="rtl"] .gz-chat-icon--send,
html[lang="ar"] .gz-chat-icon--send,
html.admin-lang-ar .gz-chat-icon--send {
  transform: scaleX(-1);
}

/* ─────────────────────────────────────────────────────────────────────
 * §2  Floating launcher canon — round 56×56 FAB on ALL viewports
 *
 * Owner-Auftrag 2026-05-22: the textual-pill launcher was visually heavy
 * on mobile (overflowed sticky CTAs / footer) AND on desktop (competed
 * with adjacent right-edge controls like the admin Feedback tab and the
 * landing WhatsApp FAB). The professional canon — the same shape every
 * modern chat surface uses (Intercom, Crisp, Drift, WhatsApp business
 * widget) — is a single 56×56 round icon button. We collapse to it on
 * EVERY viewport so the four customer launchers
 *   .lsc-launcher  (landing sales chat)
 *   .scc-launcher  (onboarding support chat)
 *   .pac-launcher  (subdomain admin-panel chat)
 *   .sc-launcher   (onboarding support-call booking)
 * read as one consistent help-dock visual canon, and never overlap the
 * page's own controls.
 *
 * The textual label stays in the DOM (visually hidden) so screen readers
 * still pick it up via the button's aria-label. The unread dot relocates
 * to the upper-trailing corner of the round icon (it was an inline pill
 * inside the wide button).
 *
 * Anchored to inset-block-end / inset-inline-end so RTL flips
 * automatically. The widget's own JS reads --*-cta-lift to add precise
 * lift when an IntersectionObserver detects a sticky CTA is on-screen;
 * the body:has rules in §7 set the global --gz-fab-stack-lift fallback.
 *
 * Why a CSS variable instead of inline style: the variable is the only
 * machinery that needs to ping each repaint; the launcher position
 * itself stays in the stylesheet, so a hot CTA resize doesn't trigger
 * style recalcs on the launcher element.
 * ───────────────────────────────────────────────────────────────────── */

/* — Launcher shape + bot+human avatar canvas —
 *
 * Smart size ladder via a single token (--gz-fab-size). The launcher
 * reads the token so any context override (a denser onboarding page, a
 * specific widget that needs to grow) is a one-line custom-property
 * override at the right scope. The ladder tracks viewport at the :root:
 *   Phone S (≤375)        → 46px   (one-handed reach, dense content)
 *   Phone (376–640)       → 50px
 *   Tablet (641–1024)     → 54px
 *   Desktop (≥1025)       → 58px   (legible avatar detail on a 1440 grid)
 *
 * Inner corner-badge tracks the FAB via clamp() so the dot stays
 * legible across the ladder without re-declaring per breakpoint.
 * ----------------------------------------------------------------- */
:root {
  --gz-fab-size: 50px;        /* phone default */
  --gz-fab-badge: 10px;
  --gz-fab-badge-inset: 5px;
  --gz-fab-corner-gap: 12px;  /* inter-FAB stacking gap (mobile) */
}
@media (min-width: 641px) {
  :root {
    --gz-fab-size: 54px;
    --gz-fab-badge: 11px;
    --gz-fab-badge-inset: 6px;
  }
}
@media (min-width: 1025px) {
  :root {
    --gz-fab-size: 58px;
    --gz-fab-badge: 12px;
    --gz-fab-badge-inset: 6px;
  }
}
@media (max-width: 375px) {
  :root {
    --gz-fab-size: 46px;
    --gz-fab-badge: 9px;
    --gz-fab-badge-inset: 5px;
  }
}

/* Per-widget identity tokens — the ring is the cheapest, most legible
   signal that distinguishes two launchers that share a dock (onboarding
   has the chat + the booking pair). Halo is the outer drop-shadow tint.
   Dark-mode follows automatically since rgb()-from-token resolves on the
   current theme's token sheet. */
#lsc-root.lsc-root {
  --gz-fab-ring: rgba(var(--primary-strong-rgb, 193, 74, 0), 0.22);
  --gz-fab-halo: rgba(var(--primary-strong-rgb, 193, 74, 0), 0.34);
}
.scc-root {
  --gz-fab-ring: rgba(var(--primary-strong-rgb, 193, 74, 0), 0.22);
  --gz-fab-halo: rgba(var(--primary-strong-rgb, 193, 74, 0), 0.34);
}
.sc-root {
  /* Booking ≠ chat. Tint the ring with the success/booking-confirm token
     so the dock has TWO distinguishable circles, not two clones. */
  --gz-fab-ring: rgba(var(--success-rgb, 34, 197, 94), 0.28);
  --gz-fab-halo: rgba(var(--success-rgb, 34, 197, 94), 0.28);
}
#pac-root.pac-root {
  /* Admin panel — uses widget-local --pac-accent (text-strong token) so
     it flips in dark mode along with the rest of the admin surface. */
  --gz-fab-ring: rgba(var(--text-rgb, 11, 18, 32), 0.22);
  --gz-fab-halo: rgba(15, 23, 42, 0.30);
}
[data-theme="dark"] #pac-root.pac-root,
:root[data-theme="dark"] #pac-root.pac-root {
  --gz-fab-ring: rgba(var(--text-rgb, 228, 231, 238), 0.30);
  --gz-fab-halo: rgba(0, 0, 0, 0.55);
}

#lsc-root.lsc-root .lsc-launcher,
.scc-root .scc-launcher,
#pac-root.pac-root .pac-launcher,
.sc-root .sc-launcher {
  width: var(--gz-fab-size, 52px);
  height: var(--gz-fab-size, 52px);
  padding: 0;
  border-radius: 50%;
  gap: 0;
  max-width: none;
  display: inline-grid;
  place-items: center;
  position: relative;          /* anchor the corner badge */
  overflow: hidden;            /* clip the avatar image to the circle */
  background: var(--surface, #ffffff);
  /* Identity ring (inset) + ambient shadow + accent halo. Combined here
     so per-widget hover shadow (still defined per-widget) replaces the
     full stack on hover — gives a "lift into accent" interaction. */
  box-shadow:
    inset 0 0 0 2px var(--gz-fab-ring, rgba(0, 0, 0, 0.08)),
    0 6px 16px rgba(15, 23, 42, 0.14),
    0 14px 34px var(--gz-fab-halo, rgba(0, 0, 0, 0.10));
}

#lsc-root.lsc-root .lsc-launcher__text,
.scc-root .scc-launcher__text,
#pac-root.pac-root .pac-launcher__text,
.sc-root .sc-launcher__text {
  /* Hide the textual label without removing it from the accessibility tree
     — the button's aria-label (set in PHP/JS) already carries the same
     string and is what screen readers announce. */
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The widget's JS injects an inline <svg> chat-bubble glyph inside
   .*-launcher__icon. We REPLACE that visual with the shared bot+human
   avatar by (a) hiding the inner SVG, (b) using the icon container as
   a full-bleed avatar canvas via background-image. The avatar WebP is
   already a circular crop with transparent corners, so it sits cleanly
   inside the circular FAB. */
#lsc-root.lsc-root .lsc-launcher__icon,
.scc-root .scc-launcher__icon,
#pac-root.pac-root .pac-launcher__icon,
.sc-root .sc-launcher__icon {
  width: 100%;
  height: 100%;
  background-image: url('/icons/bot_human_chat.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border-radius: 50%;
  font-size: 0;          /* belt-and-braces if the icon ever held text */
}

#lsc-root.lsc-root .lsc-launcher__icon > svg,
.scc-root .scc-launcher__icon > svg,
#pac-root.pac-root .pac-launcher__icon > svg,
.sc-root .sc-launcher__icon > svg {
  display: none;
}

/* Booking ≠ chat. The support-call (.sc-launcher) is the appointment-
   booking widget, NOT a chat — give it a call-centre photo so users
   recognise the dock as TWO distinct entry points, not two clones. */
.sc-root .sc-launcher__icon {
  background-image: url('/icons/call_chat.png');
}

/* ── Drag state (Batch 11 — gz-fab-draggable.js) ───────────────────────
   While the user is dragging a FAB, the document gets `.gz-fab-dragging`
   so we can disable transitions globally (smooth follow) + lift the
   grabbed FAB to a visible state. The handle uses cursor:grab at rest,
   cursor:grabbing while dragging. */
html.gz-fab-dragging,
html.gz-fab-dragging body,
html.gz-fab-dragging * {
  cursor: grabbing !important;
  user-select: none !important;
}

#lsc-launcher,
.scc-launcher,
#pac-root .pac-launcher,
.sc-launcher,
.wa-fab {
  cursor: grab;
  touch-action: none;
}

#lsc-root.gz-fab-dragging,
.scc-root.gz-fab-dragging,
#pac-root.gz-fab-dragging,
.sc-root.gz-fab-dragging,
.wa-fab.gz-fab-dragging {
  opacity: 0.92;
  transition: none !important;
  animation: none !important;
}

#lsc-root.gz-fab-dragging .lsc-launcher,
.scc-root.gz-fab-dragging .scc-launcher,
#pac-root.gz-fab-dragging .pac-launcher,
.sc-root.gz-fab-dragging .sc-launcher,
.wa-fab.gz-fab-dragging {
  transform: none !important;
  transition: none !important;
  animation: none !important;
}

/* ── WhatsApp FAB harmonisation ───────────────────────────────────────
   The .wa-fab is defined in public.css with its own --wa-fab-size
   (56 mobile / 60 desktop) and --wa-fab-edge (16 mobile / 22 desktop).
   That makes it visually larger AND set further inside than the chat
   FAB (which uses --gz-fab-size 46/50/54/58 and right: 16). Override
   here so the WhatsApp FAB matches the chat FAB exactly — same size,
   same right-edge, same baseline. The syncDock JS still lifts WhatsApp
   above the chat launcher via inline margin-bottom, so vertical
   stacking is preserved. */
.wa-fab {
  width: var(--gz-fab-size, 50px);
  height: var(--gz-fab-size, 50px);
  right: max(16px, env(safe-area-inset-right, 0px));
  bottom: calc(
    max(16px, env(safe-area-inset-bottom, 0px))
    + var(--ui-cookie-banner-height, 0px)
  );
}

/* RTL: mirror right→left so WhatsApp sits on the inline-start edge
   alongside the chat FAB (logical inset-inline-end flips automatically
   for the chat FABs; .wa-fab uses physical right/left so we mirror it
   explicitly here just like public.css does). */
[dir="rtl"] .wa-fab,
html[lang="ar"] .wa-fab {
  right: auto;
  left: max(16px, env(safe-area-inset-left, 0px));
}

/* ── Interactive polish ────────────────────────────────────────────────
   Entrance: scale + fade-in on mount so the launcher "arrives" rather
   than snapping in. Hover (desktop / hover-capable devices only): the
   launcher scales 1.06 and the halo deepens — the identity ring widens
   to 3px in the same motion so the accent reads stronger. Focus-visible
   adds an outer accent ring (3px) without scale, distinct from hover.
   Unread badge pulses with a calm 1.6s heartbeat. Everything honours
   prefers-reduced-motion. ─────────────────────────────────────────── */

@keyframes gz-fab-arrive {
  from { opacity: 0; transform: scale(0.86) translateY(4px); }
  to   { opacity: 1; transform: none; }
}

@keyframes gz-fab-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.86); }
}

#lsc-root.lsc-root .lsc-launcher,
.scc-root .scc-launcher,
#pac-root.pac-root .pac-launcher,
.sc-root .sc-launcher {
  animation: gz-fab-arrive 320ms cubic-bezier(0.16, 1, 0.3, 1) both;
  transition:
    transform 180ms cubic-bezier(0.2, 0.7, 0.2, 1),
    box-shadow 180ms cubic-bezier(0.2, 0.7, 0.2, 1);
  will-change: transform;
}

/* Hover only on hover-capable devices — avoids "sticky hover" on touch. */
@media (hover: hover) {
  #lsc-root.lsc-root .lsc-launcher:hover,
  .scc-root .scc-launcher:hover,
  #pac-root.pac-root .pac-launcher:hover,
  .sc-root .sc-launcher:hover {
    transform: translateY(-2px) scale(1.06);
    box-shadow:
      inset 0 0 0 3px var(--gz-fab-ring, rgba(0, 0, 0, 0.12)),
      0 10px 22px rgba(15, 23, 42, 0.18),
      0 22px 44px var(--gz-fab-halo, rgba(0, 0, 0, 0.14));
  }
}

#lsc-root.lsc-root .lsc-launcher:focus-visible,
.scc-root .scc-launcher:focus-visible,
#pac-root.pac-root .pac-launcher:focus-visible,
.sc-root .sc-launcher:focus-visible {
  outline: none;
  box-shadow:
    inset 0 0 0 2px var(--gz-fab-ring, rgba(0, 0, 0, 0.16)),
    0 0 0 3px var(--surface, #ffffff),
    0 0 0 6px var(--gz-fab-ring, rgba(0, 0, 0, 0.45)),
    0 14px 34px var(--gz-fab-halo, rgba(0, 0, 0, 0.18));
}

/* The unread dot is positioned in the badge rule above. Pulse it so the
   user notices a fresh message without the FAB jumping/scaling. */
#lsc-root.lsc-root[data-unread='1'] .lsc-launcher__badge,
.scc-root[data-unread='1'] .scc-launcher__badge,
#pac-root.pac-root[data-unread='1'] .pac-launcher__badge {
  animation: gz-fab-pulse 1.6s ease-in-out infinite;
  transform-origin: center;
}

@media (prefers-reduced-motion: reduce) {
  #lsc-root.lsc-root .lsc-launcher,
  .scc-root .scc-launcher,
  #pac-root.pac-root .pac-launcher,
  .sc-root .sc-launcher {
    animation: none;
    transition: none;
  }
  #lsc-root.lsc-root[data-unread='1'] .lsc-launcher__badge,
  .scc-root[data-unread='1'] .scc-launcher__badge,
  #pac-root.pac-root[data-unread='1'] .pac-launcher__badge {
    animation: none;
  }
  #lsc-root.lsc-root .lsc-launcher:hover,
  .scc-root .scc-launcher:hover,
  #pac-root.pac-root .pac-launcher:hover,
  .sc-root .sc-launcher:hover {
    transform: none;
  }
}

/* Unread / status dot — upper-trailing corner of the round icon (was an
   inline pill in the wide-button layout). RTL-safe via inset-inline-end.
   Sizes track the FAB ladder above so the dot stays legible without
   covering the avatar's face. */
#lsc-root.lsc-root[data-unread='1'] .lsc-launcher__badge,
.scc-root[data-unread='1'] .scc-launcher__badge,
#pac-root.pac-root[data-unread='1'] .pac-launcher__badge,
.sc-root[data-has-booking='1'] .sc-launcher__badge {
  position: absolute;
  inset-block-start: var(--gz-fab-badge-inset, 5px);
  inset-inline-end: var(--gz-fab-badge-inset, 5px);
  width: var(--gz-fab-badge, 10px);
  height: var(--gz-fab-badge, 10px);
  box-shadow: 0 0 0 2px var(--surface, #ffffff);
  z-index: 2;          /* above the avatar background-image */
}

/* NOTE 2026-05-23: previous mobile @media rules for inset-block-end have
   been MOVED into each widget's own CSS file. The cascade defeated them
   here: _chat_widget_shared.css loads BEFORE per-widget CSS, so my
   identical-specificity mobile selectors lost to the per-widget desktop
   default in source order. The per-widget CSS now owns mobile positioning
   alongside its desktop default so the lift chain
   (--*-cta-lift → --gz-fab-stack-lift → 0) actually fires. */

/* ─────────────────────────────────────────────────────────────────────
 * §3  Action-sheet (paperclip menu)
 *
 * One paperclip-button replaces the previous attach/camera/mic chain. Tap
 * opens a tiny sheet anchored to the composer:
 *   - Mobile ≤640px → bottom-sheet (slide up).
 *   - Desktop      → inline popover above the composer.
 * Each widget renders a `[role=dialog] .gz-chat-actions` with 1–3 items.
 * The widget-specific JS owns the open/close (with focus trap + ESC) and
 * sets [data-action-open="1"] on the action-sheet element.
 * ───────────────────────────────────────────────────────────────────── */

.gz-chat-actions {
  position: absolute;
  z-index: 5;
  background: var(--surface, #ffffff);
  color: var(--text, #0b1220);
  border: 1px solid var(--border, rgba(11, 18, 32, 0.12));
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.18);
  padding: 6px;
  min-width: 220px;
  max-width: 320px;
  display: none;
  flex-direction: column;
  gap: 2px;
}

.gz-chat-actions[data-action-open="1"] {
  display: flex;
}

.gz-chat-actions__item {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: inherit;
  text-align: start;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 10px;
  cursor: pointer;
  font: inherit;
  font-size: 0.95rem;
  min-height: 44px;          /* mobile touch target */
}

.gz-chat-actions__item:hover,
.gz-chat-actions__item:focus-visible {
  background: var(--surface-2, #f1f4fa);
  outline: none;
}

.gz-chat-actions__icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  display: inline-grid;
  place-items: center;
  color: var(--text-strong, #0b1220);
}

.gz-chat-actions__icon svg {
  width: 22px;
  height: 22px;
}

.gz-chat-actions__label {
  flex: 1 1 auto;
  min-width: 0;
}

.gz-chat-actions__scrim {
  position: fixed;
  inset: 0;
  background: transparent;        /* invisible on desktop; bottom-sheet adds */
  z-index: 4;
  display: none;
}

.gz-chat-actions__scrim[data-action-open="1"] {
  display: block;
}

@media (max-width: 640px) {
  .gz-chat-actions {
    position: fixed;
    inset-inline: 16px;
    inset-block-end: calc(16px + env(safe-area-inset-bottom, 0px));
    inset-block-start: auto;
    inset-inline-end: 16px;
    inset-inline-start: 16px;
    border-radius: 18px;
    padding: 10px;
    transform: translateY(8px);
    opacity: 0;
    transition: transform 180ms ease, opacity 180ms ease;
    pointer-events: none;
    display: flex;            /* keep in DOM for transition; gate w/ opacity */
    z-index: 1310;
  }
  .gz-chat-actions[data-action-open="1"] {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }
  .gz-chat-actions__scrim {
    background: rgba(10, 12, 20, 0.45);
    z-index: 1305;
  }
}

/* Dark mode — admin contract (data-theme), public contract (theme_a tokens). */
[data-theme="dark"] .gz-chat-actions,
body.admin-page.dark-mode .gz-chat-actions {
  background: var(--surface, #1a1d27);
  color: var(--text, #e5e7eb);
  border-color: rgba(228, 231, 238, 0.14);
}

[data-theme="dark"] .gz-chat-actions__item:hover,
[data-theme="dark"] .gz-chat-actions__item:focus-visible,
body.admin-page.dark-mode .gz-chat-actions__item:hover,
body.admin-page.dark-mode .gz-chat-actions__item:focus-visible {
  background: rgba(255, 255, 255, 0.06);
}

/* ─────────────────────────────────────────────────────────────────────
 * §4  Recording bar — composer-replacement semantics
 *
 * While the recorder is in 'recording' / 'ready_to_send' / 'uploading', the
 * widget collapses the composer row entirely (no textarea, no attach button)
 * and shows only the recording bar. Each widget's root carries
 * [data-rec-state]; we attribute-target the composer + sibling rec bar so
 * the swap happens without JS having to flip individual elements.
 * ───────────────────────────────────────────────────────────────────── */

/* Landing — #lsc-root */
#lsc-root.lsc-root[data-rec-state="recording"] .lsc-composer,
#lsc-root.lsc-root[data-rec-state="ready_to_send"] .lsc-composer,
#lsc-root.lsc-root[data-rec-state="uploading"] .lsc-composer,
#lsc-root.lsc-root[data-rec-state="recording"] .lsc-tray,
#lsc-root.lsc-root[data-rec-state="ready_to_send"] .lsc-tray,
#lsc-root.lsc-root[data-rec-state="uploading"] .lsc-tray {
  display: none !important;
}

/* Onboarding — .scc-root */
.scc-root[data-rec-state="recording"] .scc-composer,
.scc-root[data-rec-state="ready_to_send"] .scc-composer,
.scc-root[data-rec-state="uploading"] .scc-composer,
.scc-root[data-rec-state="recording"] .scc-tray,
.scc-root[data-rec-state="ready_to_send"] .scc-tray,
.scc-root[data-rec-state="uploading"] .scc-tray {
  display: none !important;
}

/* Panel — #pac-root */
#pac-root.pac-root[data-rec-state="recording"] .pac-composer,
#pac-root.pac-root[data-rec-state="ready_to_send"] .pac-composer,
#pac-root.pac-root[data-rec-state="uploading"] .pac-composer,
#pac-root.pac-root[data-rec-state="recording"] .pac-tray,
#pac-root.pac-root[data-rec-state="ready_to_send"] .pac-tray,
#pac-root.pac-root[data-rec-state="uploading"] .pac-tray {
  display: none !important;
}

/* Admin composer (shared library — chat_composer.css owns .chc-bar/.chc-rec).
   When recording, the .chc-bar hides via inline [hidden] from the lib; the
   replyTextarea sibling should also collapse so the visual swap is total. */
.sci-composer[data-rec-state="recording"] .sci-field,
.sci-composer[data-rec-state="ready_to_send"] .sci-field,
.sci-composer[data-rec-state="uploading"] .sci-field {
  display: none !important;
}

/* ─────────────────────────────────────────────────────────────────────
 * §5  Bubble polish — image radius/border/shadow + voice pill
 *
 * The widgets carry their own bubble class roots (lsc-msg / scc-msg /
 * pac-msg), but the attachment children all read as one product. Apply
 * the same radius/border/soft-shadow + voice pill shape across all six
 * surfaces (3 widgets + 3 inboxes).
 * ───────────────────────────────────────────────────────────────────── */

/* Image thumbs */
.lsc-msg__att,
.scc-msg__att,
.pac-msg__att,
.sci-msg__att {
  border-radius: 12px;
  border: 1px solid rgba(0, 0, 0, 0.06);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05),
              0 4px 12px rgba(15, 23, 42, 0.06);
  background: var(--surface, #ffffff);
}

[data-theme="dark"] .lsc-msg__att,
[data-theme="dark"] .scc-msg__att,
[data-theme="dark"] .pac-msg__att,
[data-theme="dark"] .sci-msg__att,
body.admin-page.dark-mode .sci-msg__att {
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4),
              0 4px 12px rgba(0, 0, 0, 0.35);
}

/* Voice row — pill-shape container so the native player + duration read
   as a single object. The native <audio> is browser-themed; we just clamp
   width + radius and lock duration to LTR mm:ss. */
.lsc-msg__voice-row,
.scc-msg__voice-row,
.pac-msg__voice-row,
.sci-msg__voice-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
  background: var(--surface-2, #f1f4fa);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 999px;
  max-width: 320px;
  margin-block-start: 4px;
}

[data-theme="dark"] .lsc-msg__voice-row,
[data-theme="dark"] .scc-msg__voice-row,
[data-theme="dark"] .pac-msg__voice-row,
[data-theme="dark"] .sci-msg__voice-row,
body.admin-page.dark-mode .sci-msg__voice-row {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.12);
}

.lsc-msg__voice,
.scc-msg__voice,
.pac-msg__voice,
.sci-msg__voice {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 240px;
  height: 36px;
}

.lsc-msg__voice-dur,
.scc-msg__voice-dur,
.pac-msg__voice-dur,
.sci-msg__voice-dur {
  flex: 0 0 auto;
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
  color: var(--muted, #54607a);
  background: transparent;
  padding: 0;
  border-radius: 0;
}

[data-theme="dark"] .lsc-msg__voice-dur,
[data-theme="dark"] .scc-msg__voice-dur,
[data-theme="dark"] .pac-msg__voice-dur,
[data-theme="dark"] .sci-msg__voice-dur,
body.admin-page.dark-mode .sci-msg__voice-dur {
  color: var(--muted, #9ca3af);
}

/* ─────────────────────────────────────────────────────────────────────
 * §6  Sent-bubble "delivered" checkmark
 *
 * The customer's own bubble carries a small bottom-trailing checkmark to
 * confirm the message reached the server. The widget's render layer adds
 * a .lsc-msg__sent / .scc-msg__sent / .pac-msg__sent span with the check
 * glyph; CSS positions it consistently across the three widgets.
 * ───────────────────────────────────────────────────────────────────── */

.lsc-msg__sent,
.scc-msg__sent,
.pac-msg__sent {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-inline-start: 6px;
  vertical-align: middle;
  color: var(--success, #16a34a);
  opacity: 0.85;
}

.lsc-msg__sent svg,
.scc-msg__sent svg,
.pac-msg__sent svg {
  width: 14px;
  height: 14px;
}

/* Reduced-motion: kill the action-sheet entrance transition. */
@media (prefers-reduced-motion: reduce) {
  .gz-chat-actions {
    transition: none;
  }
}

/* ─────────────────────────────────────────────────────────────────────
 * §7  FAB stack — declarative obstruction lift (CSS-only fallback)
 *
 * Each "bottom obstruction" on a public page (sticky product CTA, the
 * support-call "Hilfe?" pill, future bottom sheets …) advertises itself
 * by sitting in the DOM with a known selector. We translate that
 * presence into a shared CSS variable on <body> that ALL FABs (LSC,
 * SCC, SC, WA via syncDock) read in their inset-block-end calc.
 *
 * This is a PURE CSS path that fires the moment the obstruction
 * mounts — no IntersectionObserver, no setTimeout, no race with the
 * mobile transform transition. The widget JS still measures the
 * obstruction precisely and overrides via inline style on <body>; if
 * the JS observer misses (cache miss, defer race, transform timing)
 * the page still positions FABs correctly. Modern :has() (Chrome 105+,
 * Safari 15.4+, Firefox 121+) is well past our support baseline.
 *
 * Height values are conservative measurements of each obstruction's
 * actual rendered height on mobile (≤640px), padded by 12px breathing.
 * The widget JS may override with a precise per-resize measurement.
 * ───────────────────────────────────────────────────────────────────── */

/* Default — no obstruction on the page. */
:root {
  --gz-fab-stack-lift: 0px;
}

/* Sticky product CTA bar (modules/offers/sticky_cta + variants). Toggled
   via the `inert` attribute by sticky_cta.js (WCAG-friendly hide); when
   NOT inert the bar transforms into the viewport. Height ~72px + 12px. */
body:has([data-sticky-cta]:not([inert])),
body:has(.sticky-cta:not([inert])),
body:has(.gz-sticky-cta:not([hidden])),
body:has(.pricing-sticky-cta:not([hidden])),
body:has(.footer-cta-bar:not([hidden])) {
  --gz-fab-stack-lift: 84px;
}

/* Support-call is another FAB, not a bottom obstruction. It must not set the
   global lift because .sc-root itself would read that value. Onboarding chat
   stacking is handled by --scc-dock-offset in support-chat.js. */


/* Make the LSC mobile FAB use the shared lift as a fallback when the
   widget JS hasn't measured a precise --lsc-cta-lift yet. The widget
   still owns --lsc-cta-lift via setProperty; we just chain the
   variable resolution so a missing local var falls back to the global. */
@media (max-width: 640px) {
  #lsc-root.lsc-root {
    inset-block-end: calc(
      max(18px, env(safe-area-inset-bottom, 0px))
      + var(--ui-cookie-banner-height, 0px)
      + var(--lsc-cta-lift, var(--gz-fab-stack-lift, 0px))
    );
  }
}
