﻿/**
 * AIKC Chatbot — floating widget styles.
 * Visual tokens are driven by CSS custom properties set at runtime from
 * admin config (cores, tamanho, offsets, posição).
 */

.aikc-chatbot,
.aikc-chatbot * {
    box-sizing: border-box;
}

.aikc-chatbot {
    --aikc-cb-primary:   #3b44b5;
    --aikc-cb-accent:    #923472;
    --aikc-cb-surface:   #f5f5f7;
    --aikc-cb-surface-2: #ffffff;
    /* Panel-scoped vars are populated PER PRESET by the [data-theme="…"]
       blocks below (see "Panel palette per preset"). Each preset declares
       its own header background, message bubble colours, borders, etc.
       The defaults here mirror the `legacy` preset and act as the no-JS /
       unrecognised-theme fallback. The admin's primary/accent/surface
       customisation continues to override `--aikc-cb-panel-primary`/-accent
       /-surface only; the rest of the palette stays preset-controlled. */
    --aikc-cb-panel-primary:        #3b44b5;
    --aikc-cb-panel-accent:         #923472;
    --aikc-cb-panel-surface:        #f5f5f7;
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #3b44b5 0%, #923472 100%);
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #64748b;
    --aikc-cb-panel-user-bg:        linear-gradient(135deg, #3b44b5 0%, #923472 100%);
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         #e5e7eb;
    --aikc-cb-panel-compose-bg:     #ffffff;
    /* Legacy var names retained — older rules and the admin tab still
       reference them. Kept aligned with panel-* defaults for backwards
       compatibility. */
    --aikc-cb-text:      #0f172a;
    --aikc-cb-muted:     #64748b;
    --aikc-cb-border:    #e5e7eb;
    --aikc-cb-radius:    16px;
    --aikc-cb-shadow:    0 18px 48px rgba(15, 23, 42, 0.22);
    --aikc-cb-font:      "Aptos", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --aikc-cb-bubble-size: 64px;
    --aikc-cb-offset-x: 20px;
    --aikc-cb-offset-y: 20px;

    position: fixed;
    z-index: 999999;
    font-family: var(--aikc-cb-font);
    color: var(--aikc-cb-panel-text);
    line-height: 1.45;
}

/* Position variants */
.aikc-chatbot[data-pos="bottom-right"] { right: var(--aikc-cb-offset-x); bottom: var(--aikc-cb-offset-y); left: auto; top: auto; }
.aikc-chatbot[data-pos="bottom-left"]  { left:  var(--aikc-cb-offset-x); bottom: var(--aikc-cb-offset-y); right: auto; top: auto; }
.aikc-chatbot[data-pos="top-right"]    { right: var(--aikc-cb-offset-x); top:    var(--aikc-cb-offset-y); left: auto; bottom: auto; }
.aikc-chatbot[data-pos="top-left"]     { left:  var(--aikc-cb-offset-x); top:    var(--aikc-cb-offset-y); right: auto; bottom: auto; }

/* ── Floating bubble ───────────────────────────── */
/* All `!important` declarations here are deliberate — site themes routinely
   target generic <button> selectors and would otherwise override our look.
   Per-theme tweaks below stay !important for the same reason. New rules in
   per-theme blocks only use !important when they need to win against this
   base block. */
.aikc-chatbot__bubble {
    --aikc-cb-bubble-pad: 14px;
    width: var(--aikc-cb-bubble-size) !important;
    height: var(--aikc-cb-bubble-size) !important;
    min-width: var(--aikc-cb-bubble-size) !important;
    min-height: var(--aikc-cb-bubble-size) !important;
    max-width: var(--aikc-cb-bubble-size) !important;
    max-height: var(--aikc-cb-bubble-size) !important;
    padding: var(--aikc-cb-bubble-pad) !important;
    box-sizing: border-box !important;
    margin: 0 !important;
    border: 0 !important;
    border-radius: 50% !important;
    /* Layered gradient: radial highlight on top + brand diagonal underneath */
    background:
        radial-gradient(circle at 30% 25%, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 55%),
        linear-gradient(135deg, var(--aikc-cb-primary) 0%, var(--aikc-cb-accent) 100%) !important;
    color: #fff !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    /* Inner highlight ring + soft outer glow + main shadow */
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.35),
        inset 0 -2px 6px rgba(0,0,0,0.10),
        var(--aikc-cb-shadow),
        0 0 0 0 rgba(59, 68, 181, 0.4) !important;
    transition: transform 180ms ease, box-shadow 220ms ease;
    position: relative;
    z-index: 2;
    outline: none !important;
    text-shadow: none !important;
    font-size: 0 !important;
    line-height: 1 !important;
    text-transform: none !important;
    letter-spacing: 0 !important;
    overflow: visible;
}
/* Generic hover: just a subtle scale. Individual themes override transform
   and box-shadow with their own signature (e.g. legacy adds rotate, retro
   adds press-in). Base transform stays without !important so themes win. */
.aikc-chatbot__bubble:hover {
    transform: scale(1.06);
}
.aikc-chatbot__bubble:focus-visible {
    outline: 3px solid var(--aikc-cb-accent) !important;
    outline-offset: 3px;
}
/* Legacy keeps its original rotate+halo hover for backwards compatibility. */
.aikc-chatbot[data-theme="legacy"] .aikc-chatbot__bubble:hover {
    transform: scale(1.08) rotate(-3deg);
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.4),
        inset 0 -2px 6px rgba(0,0,0,0.10),
        var(--aikc-cb-shadow),
        0 0 0 10px rgba(59, 68, 181, 0.14) !important;
}
.aikc-chatbot__bubble svg {
    width: 100% !important;
    height: 100% !important;
    display: block !important;
    max-width: none !important;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));
}
.aikc-chatbot__bubble.is-pulse {
    animation: aikc-cb-pulse 2.2s ease-in-out infinite, aikc-cb-bob 3.6s ease-in-out infinite;
}
@keyframes aikc-cb-pulse {
    0%, 100% {
        box-shadow:
            var(--aikc-cb-shadow),
            0 0 0 0 rgba(59, 68, 181, 0.55),
            0 0 0 0 rgba(146, 52, 114, 0.30);
    }
    50% {
        box-shadow:
            var(--aikc-cb-shadow),
            0 0 0 12px rgba(59, 68, 181, 0.0),
            0 0 0 22px rgba(146, 52, 114, 0.0);
    }
}
@keyframes aikc-cb-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
    .aikc-chatbot__bubble.is-pulse { animation: none; }
}

/* Bubble tooltip on hover */
.aikc-chatbot__tooltip {
    position: absolute;
    bottom: calc(100% + 10px);
    right: 0;
    padding: 6px 10px;
    background: #0f172a;
    color: #fff;
    font-size: 12px;
    font-weight: 500;
    border-radius: 8px;
    white-space: nowrap;
    opacity: 0;
    transform: translateY(4px);
    pointer-events: none;
    transition: opacity 160ms ease, transform 160ms ease;
}
.aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__tooltip,
.aikc-chatbot[data-pos="top-left"] .aikc-chatbot__tooltip { right: auto; left: 0; }
.aikc-chatbot[data-pos^="top-"] .aikc-chatbot__tooltip { bottom: auto; top: calc(100% + 10px); transform: translateY(-4px); }
.aikc-chatbot__bubble:hover + .aikc-chatbot__tooltip,
.aikc-chatbot__bubble:focus-visible + .aikc-chatbot__tooltip {
    opacity: 1;
    transform: translateY(0);
}

/* Teaser (pre-panel mini bubble) */
.aikc-chatbot__teaser {
    position: absolute;
    bottom: calc(100% + 16px);
    right: 0;
    /* Cap width AND respect viewport so we never overflow on small screens.
       The 88px subtracted = ~64 bubble + 20 offset + 4 margin safety. */
    width: min(280px, calc(100vw - 88px));
    max-width: 280px;
    padding: 14px 30px 14px 16px;
    background: linear-gradient(180deg, #ffffff 0%, #fafaff 100%);
    color: var(--aikc-cb-text);
    border: 1px solid var(--aikc-cb-border);
    border-radius: 16px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15, 23, 42, 0.06);
    font-family: var(--aikc-cb-font);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.4;
    /* Force normal wrapping — div-as-button avoids button-default nowrap. */
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: anywhere;
    cursor: pointer;
    opacity: 0;
    transform: translateY(8px) scale(0.96);
    pointer-events: none;
    transition: opacity 220ms ease, transform 260ms cubic-bezier(.2,.9,.3,1.4);
}
.aikc-chatbot__teaser-text {
    display: block;
    white-space: normal;
    word-wrap: break-word;
    overflow-wrap: anywhere;
}
/* Speech-bubble tail pointing to the chat bubble */
.aikc-chatbot__teaser::after {
    content: "";
    position: absolute;
    bottom: -7px;
    right: 22px;
    width: 14px;
    height: 14px;
    background: linear-gradient(135deg, #fafaff 50%, transparent 50%);
    border-right: 1px solid var(--aikc-cb-border);
    border-bottom: 1px solid var(--aikc-cb-border);
    transform: rotate(45deg);
    border-bottom-right-radius: 3px;
}
.aikc-chatbot__teaser:hover {
    transform: translateY(-1px) scale(1);
    box-shadow: 0 16px 40px rgba(15, 23, 42, 0.22), 0 2px 8px rgba(15, 23, 42, 0.08);
}
.aikc-chatbot__teaser.is-open {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__teaser,
.aikc-chatbot[data-pos="top-left"] .aikc-chatbot__teaser { right: auto; left: 0; }
.aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__teaser::after,
.aikc-chatbot[data-pos="top-left"] .aikc-chatbot__teaser::after  { right: auto; left: 22px; }
.aikc-chatbot[data-pos^="top-"] .aikc-chatbot__teaser { bottom: auto; top: calc(100% + 16px); }
.aikc-chatbot[data-pos^="top-"] .aikc-chatbot__teaser::after {
    bottom: auto; top: -7px; transform: rotate(225deg);
}
.aikc-chatbot__teaser-dismiss {
    position: absolute;
    top: -8px;
    right: -8px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    border: 1px solid var(--aikc-cb-border);
    color: var(--aikc-cb-muted);
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    z-index: 1;
}
.aikc-chatbot__teaser-dismiss svg { width: 12px; height: 12px; stroke: currentColor; fill: none; }
.aikc-chatbot__teaser:hover .aikc-chatbot__teaser-dismiss { color: var(--aikc-cb-text); }

/* ── Chooser (chat vs WhatsApp) ────────────────── */
.aikc-chatbot__chooser {
    position: absolute;
    bottom: calc(100% + 14px);
    right: 0;
    width: 280px;
    max-width: calc(100vw - 32px);
    padding: 16px 14px 14px;
    /* Chooser is a mini panel sitting above the bubble — it tracks the
       panel palette of the active preset (not the bubble's own surface)
       so dark themes get a dark chooser, terminal gets neon-on-black, etc. */
    background: var(--aikc-cb-panel-surface);
    border: 1px solid var(--aikc-cb-panel-border);
    border-radius: 16px;
    box-shadow: 0 18px 48px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15, 23, 42, 0.06);
    font-family: var(--aikc-cb-font);
    color: var(--aikc-cb-panel-text);
    opacity: 0;
    transform: translateY(8px) scale(0.96);
    transform-origin: bottom right;
    pointer-events: none;
    transition: opacity 200ms ease, transform 240ms cubic-bezier(.2,.9,.3,1.2);
    z-index: 3;
}
.aikc-chatbot__chooser.is-open {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__chooser,
.aikc-chatbot[data-pos="top-left"]    .aikc-chatbot__chooser { right: auto; left: 0; transform-origin: bottom left; }
.aikc-chatbot[data-pos^="top-"]       .aikc-chatbot__chooser { bottom: auto; top: calc(100% + 14px); transform-origin: top right; }
.aikc-chatbot[data-pos="top-left"]    .aikc-chatbot__chooser { transform-origin: top left; }

.aikc-chatbot__chooser-title {
    font-size: 14px;
    font-weight: 600;
    margin: 0 26px 12px 0;
    color: var(--aikc-cb-panel-text);
    line-height: 1.3;
}
.aikc-chatbot__chooser-close {
    position: absolute !important;
    top: 8px !important;
    right: 8px !important;
    width: 26px !important;
    height: 26px !important;
    min-width: 26px !important;
    min-height: 26px !important;
    padding: 0 !important;
    background: transparent !important;
    border: 0 !important;
    border-radius: 999px !important;
    color: var(--aikc-cb-panel-muted) !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    font-size: 0 !important;
    line-height: 1 !important;
    box-shadow: none !important;
}
.aikc-chatbot__chooser-close:hover { color: var(--aikc-cb-panel-text) !important; background: var(--aikc-cb-panel-assistant-bg) !important; }
.aikc-chatbot__chooser-close svg   { width: 14px !important; height: 14px !important; stroke: currentColor !important; fill: none !important; }

.aikc-chatbot__chooser-btn {
    display: flex !important;
    align-items: center !important;
    gap: 12px !important;
    width: 100% !important;
    padding: 10px 12px !important;
    margin: 0 0 8px 0 !important;
    /* Each chooser button mirrors an assistant message bubble — same
       palette so dark themes get dark buttons, light themes light. */
    background: var(--aikc-cb-panel-assistant-bg) !important;
    border: 1px solid var(--aikc-cb-panel-border) !important;
    border-radius: 12px !important;
    color: var(--aikc-cb-panel-assistant-text) !important;
    cursor: pointer !important;
    text-align: left !important;
    text-decoration: none !important;
    font-family: inherit !important;
    font-size: 13px !important;
    line-height: 1.3 !important;
    transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
    box-shadow: none !important;
}
.aikc-chatbot__chooser-btn:last-child { margin-bottom: 0 !important; }
.aikc-chatbot__chooser-btn:hover {
    transform: translateY(-1px);
    border-color: var(--aikc-cb-primary) !important;
    /* Subtle elevation in place of the previous hardcoded white bg —
       works on both light and dark themes. */
    box-shadow: 0 4px 10px rgba(15, 23, 42, 0.10) !important;
}
.aikc-chatbot__chooser-icon {
    flex: 0 0 36px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.aikc-chatbot__chooser-icon--chat {
    background: linear-gradient(135deg, var(--aikc-cb-primary) 0%, var(--aikc-cb-accent) 100%);
    padding: 7px;
}
.aikc-chatbot__chooser-icon--chat svg { width: 100%; height: 100%; }
.aikc-chatbot__chooser-icon--wa svg { width: 100%; height: 100%; display: block; }

.aikc-chatbot__chooser-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 auto;
}
.aikc-chatbot__chooser-label { font-weight: 600; color: var(--aikc-cb-panel-assistant-text); }
.aikc-chatbot__chooser-sub   { font-size: 12px; color: var(--aikc-cb-panel-muted); font-weight: 400; }

/* Glassmorphism: the chooser inherits the same frosted-glass treatment
   the panel gets, so it doesn't read as opaque white over a blurred chat. */
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__chooser {
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
}

/* Unread badge */
.aikc-chatbot__badge {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    background: #ef4444;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    border-radius: 10px;
    display: none;
    align-items: center;
    justify-content: center;
    border: 2px solid #fff;
    line-height: 1;
}
.aikc-chatbot__badge.is-visible { display: flex; }

/* ── Panel ─────────────────────────────────────── */
.aikc-chatbot__panel {
    position: absolute;
    right: 0;
    bottom: calc(var(--aikc-cb-bubble-size) + 14px);
    width: 380px;
    max-width: calc(100vw - 32px);
    height: 560px;
    max-height: calc(100vh - 120px);
    background: var(--aikc-cb-panel-assistant-bg);
    border-radius: var(--aikc-cb-radius);
    box-shadow: var(--aikc-cb-shadow);
    display: none;
    flex-direction: column;
    overflow: hidden;
    transform-origin: bottom right;
    z-index: 1;
}
.aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__panel { left: 0; right: auto; transform-origin: bottom left; }
.aikc-chatbot[data-pos="top-right"]   .aikc-chatbot__panel { top: calc(var(--aikc-cb-bubble-size) + 14px); bottom: auto; transform-origin: top right; }
.aikc-chatbot[data-pos="top-left"]    .aikc-chatbot__panel { top: calc(var(--aikc-cb-bubble-size) + 14px); bottom: auto; left: 0; right: auto; transform-origin: top left; }

.aikc-chatbot__panel.is-open { display: flex !important; }
.aikc-chatbot [hidden] { display: none !important; }

/* Open-in animations per effect */
.aikc-chatbot__panel.is-open[data-effect="slide"]  { animation: aikc-cb-slide 240ms cubic-bezier(.2,.9,.3,1.1); }
.aikc-chatbot__panel.is-open[data-effect="fade"]   { animation: aikc-cb-fade 260ms ease; }
.aikc-chatbot__panel.is-open[data-effect="bounce"] { animation: aikc-cb-bounce 420ms cubic-bezier(.34,1.56,.64,1); }
.aikc-chatbot__panel.is-open[data-effect="none"]   { animation: none; }

/* ── Close-out: reuse the open keyframes in reverse ───────────────
 * Adding `.is-closing` flips the chosen open animation backwards so the
 * panel collapses with the same visual signature it opened with (e.g.
 * iris-dilate shrinks from the corner; flip-3d rotates back; mask-reveal
 * runs its gradient sweep in the opposite direction).
 *
 * Stagger-stack would behave badly under reverse (each message has its
 * own keyframe + cumulative delay), so we override it with a simple
 * reverse fade — fast, predictable, no leftover staggered ghosts.
 *
 * The JS removes `.is-open` and `.is-closing` after `animationend` (with
 * a timeout fallback) so the panel actually hides; until then the
 * `animation-fill-mode: forwards` keeps the end-of-animation visual
 * (invisible/translated) on screen. */
.aikc-chatbot__panel.is-open.is-closing {
    animation-direction: reverse !important;
    animation-fill-mode: forwards !important;
}
.aikc-chatbot__panel.is-open.is-closing[data-effect="stagger-stack"] {
    animation: aikc-cb-fade 200ms ease reverse forwards !important;
}
.aikc-chatbot__panel.is-open.is-closing .aikc-chatbot__msg,
.aikc-chatbot__panel.is-open.is-closing .aikc-chatbot__compose {
    /* During close, individual msg/compose animations stop running so they
       don't keep their entry styles and override the panel-level fade. */
    animation: none !important;
}
.aikc-chatbot__panel.is-open.is-closing[data-effect="none"] {
    /* No animation configured? Just hide instantly via the JS path —
       nothing for CSS to do here. */
    animation: none !important;
}

@keyframes aikc-cb-slide {
    from { opacity: 0; transform: translateY(20px) scale(0.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes aikc-cb-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes aikc-cb-bounce {
    0%   { opacity: 0; transform: scale(0.6); }
    55%  { opacity: 1; transform: scale(1.04); }
    80%  { transform: scale(0.98); }
    100% { transform: scale(1); }
}

/* ── Header ───────────────────────────────────── */
.aikc-chatbot__header {
    padding: 14px 16px;
    /* Header background is preset-controlled via the panel palette. Each
       [data-theme="…"] block below declares --aikc-cb-panel-header-bg as
       either a solid colour or a gradient string. */
    background: var(--aikc-cb-panel-header-bg);
    color: var(--aikc-cb-panel-user-text);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.aikc-chatbot__title    { font-weight: 600; font-size: 15px; margin: 0; line-height: 1.2; }
.aikc-chatbot__subtitle { font-size: 12px; opacity: 0.85; margin: 2px 0 0; }

.aikc-chatbot__header-actions { display: flex; gap: 4px; }
.aikc-chatbot__icon-btn {
    background: transparent !important;
    border: 0 !important;
    color: #fff !important;
    cursor: pointer !important;
    width: 32px !important;
    height: 32px !important;
    min-width: 32px !important;
    min-height: 32px !important;
    padding: 0 !important;
    border-radius: 8px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    box-shadow: none !important;
    outline: none;
    line-height: 1 !important;
    text-shadow: none !important;
    font-size: 0 !important;
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(255,255,255,0.2);
}
.aikc-chatbot__icon-btn:hover,
.aikc-chatbot__icon-btn:focus {
    background: rgba(255,255,255,0.18) !important;
    color: #fff !important;
}
.aikc-chatbot__icon-btn svg {
    width: 18px !important;
    height: 18px !important;
    display: block !important;
    stroke: #fff !important;
    fill: none !important;
    pointer-events: none;
}

/* ── Messages ─────────────────────────────────── */
.aikc-chatbot__messages {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 14px;
    background: var(--aikc-cb-panel-surface);
    display: flex;
    flex-direction: column;
    gap: 10px;
    scrollbar-width: thin;
    scrollbar-color: var(--aikc-cb-panel-border) transparent;
}
.aikc-chatbot__messages::-webkit-scrollbar { width: 6px; }
.aikc-chatbot__messages::-webkit-scrollbar-thumb { background: var(--aikc-cb-panel-border); border-radius: 999px; }

.aikc-chatbot__msg {
    max-width: 86%;
    padding: 10px 12px;
    border-radius: 14px;
    font-size: 14px;
    line-height: 1.5;
    word-wrap: break-word;
    animation: aikc-cb-msg-in 280ms cubic-bezier(.2,.9,.3,1);
}
@keyframes aikc-cb-msg-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.aikc-chatbot__msg--user {
    align-self: flex-end;
    background: var(--aikc-cb-panel-user-bg);
    color: var(--aikc-cb-panel-user-text);
    border-bottom-right-radius: 4px;
}
.aikc-chatbot__msg--assistant {
    align-self: flex-start;
    background: var(--aikc-cb-panel-assistant-bg);
    color: var(--aikc-cb-panel-assistant-text);
    border: 1px solid var(--aikc-cb-panel-border);
    border-bottom-left-radius: 4px;
}

/* Typewriter cursor */
.aikc-chatbot__msg--typing-text::after {
    content: '▊';
    display: inline-block;
    margin-left: 2px;
    animation: aikc-cb-caret 1s steps(2) infinite;
    color: var(--aikc-cb-panel-primary);
}
@keyframes aikc-cb-caret {
    50% { opacity: 0; }
}

/* Typing indicator — three dots */
.aikc-chatbot__typing-dots {
    display: inline-flex;
    gap: 4px;
    padding: 4px 0;
}
.aikc-chatbot__typing-dots span {
    width: 7px;
    height: 7px;
    background: var(--aikc-cb-muted);
    border-radius: 50%;
    animation: aikc-cb-dot 1.2s ease-in-out infinite;
}
.aikc-chatbot__typing-dots span:nth-child(2) { animation-delay: 0.15s; }
.aikc-chatbot__typing-dots span:nth-child(3) { animation-delay: 0.3s; }
@keyframes aikc-cb-dot {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
    40%           { transform: scale(1);   opacity: 1; }
}

/* Citations */
.aikc-chatbot__citations {
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.aikc-chatbot__citation {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: var(--aikc-cb-panel-assistant-bg);
    border: 1px solid var(--aikc-cb-panel-border);
    border-left: 3px solid var(--aikc-cb-panel-accent);
    border-radius: 8px;
    color: var(--aikc-cb-panel-assistant-text);
    text-decoration: none;
    font-size: 12.5px;
    opacity: 0;
    transform: translateY(4px);
    animation: aikc-cb-msg-in 320ms ease forwards;
    transition: background 140ms ease, border-color 140ms ease;
}
.aikc-chatbot__citation:hover {
    background: var(--aikc-cb-panel-surface);
    border-left-color: var(--aikc-cb-panel-primary);
}
.aikc-chatbot__citation-type {
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--aikc-cb-panel-accent);
    font-weight: 700;
}
.aikc-chatbot__citation-title { flex: 1; font-weight: 500; }
.aikc-chatbot__citation-icon  { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.aikc-chatbot__citation svg   { width: 14px; height: 14px; color: var(--aikc-cb-panel-muted); flex-shrink: 0; }

/* Click feedback: the visitor clicked a citation and the next page is
   loading. Spinner replaces the link icon (JS swap), the row is dimmed
   slightly, cursor switches to wait, and a thin accent bar sweeps across
   the bottom to reinforce "something is happening". */
.aikc-chatbot__citation.is-loading {
    cursor: wait;
    opacity: 0.7;
    position: relative;
    overflow: hidden;
}
.aikc-chatbot__citation.is-loading .aikc-chatbot__citation-icon svg {
    color: var(--aikc-cb-panel-accent);
    animation: aikc-cb-spin 700ms linear infinite;
}
.aikc-chatbot__citation.is-loading::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--aikc-cb-panel-accent), transparent);
    animation: aikc-cb-progress-sweep 1.1s ease-in-out infinite;
}
@keyframes aikc-cb-spin {
    to { transform: rotate(360deg); }
}
@keyframes aikc-cb-progress-sweep {
    from { transform: translateX(-100%); }
    to   { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
    .aikc-chatbot__citation.is-loading .aikc-chatbot__citation-icon svg { animation: none; }
    .aikc-chatbot__citation.is-loading::after { animation: none; opacity: 0.5; }
}

/* Narrow viewports: split the row in two — type chip on top, title below,
   with the link icon pinned to the right. Keeps long titles readable on
   phones instead of squeezing them next to the type chip.
   The icon wrapper (not the svg) holds the absolute positioning so the
   svg's own transform stays free for the loading-spinner rotation. */
@media (max-width: 560px) {
    .aikc-chatbot__citation {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
        padding-right: 30px;
        position: relative;
    }
    .aikc-chatbot__citation-title { width: 100%; }
    .aikc-chatbot__citation-icon {
        position: absolute;
        right: 10px;
        top: 50%;
        transform: translateY(-50%);
    }
}

/* Feedback */
.aikc-chatbot__feedback { display: flex; gap: 6px; margin-top: 6px; }
.aikc-chatbot__feedback button {
    background: transparent; border: 1px solid var(--aikc-cb-panel-border);
    border-radius: 999px; padding: 2px 8px; font-size: 12px;
    color: var(--aikc-cb-panel-muted); cursor: pointer;
}
.aikc-chatbot__feedback button:hover  { color: var(--aikc-cb-panel-primary); border-color: var(--aikc-cb-panel-primary); }
.aikc-chatbot__feedback button.is-active { background: var(--aikc-cb-panel-primary); color: var(--aikc-cb-panel-user-text); border-color: var(--aikc-cb-panel-primary); }

/* Compose */
.aikc-chatbot__compose {
    border-top: 1px solid var(--aikc-cb-panel-border);
    padding: 10px;
    display: flex;
    gap: 8px;
    align-items: flex-end;
    background: var(--aikc-cb-panel-compose-bg);
}
.aikc-chatbot__compose textarea {
    flex: 1 1 auto;
    min-height: 72px;
    max-height: 140px;
    resize: none;
    border: 1px solid var(--aikc-cb-panel-border);
    border-radius: 10px;
    padding: 12px 14px;
    font-family: inherit;
    font-size: 14px;
    line-height: 1.45;
    background: var(--aikc-cb-panel-compose-bg);
    color: var(--aikc-cb-panel-text);
    outline: none;
    transition: border-color 140ms ease, background 140ms ease;
}
.aikc-chatbot__compose textarea:focus {
    border-color: var(--aikc-cb-panel-primary);
    background: var(--aikc-cb-panel-compose-bg);
}

.aikc-chatbot__send {
    border: 0 !important;
    /* Send button uses the same fill as the user-bubble — it represents the
       "I'm about to send a user message" affordance, so the colour should
       match what the user message looks like once posted. */
    background: var(--aikc-cb-panel-user-bg) !important;
    color: var(--aikc-cb-panel-user-text) !important;
    width: 40px !important;
    height: 40px !important;
    min-width: 40px !important;
    min-height: 40px !important;
    padding: 0 !important;
    border-radius: 10px !important;
    cursor: pointer !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex: 0 0 40px !important;
    box-shadow: none !important;
    text-shadow: none !important;
    line-height: 1 !important;
    font-size: 0 !important;
    outline: none;
    transition: transform 140ms ease, box-shadow 140ms ease;
}
.aikc-chatbot__send:hover,
.aikc-chatbot__send:focus {
    transform: scale(1.06);
    box-shadow: 0 6px 18px color-mix(in srgb, var(--aikc-cb-panel-primary) 35%, transparent) !important;
}
.aikc-chatbot__send:disabled { opacity: 0.5 !important; cursor: not-allowed !important; transform: none !important; }
.aikc-chatbot__send svg {
    width: 18px !important;
    height: 18px !important;
    display: block !important;
    stroke: currentColor !important;
    fill: none !important;
}

.aikc-chatbot__footer {
    font-size: 11px;
    color: var(--aikc-cb-panel-muted);
    text-align: center;
    padding: 6px 10px 10px;
    background: var(--aikc-cb-panel-compose-bg);
}

/* Mobile */
@media (max-width: 560px) {
    /* Pin panel to the *visual* viewport so it adapts to the browser's URL
       bar showing/hiding on iOS Safari and respects notch / home indicator
       safe areas. position:fixed + top+bottom lets the browser size the
       height between the actual visible edges, avoiding 100vh quirks. */
    .aikc-chatbot__panel,
    .aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__panel,
    .aikc-chatbot[data-pos="top-right"] .aikc-chatbot__panel,
    .aikc-chatbot[data-pos="top-left"] .aikc-chatbot__panel {
        position: fixed;
        top: max(8px, env(safe-area-inset-top, 8px));
        right: max(8px, env(safe-area-inset-right, 8px));
        bottom: max(8px, env(safe-area-inset-bottom, 8px));
        left: max(8px, env(safe-area-inset-left, 8px));
        width: auto;
        height: auto;
        max-width: none;
        max-height: none;
    }
    /* Larger, finger-friendly tap targets for header actions on mobile.
       32px is below the WCAG 44px minimum and was hard to dismiss reliably. */
    .aikc-chatbot__icon-btn {
        width: 44px !important;
        height: 44px !important;
        min-width: 44px !important;
        min-height: 44px !important;
    }
    .aikc-chatbot__icon-btn svg {
        width: 22px !important;
        height: 22px !important;
    }
    .aikc-chatbot__header-actions { gap: 6px; }
    /* Hide the floating bubble while the panel is open on mobile — it sits
       at bottom-right and would overlap the send button inside the panel.
       The X in the header is the close affordance on mobile. */
    .aikc-chatbot.is-open .aikc-chatbot__bubble,
    .aikc-chatbot.is-open .aikc-chatbot__tooltip {
        display: none !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Bubble themes (data-theme + shape/shadow/anim/border facets)
 *
 * Each preset sets a few of the existing CSS vars and overrides
 * `.aikc-chatbot__bubble` rules. The chat panel does NOT change with the
 * preset — only the bubble, the chooser-icon (which mirrors the bubble),
 * and the inline pill label are themed.
 * ═══════════════════════════════════════════════════════════════════════════ */

/* Pill label is invisible by default — themes that use shape="pill" reveal it
   via the [data-shape="pill"] rules below. */
.aikc-chatbot__bubble-label {
    display: none;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1;
    white-space: nowrap;
}

/* ─────────── Shape facet ─────────── */
.aikc-chatbot[data-shape="circle"] .aikc-chatbot__bubble  { border-radius: 50% !important; }
.aikc-chatbot[data-shape="squircle"] .aikc-chatbot__bubble { border-radius: 22% !important; }
.aikc-chatbot[data-shape="square"] .aikc-chatbot__bubble   { border-radius: 8% !important; }

/* Speech bubble: rounded squircle with a small tail at the bottom. The size
   is overridden to a non-1:1 ratio (64×56 visual) by using width var as base
   and capping height to 56/64 ratio. */
.aikc-chatbot[data-shape="speech"] .aikc-chatbot__bubble {
    border-radius: 22% !important;
    height: calc(var(--aikc-cb-bubble-size) * 0.875) !important;
    min-height: calc(var(--aikc-cb-bubble-size) * 0.875) !important;
    max-height: calc(var(--aikc-cb-bubble-size) * 0.875) !important;
    position: relative;
}
.aikc-chatbot[data-shape="speech"] .aikc-chatbot__bubble::after {
    content: "";
    position: absolute;
    bottom: -6px;
    left: 28%;
    width: 0;
    height: 0;
    border-left: 8px solid transparent;
    border-right: 8px solid transparent;
    border-top: 8px solid currentColor;
    /* Tail inherits the bubble's solid colour through currentColor. Themes
       that use gradient bubbles will need to paint this explicitly. */
}

/* Pill: width auto + horizontal padding + inline label visible.
   Height tracks --aikc-cb-bubble-size so the admin slider works on pill-cta
   exactly like on circle/squircle (QA req #14). We clamp the pill's height
   to ~0.81 of the bubble size to keep it visually a pill rather than a tall
   capsule (52 / 64 ≈ 0.81 — matches the previous look at the default size).
   The horizontal padding stays proportional via calc() so a larger pill keeps
   readable label whitespace. */
.aikc-chatbot[data-shape="pill"] .aikc-chatbot__bubble {
    border-radius: 999px !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    height:     calc(var(--aikc-cb-bubble-size) * 0.8125) !important;
    min-height: calc(var(--aikc-cb-bubble-size) * 0.8125) !important;
    max-height: calc(var(--aikc-cb-bubble-size) * 0.8125) !important;
    padding: calc(var(--aikc-cb-bubble-size) * 0.21875) calc(var(--aikc-cb-bubble-size) * 0.34375) !important;
    gap: 10px;
}
.aikc-chatbot[data-shape="pill"] .aikc-chatbot__bubble svg {
    /* Icon ~42% of pill height — sized off bubble-size so the SVG scales
       with the slider too, not locked to a hard 22px. */
    width:  calc(var(--aikc-cb-bubble-size) * 0.34375) !important;
    height: calc(var(--aikc-cb-bubble-size) * 0.34375) !important;
}
.aikc-chatbot[data-shape="pill"] .aikc-chatbot__bubble .aikc-chatbot__bubble-label {
    /* Label font scales with size so it stays proportional to the pill. */
    display: inline-block;
    font-size: calc(var(--aikc-cb-bubble-size) * 0.234375);
}

/* ─────────── Shadow facet ─────────── */
.aikc-chatbot[data-shadow="none"]   .aikc-chatbot__bubble { box-shadow: none !important; }
.aikc-chatbot[data-shadow="soft"]   .aikc-chatbot__bubble { box-shadow: 0 6px 16px rgba(15,23,42,0.15) !important; }
.aikc-chatbot[data-shadow="medium"] .aikc-chatbot__bubble { box-shadow: 0 10px 24px rgba(15,23,42,0.22) !important; }
.aikc-chatbot[data-shadow="strong"] .aikc-chatbot__bubble {
    /* Original legacy layered shadow. Kept identical to pre-theme behaviour. */
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.35),
        inset 0 -2px 6px rgba(0,0,0,0.10),
        0 18px 48px rgba(15, 23, 42, 0.22),
        0 0 0 0 rgba(59, 68, 181, 0.4) !important;
}
/* Colored shadow uses the primary colour mixed with alpha. */
.aikc-chatbot[data-shadow="colored"] .aikc-chatbot__bubble {
    box-shadow: 0 12px 32px color-mix(in srgb, var(--aikc-cb-primary) 35%, transparent) !important;
}
/* Hard-pixel: zero-blur offset; classic 8-bit. */
.aikc-chatbot[data-shadow="hard-pixel"] .aikc-chatbot__bubble {
    box-shadow: 4px 4px 0 #18181b !important;
}
/* Glow: large soft halo using accent. */
.aikc-chatbot[data-shadow="glow"] .aikc-chatbot__bubble {
    box-shadow: 0 0 30px color-mix(in srgb, var(--aikc-cb-accent) 50%, transparent) !important;
}

/* ─────────── Border facet ─────────── */
.aikc-chatbot[data-border="none"]  .aikc-chatbot__bubble { border: 0 !important; }
.aikc-chatbot[data-border="thin"]  .aikc-chatbot__bubble { border: 1px solid color-mix(in srgb, var(--aikc-cb-accent) 60%, transparent) !important; }
.aikc-chatbot[data-border="thick"] .aikc-chatbot__bubble { border: 2px solid var(--aikc-cb-primary) !important; }
.aikc-chatbot[data-border="gradient"] .aikc-chatbot__bubble {
    border: 2px solid transparent !important;
    background-clip: padding-box;
}

/* ─────────── Animation facet ─────────── */
.aikc-chatbot[data-anim="bounce"] .aikc-chatbot__bubble:not(.is-pulse) {
    animation: aikc-cb-theme-bounce 2.6s ease-in-out infinite;
}
@keyframes aikc-cb-theme-bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
}
.aikc-chatbot[data-anim="glow"] .aikc-chatbot__bubble:not(.is-pulse) {
    animation: aikc-cb-theme-glow 3.4s ease-in-out infinite;
}
@keyframes aikc-cb-theme-glow {
    0%, 100% { box-shadow: 0 0 16px color-mix(in srgb, var(--aikc-cb-accent) 35%, transparent); }
    50%      { box-shadow: 0 0 32px color-mix(in srgb, var(--aikc-cb-accent) 70%, transparent); }
}
.aikc-chatbot[data-anim="rotate-gradient"] .aikc-chatbot__bubble:not(.is-pulse) {
    background-size: 200% 200% !important;
    animation: aikc-cb-theme-rot 8s linear infinite;
}
@keyframes aikc-cb-theme-rot {
    0%   { background-position: 0% 0%; }
    100% { background-position: 200% 200%; }
}

/* ═══════════════ Per-theme blocks ═══════════════ */

/* 1. legacy — identical to the existing default look (kept for clarity). */
.aikc-chatbot[data-theme="legacy"] .aikc-chatbot__bubble {
    background:
        radial-gradient(circle at 30% 25%, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 55%),
        linear-gradient(135deg, var(--aikc-cb-primary) 0%, var(--aikc-cb-accent) 100%) !important;
    color: #fff !important;
}

/* 2. corporate-blue — flat solid + light shadow + scale hover. */
.aikc-chatbot[data-theme="corporate-blue"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #fff !important;
}
.aikc-chatbot[data-theme="corporate-blue"] .aikc-chatbot__bubble:hover {
    transform: scale(1.04);
    box-shadow: 0 12px 28px rgba(15,23,42,0.22) !important;
}

/* 3. playful-coral — radial coral/amber + bouncy wobble. */
.aikc-chatbot[data-theme="playful-coral"] .aikc-chatbot__bubble {
    background: radial-gradient(circle at 30% 30%, var(--aikc-cb-primary) 0%, var(--aikc-cb-accent) 100%) !important;
    color: #fff !important;
}
.aikc-chatbot[data-theme="playful-coral"] .aikc-chatbot__bubble:hover {
    animation: aikc-cb-wobble 600ms ease;
}
@keyframes aikc-cb-wobble {
    0%, 100% { transform: scale(1.1) rotate(0); }
    25%      { transform: scale(1.1) rotate(6deg); }
    75%      { transform: scale(1.1) rotate(-6deg); }
}

/* 4. dark-glass — dark navy + cyan glow + inner light.
   QA req #7: previously hardcoded #0f172a/#1e293b which ignored admin colour
   overrides. Now derives the gradient from --aikc-cb-primary so admins can
   re-tint (e.g. deep teal, oxblood). The 2nd stop is a lighter sibling
   produced via color-mix(primary + white) to keep the "glass highlight"
   look without locking the hue. */
.aikc-chatbot[data-theme="dark-glass"] .aikc-chatbot__bubble {
    background: linear-gradient(180deg,
        var(--aikc-cb-primary) 0%,
        color-mix(in srgb, var(--aikc-cb-primary) 78%, #ffffff) 100%) !important;
    color: var(--aikc-cb-accent) !important;
}
.aikc-chatbot[data-theme="dark-glass"] .aikc-chatbot__bubble:hover {
    box-shadow:
        0 0 40px color-mix(in srgb, var(--aikc-cb-accent) 70%, transparent),
        inset 0 0 12px color-mix(in srgb, var(--aikc-cb-accent) 25%, transparent) !important;
}

/* 5. speech-bubble — solid green squircle, tail points down. */
.aikc-chatbot[data-theme="speech-bubble"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #fff !important;
}
.aikc-chatbot[data-theme="speech-bubble"] .aikc-chatbot__bubble:hover {
    transform: scale(1.06);
}

/* 6. neumorphic — soft dual-tone shadow on neutral surface. */
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__bubble {
    background: #e7e9ee !important;
    color: var(--aikc-cb-accent) !important;
    box-shadow:
        8px 8px 16px #c8cad0,
        -8px -8px 16px #ffffff !important;
}
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__bubble:hover,
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__bubble:active {
    /* "Pressed" inset — visually inverts the shadow pair. */
    box-shadow:
        inset 6px 6px 12px #c8cad0,
        inset -6px -6px 12px #ffffff !important;
}

/* 7. gradient-sunset — animated 3-stop gradient (orange→pink→purple by
   default, but fully admin-tintable).
   QA req #7: previously hardcoded #f97316/#ec4899/#8b5cf6. Now stop 1 is
   --aikc-cb-primary, stop 3 is --aikc-cb-accent, and stop 2 is the perceptual
   midpoint produced via color-mix(primary, accent). Admins picking complementary
   brand colours get a credible sunset; picking dissonant ones get a softer
   2-tone since the midpoint averages them. */
.aikc-chatbot[data-theme="gradient-sunset"] .aikc-chatbot__bubble {
    background: linear-gradient(135deg,
        var(--aikc-cb-primary) 0%,
        color-mix(in srgb, var(--aikc-cb-primary) 50%, var(--aikc-cb-accent)) 50%,
        var(--aikc-cb-accent) 100%) !important;
    background-size: 200% 200% !important;
    color: #fff !important;
}
.aikc-chatbot[data-theme="gradient-sunset"] .aikc-chatbot__bubble:hover {
    transform: scale(1.08);
}

/* 8. mono-outline — transparent + black border + black icon, hover inverts. */
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__bubble {
    background: transparent !important;
    color: #0f172a !important;
    border: 2px solid #0f172a !important;
}
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__bubble svg {
    filter: none;
}
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__bubble:hover {
    background: #0f172a !important;
    color: #fff !important;
}

/* 9. pill-cta — solid indigo pill with inline "Ask AI". */
.aikc-chatbot[data-theme="pill-cta"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #fff !important;
}
.aikc-chatbot[data-theme="pill-cta"] .aikc-chatbot__bubble:hover {
    transform: scale(1.04);
    box-shadow: 0 14px 30px color-mix(in srgb, var(--aikc-cb-primary) 40%, transparent) !important;
}

/* 10. retro-pixel — flat amber square with crisp pixel shadow. */
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #18181b !important;
    border: 2px solid #18181b !important;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__bubble:hover,
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__bubble:active {
    /* "Press in" — bubble slides 2px down-right, shadow shrinks to match. */
    transform: translate(2px, 2px);
    box-shadow: 2px 2px 0 #18181b !important;
}

/* 11. midnight-luxe — dark slate gradient with warm gold accent. The `glow`
   shadow/animation facets already produce the gold halo via --aikc-cb-accent. */
.aikc-chatbot[data-theme="midnight-luxe"] .aikc-chatbot__bubble {
    background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%) !important;
    color: var(--aikc-cb-accent) !important;
}
.aikc-chatbot[data-theme="midnight-luxe"] .aikc-chatbot__bubble:hover {
    transform: scale(1.04);
    box-shadow: 0 0 36px rgba(240, 198, 116, 0.45) !important;
}

/* 12. wellness-mint — flat teal with a soft shadow + gentle hover scale. */
.aikc-chatbot[data-theme="wellness-mint"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #ffffff !important;
}
.aikc-chatbot[data-theme="wellness-mint"] .aikc-chatbot__bubble:hover {
    transform: scale(1.05);
    box-shadow: 0 10px 24px rgba(20, 184, 166, 0.32) !important;
}

/* 13. trust-navy — solid navy + clean lift hover. B2B sober. */
.aikc-chatbot[data-theme="trust-navy"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #ffffff !important;
}
.aikc-chatbot[data-theme="trust-navy"] .aikc-chatbot__bubble:hover {
    transform: scale(1.04);
    box-shadow: 0 12px 28px rgba(30, 58, 138, 0.32) !important;
}

/* 14. beauty-rose — pastel radial; shadow facet "colored" already paints the
   pink halo via primary, but we override the stop colours so the radial reads
   as petal-soft regardless of admin tint. */
.aikc-chatbot[data-theme="beauty-rose"] .aikc-chatbot__bubble {
    background: radial-gradient(circle at 30% 30%, var(--aikc-cb-primary) 0%, var(--aikc-cb-accent) 100%) !important;
    color: #ffffff !important;
    box-shadow: 0 12px 32px rgba(249, 168, 212, 0.35) !important;
}
.aikc-chatbot[data-theme="beauty-rose"] .aikc-chatbot__bubble:hover {
    transform: scale(1.05);
}

/* 15. action-red — high-contrast solid red with a coloured halo. The pulse
   animation is driven by .is-pulse (the global admin toggle); declaring
   animation:'pulse' in the preset is informational only. */
.aikc-chatbot[data-theme="action-red"] .aikc-chatbot__bubble {
    background: var(--aikc-cb-primary) !important;
    color: #ffffff !important;
    box-shadow: 0 10px 28px rgba(220, 38, 38, 0.40) !important;
}
.aikc-chatbot[data-theme="action-red"] .aikc-chatbot__bubble:hover {
    transform: scale(1.06);
    box-shadow: 0 14px 34px rgba(220, 38, 38, 0.55) !important;
}

/* 16. terminal — pure black square with neon-green outline. Hover inverts. */
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__bubble {
    background: #000000 !important;
    color: #00ff88 !important;
    border: 2px solid #00ff88 !important;
}
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__bubble:hover {
    background: #00ff88 !important;
    color: #000000 !important;
}

/* 17. cyber-violet — neon violet→magenta gradient with a constant glow. */
.aikc-chatbot[data-theme="cyber-violet"] .aikc-chatbot__bubble {
    background: linear-gradient(135deg, #a855f7 0%, #ec4899 100%) !important;
    color: #ffffff !important;
    box-shadow: 0 0 32px rgba(168, 85, 247, 0.55) !important;
}
.aikc-chatbot[data-theme="cyber-violet"] .aikc-chatbot__bubble:hover {
    transform: scale(1.06);
    box-shadow: 0 0 44px rgba(168, 85, 247, 0.75) !important;
}

/* 18. editorial-serif — black bubble + gold thin border. */
.aikc-chatbot[data-theme="editorial-serif"] .aikc-chatbot__bubble {
    background: #1a1a1a !important;
    color: var(--aikc-cb-accent) !important;
    border: 2px solid var(--aikc-cb-accent) !important;
}
.aikc-chatbot[data-theme="editorial-serif"] .aikc-chatbot__bubble:hover {
    transform: scale(1.04);
}

/* 19. iconic-mini — no background, no shadow, no border. Just the icon.
   The bubble's base !important rules are overridden by these. The bubble
   svg already fills 100% (see base rule); we keep it for clarity. */
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__bubble {
    background: transparent !important;
    color: var(--aikc-cb-primary) !important;
    box-shadow: none !important;
    border: 0 !important;
}
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__bubble svg {
    /* Drop the soft drop-shadow filter so the icon reads as a pure mark. */
    filter: none !important;
}
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__bubble:hover {
    transform: scale(1.08);
    color: color-mix(in srgb, var(--aikc-cb-primary) 70%, #6366f1) !important;
}

/* 20. glassmorphism — frosted bubble + frosted panel. */
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__bubble {
    background: rgba(255, 255, 255, 0.4) !important;
    color: #0f172a !important;
    border: 1px solid rgba(255, 255, 255, 0.6) !important;
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
}
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__bubble:hover {
    transform: scale(1.05);
    background: rgba(255, 255, 255, 0.55) !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * Panel palette per preset (D-iter)
 *
 * Each preset declares the chat-panel CSS vars its CSS palette needs. The
 * panel-aware rules above (.aikc-chatbot__header, __messages, __msg--user,
 * __msg--assistant, __compose, __send, __citation, etc.) read these vars
 * exclusively — no panel rule hardcodes a colour. Result: switching preset
 * recolours the whole panel, not just the bubble.
 *
 * The admin's own primary/accent/surface "Colors" inputs continue to feed
 * --aikc-cb-panel-primary/-accent/-surface via inline-style on the root
 * (set by widget.js applyAppearance). Those THREE vars are admin-overridable;
 * everything else here is preset-only by design — exposing 9+ colour pickers
 * to the admin per preset would explode the UI for marginal benefit, and the
 * preset palettes are already vetted for WCAG AA contrast.
 *
 * Note on cascade: each [data-theme="X"] block below uses single-class
 * specificity so the JS inline-style overrides for panel-primary/-accent/
 * -surface still win. The non-overridable vars (header-bg, user-bg,
 * assistant-bg, etc.) are set here and stay set unless replaced by a future
 * "advanced customisation" pane. ═════════════════════════════════════════ */

/* legacy — gradient header + indigo→magenta user bubbles. Identical to v1
   defaults so existing sites see zero visual change after this iteration. */
.aikc-chatbot[data-theme="legacy"] {
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #3b44b5 0%, #923472 100%);
    --aikc-cb-panel-surface:        #f5f5f7;
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #64748b;
    --aikc-cb-panel-user-bg:        linear-gradient(135deg, #3b44b5 0%, #923472 100%);
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         #e5e7eb;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* corporate-blue — solid blue header + off-white assistant bubbles. */
.aikc-chatbot[data-theme="corporate-blue"] {
    --aikc-cb-panel-header-bg:      #1f4ed8;
    --aikc-cb-panel-surface:        #ffffff;
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #475569;
    --aikc-cb-panel-user-bg:        #1f4ed8;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #f5f7fb;
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         #dbe2ed;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* playful-coral — warm gradient + brown text on cream. */
.aikc-chatbot[data-theme="playful-coral"] {
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #ff6b6b 0%, #ffd166 100%);
    --aikc-cb-panel-surface:        #fff7f0;
    --aikc-cb-panel-text:           #3b2a1f;
    --aikc-cb-panel-muted:          #8a6b5a;
    --aikc-cb-panel-user-bg:        linear-gradient(135deg, #ff6b6b 0%, #ffd166 100%);
    --aikc-cb-panel-user-text:      #3b2a1f;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #3b2a1f;
    --aikc-cb-panel-border:         #fce4cf;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* dark-glass — dark navy surface + cyan user bubble. Only true-dark preset. */
.aikc-chatbot[data-theme="dark-glass"] {
    --aikc-cb-panel-header-bg:      #0f172a;
    --aikc-cb-panel-surface:        #1e293b;
    --aikc-cb-panel-text:           #f1f5f9;
    --aikc-cb-panel-muted:          #94a3b8;
    --aikc-cb-panel-user-bg:        #38bdf8;
    --aikc-cb-panel-user-text:      #0f172a;
    --aikc-cb-panel-assistant-bg:   #1e293b;
    --aikc-cb-panel-assistant-text: #f1f5f9;
    --aikc-cb-panel-border:         #334155;
    --aikc-cb-panel-compose-bg:     #0f172a;
}

/* speech-bubble — green CTA + soft mint surface. */
.aikc-chatbot[data-theme="speech-bubble"] {
    --aikc-cb-panel-header-bg:      #16a34a;
    --aikc-cb-panel-surface:        #f4faf6;
    --aikc-cb-panel-text:           #0f1f15;
    --aikc-cb-panel-muted:          #5d6b62;
    --aikc-cb-panel-user-bg:        #16a34a;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #0f1f15;
    --aikc-cb-panel-border:         #d4e7da;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* neumorphic — monochrome paper. Border is transparent so the soft shadow
   pair below acts as the visual edge. */
.aikc-chatbot[data-theme="neumorphic"] {
    --aikc-cb-panel-header-bg:      #e7e9ee;
    --aikc-cb-panel-surface:        #e7e9ee;
    --aikc-cb-panel-text:           #1e293b;
    --aikc-cb-panel-muted:          #64748b;
    --aikc-cb-panel-user-bg:        #cdd0d8;
    --aikc-cb-panel-user-text:      #1e293b;
    --aikc-cb-panel-assistant-bg:   #e7e9ee;
    --aikc-cb-panel-assistant-text: #1e293b;
    --aikc-cb-panel-border:         transparent;
    --aikc-cb-panel-compose-bg:     #ffffff;
}
/* Header text on neumorphic is dark (matches body), not the default white.
   Override here because the user-text var = dark too. */
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__header {
    color: var(--aikc-cb-panel-text);
}
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__icon-btn {
    color: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__icon-btn svg {
    stroke: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="neumorphic"] .aikc-chatbot__msg--assistant {
    /* Border transparent — replace with a soft neumorphic shadow pair so
       assistant bubbles still read as cards on the matching surface. */
    box-shadow: 2px 2px 6px #c8cad0, -2px -2px 6px #ffffff;
}

/* gradient-sunset — peach→pink header on white panel. */
.aikc-chatbot[data-theme="gradient-sunset"] {
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #f97316 0%, #ec4899 100%);
    --aikc-cb-panel-surface:        #ffffff;
    --aikc-cb-panel-text:           #1f1330;
    --aikc-cb-panel-muted:          #6b5475;
    --aikc-cb-panel-user-bg:        linear-gradient(135deg, #f97316 0%, #ec4899 100%);
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #fdf2f8;
    --aikc-cb-panel-assistant-text: #1f1330;
    --aikc-cb-panel-border:         #fce7f3;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* mono-outline — pure b&w with hard rules. */
.aikc-chatbot[data-theme="mono-outline"] {
    --aikc-cb-panel-header-bg:      #ffffff;
    --aikc-cb-panel-surface:        #ffffff;
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #4b5563;
    --aikc-cb-panel-user-bg:        #0f172a;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         #0f172a;
    --aikc-cb-panel-compose-bg:     #ffffff;
}
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__header {
    /* White header on dark text needs an explicit divider line for the
       editorial vibe — the var pattern would never produce a 2px solid. */
    color: var(--aikc-cb-panel-text);
    border-bottom: 2px solid #0f172a;
}
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__icon-btn {
    color: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__icon-btn svg {
    stroke: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__msg--assistant {
    border: 1px solid #0f172a;
}

/* pill-cta — indigo header on white. */
.aikc-chatbot[data-theme="pill-cta"] {
    --aikc-cb-panel-header-bg:      #6366f1;
    --aikc-cb-panel-surface:        #ffffff;
    --aikc-cb-panel-text:           #1e293b;
    --aikc-cb-panel-muted:          #64748b;
    --aikc-cb-panel-user-bg:        #6366f1;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #f5f5fb;
    --aikc-cb-panel-assistant-text: #1e293b;
    --aikc-cb-panel-border:         #e0e2f0;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* retro-pixel — amber + black hard rules, 8-bit shadow on send button. */
.aikc-chatbot[data-theme="retro-pixel"] {
    --aikc-cb-panel-header-bg:      #fbbf24;
    --aikc-cb-panel-surface:        #fffbeb;
    --aikc-cb-panel-text:           #18181b;
    --aikc-cb-panel-muted:          #57534e;
    --aikc-cb-panel-user-bg:        #18181b;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #18181b;
    --aikc-cb-panel-border:         #18181b;
    --aikc-cb-panel-compose-bg:     #ffffff;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__header {
    color: var(--aikc-cb-panel-text);
    border-bottom: 4px solid #18181b;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__icon-btn {
    color: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__icon-btn svg {
    stroke: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__msg--assistant {
    border: 2px solid #18181b;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__compose textarea {
    border: 2px solid #18181b;
}
.aikc-chatbot[data-theme="retro-pixel"] .aikc-chatbot__send {
    border: 2px solid #18181b !important;
    border-radius: 0 !important;
    box-shadow: 3px 3px 0 #18181b !important;
}

/* midnight-luxe — dark slate + warm gold, glow shadow. WCAG AA: #f5e9d0 on
   #2d2d2d ≈ 12:1, #f5e9d0 on #1a1a1a ≈ 14:1. */
.aikc-chatbot[data-theme="midnight-luxe"] {
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
    --aikc-cb-panel-surface:        #1a1a1a;
    --aikc-cb-panel-text:           #f5e9d0;
    --aikc-cb-panel-muted:          #a89770;
    --aikc-cb-panel-user-bg:        #f0c674;
    --aikc-cb-panel-user-text:      #1a1a1a;
    --aikc-cb-panel-assistant-bg:   #2d2d2d;
    --aikc-cb-panel-assistant-text: #f5e9d0;
    --aikc-cb-panel-border:         #4a3f2a;
    --aikc-cb-panel-compose-bg:     #1a1a1a;
}

/* wellness-mint — teal header + mint surface. Body text deep teal on light. */
.aikc-chatbot[data-theme="wellness-mint"] {
    --aikc-cb-panel-header-bg:      #14b8a6;
    --aikc-cb-panel-surface:        #f0fdfa;
    --aikc-cb-panel-text:           #134e4a;
    --aikc-cb-panel-muted:          #5f7e7c;
    --aikc-cb-panel-user-bg:        #14b8a6;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #134e4a;
    --aikc-cb-panel-border:         #ccfbf1;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* trust-navy — navy header + slate body. */
.aikc-chatbot[data-theme="trust-navy"] {
    --aikc-cb-panel-header-bg:      #1e3a8a;
    --aikc-cb-panel-surface:        #ffffff;
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #475569;
    --aikc-cb-panel-user-bg:        #1e3a8a;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #f1f5f9;
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         #cbd5e1;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* beauty-rose — pastel gradient header + warm plum body on cream. */
.aikc-chatbot[data-theme="beauty-rose"] {
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #f9a8d4 0%, #fce7f3 100%);
    --aikc-cb-panel-surface:        #fff5f7;
    --aikc-cb-panel-text:           #4a1a3a;
    --aikc-cb-panel-muted:          #8a5a72;
    --aikc-cb-panel-user-bg:        linear-gradient(135deg, #f9a8d4 0%, #fce7f3 100%);
    --aikc-cb-panel-user-text:      #4a1a3a;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #4a1a3a;
    --aikc-cb-panel-border:         #fbcfe8;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* action-red — solid red header. White-on-red user bubbles for max CTA energy. */
.aikc-chatbot[data-theme="action-red"] {
    --aikc-cb-panel-header-bg:      #dc2626;
    --aikc-cb-panel-surface:        #ffffff;
    --aikc-cb-panel-text:           #1f1413;
    --aikc-cb-panel-muted:          #6b4747;
    --aikc-cb-panel-user-bg:        #dc2626;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #1f1413;
    --aikc-cb-panel-border:         #fca5a5;
    --aikc-cb-panel-compose-bg:     #ffffff;
}

/* terminal — pure black surface + neon green text everywhere. */
.aikc-chatbot[data-theme="terminal"] {
    --aikc-cb-panel-header-bg:      #000000;
    --aikc-cb-panel-surface:        #000000;
    --aikc-cb-panel-text:           #00ff88;
    --aikc-cb-panel-muted:          #00cc6f;
    --aikc-cb-panel-user-bg:        #00ff88;
    --aikc-cb-panel-user-text:      #000000;
    --aikc-cb-panel-assistant-bg:   #0a0a0a;
    --aikc-cb-panel-assistant-text: #00ff88;
    --aikc-cb-panel-border:         #00ff88;
    --aikc-cb-panel-compose-bg:     #000000;
}
/* Monospace everywhere in the panel — including bubble, title, subtitle,
   messages, compose textarea, footer. Set at the widget root so cascade
   carries it to every descendant without per-element rules. The base widget
   var (--aikc-cb-font) is replaced with the mono stack just for this preset.
   No !important needed: nothing else in the file targets font-family on the
   same selector specificity. */
.aikc-chatbot[data-theme="terminal"] {
    --aikc-cb-font: "Courier New", "Consolas", ui-monospace, monospace;
    font-family: var(--aikc-cb-font);
}
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__bubble,
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__panel,
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__header,
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__msg,
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__compose textarea,
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__footer {
    font-family: "Courier New", "Consolas", ui-monospace, monospace;
}
/* Terminal aesthetic: solid neon-green divider lines on header, assistant
   messages, and compose. Reads as a CLI window border. */
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__header {
    border-bottom: 2px solid #00ff88;
}
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__msg--assistant {
    border: 2px solid #00ff88;
}
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__compose {
    border-top: 2px solid #00ff88;
}
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__compose textarea {
    border: 2px solid #00ff88;
}
.aikc-chatbot[data-theme="terminal"] .aikc-chatbot__icon-btn svg {
    stroke: #00ff88 !important;
}

/* cyber-violet — neon gradient header, deep violet surface. Text needs to be
   light on dark; #f3e8ff on #1a0a2e ≈ 13:1, on #2a1444 ≈ 11:1. */
.aikc-chatbot[data-theme="cyber-violet"] {
    --aikc-cb-panel-header-bg:      linear-gradient(135deg, #a855f7 0%, #ec4899 100%);
    --aikc-cb-panel-surface:        #1a0a2e;
    --aikc-cb-panel-text:           #f3e8ff;
    --aikc-cb-panel-muted:          #9d8bb0;
    --aikc-cb-panel-user-bg:        linear-gradient(135deg, #a855f7 0%, #ec4899 100%);
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #2a1444;
    --aikc-cb-panel-assistant-text: #f3e8ff;
    --aikc-cb-panel-border:         #6b21a8;
    --aikc-cb-panel-compose-bg:     #1a0a2e;
}

/* editorial-serif — black header + cream surface with a gold rule. */
.aikc-chatbot[data-theme="editorial-serif"] {
    --aikc-cb-panel-header-bg:      #1a1a1a;
    --aikc-cb-panel-surface:        #fdfbf4;
    --aikc-cb-panel-text:           #1a1a1a;
    --aikc-cb-panel-muted:          #6b5d4f;
    --aikc-cb-panel-user-bg:        #1a1a1a;
    --aikc-cb-panel-user-text:      #fdfbf4;
    --aikc-cb-panel-assistant-bg:   #fdfbf4;
    --aikc-cb-panel-assistant-text: #1a1a1a;
    --aikc-cb-panel-border:         #b8965f;
    --aikc-cb-panel-compose-bg:     #ffffff;
}
/* Serif only on title + subtitle. Body, messages, compose stay on the default
   sans stack — editorial-style brands want a serif headline over sans body. */
.aikc-chatbot[data-theme="editorial-serif"] .aikc-chatbot__title,
.aikc-chatbot[data-theme="editorial-serif"] .aikc-chatbot__subtitle {
    font-family: Georgia, "Times New Roman", "Iowan Old Style", serif;
}
.aikc-chatbot[data-theme="editorial-serif"] .aikc-chatbot__title {
    letter-spacing: 0.01em;
}
.aikc-chatbot[data-theme="editorial-serif"] .aikc-chatbot__msg--assistant {
    /* Gold rule echoes the bubble border for a print-magazine feel. */
    border: 1px solid #b8965f;
}

/* iconic-mini — barely-there panel. Header has no fill, so the title needs an
   explicit dark colour because the global header rule uses user-text (white
   by default). Same for the close/icon buttons. */
.aikc-chatbot[data-theme="iconic-mini"] {
    --aikc-cb-panel-header-bg:      #ffffff;
    --aikc-cb-panel-surface:        #fafafa;
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #6b7280;
    --aikc-cb-panel-user-bg:        #0f172a;
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   #ffffff;
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         #e5e7eb;
    --aikc-cb-panel-compose-bg:     #fafafa;
}
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__header {
    color: var(--aikc-cb-panel-text);
    border-bottom: 1px solid #e5e7eb;
}
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__title {
    /* The widget root .aikc-chatbot { color: ...-panel-text } already inherits;
       set explicitly so a white header can't accidentally bleed white text in. */
    color: #0f172a;
}
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__icon-btn {
    color: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="iconic-mini"] .aikc-chatbot__icon-btn svg {
    stroke: var(--aikc-cb-panel-text) !important;
}

/* glassmorphism — frosted everything. backdrop-filter requires the underlying
   element to be semitransparent (rgba) and the browser to support filter
   acceleration; we set both prefixed forms so Safari/older Chromium tints
   render too. */
.aikc-chatbot[data-theme="glassmorphism"] {
    --aikc-cb-panel-header-bg:      rgba(255, 255, 255, 0.7);
    --aikc-cb-panel-surface:        rgba(255, 255, 255, 0.7);
    --aikc-cb-panel-text:           #0f172a;
    --aikc-cb-panel-muted:          #475569;
    --aikc-cb-panel-user-bg:        rgba(99, 102, 241, 0.85);
    --aikc-cb-panel-user-text:      #ffffff;
    --aikc-cb-panel-assistant-bg:   rgba(255, 255, 255, 0.85);
    --aikc-cb-panel-assistant-text: #0f172a;
    --aikc-cb-panel-border:         rgba(255, 255, 255, 0.4);
    --aikc-cb-panel-compose-bg:     rgba(255, 255, 255, 0.5);
}
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__panel,
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__header,
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__messages,
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__compose,
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__footer {
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    backdrop-filter: blur(16px) saturate(180%);
}
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__msg--assistant {
    -webkit-backdrop-filter: blur(8px) saturate(160%);
    backdrop-filter: blur(8px) saturate(160%);
}
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__header {
    color: var(--aikc-cb-panel-text);
    border-bottom: 1px solid rgba(255, 255, 255, 0.4);
}
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__icon-btn {
    color: var(--aikc-cb-panel-text) !important;
}
.aikc-chatbot[data-theme="glassmorphism"] .aikc-chatbot__icon-btn svg {
    stroke: var(--aikc-cb-panel-text) !important;
}

/* Sizing tweaks for icons that benefit from a smaller draw box. The base
   .aikc-chatbot__bubble svg rule sets width/height:100% — these blocks just
   pull it in a bit. */
.aikc-chatbot[data-theme="mono-outline"] .aikc-chatbot__bubble svg,
.aikc-chatbot[data-theme="dark-glass"]   .aikc-chatbot__bubble svg,
.aikc-chatbot[data-theme="neumorphic"]   .aikc-chatbot__bubble svg {
    width: 60% !important;
    height: 60% !important;
    filter: none;
}

/* When pill shape is active the SVG sizing rule above is overridden by the
   shape rule (22px). */

/* Reduced-motion: silence theme idle animations that are decorative. The
   global .is-pulse keyframes already opt out via the existing media block. */
@media (prefers-reduced-motion: reduce) {
    .aikc-chatbot[data-anim="bounce"]          .aikc-chatbot__bubble,
    .aikc-chatbot[data-anim="glow"]            .aikc-chatbot__bubble,
    .aikc-chatbot[data-anim="rotate-gradient"] .aikc-chatbot__bubble,
    .aikc-chatbot[data-theme="playful-coral"]  .aikc-chatbot__bubble,
    .aikc-chatbot[data-theme="dark-glass"]     .aikc-chatbot__bubble,
    .aikc-chatbot[data-theme="gradient-sunset"] .aikc-chatbot__bubble,
    .aikc-chatbot[data-theme="retro-pixel"]    .aikc-chatbot__bubble {
        animation: none !important;
    }
}

/* ───────────────────────────────────────────────────────────────────────
   v3: 9 BUBBLE ENTRY animations + 8 new PANEL OPEN animations.

   Entry animations fire exactly once when the bubble mounts (page load).
   They run independently of `.is-pulse`/the per-theme idle animation —
   each pair is layered: entry first, then idle takes over. Because every
   entry keyframe ends at the natural identity transform (`opacity:1;
   transform: none;`) and we don't set `forwards`, the bubble settles
   onto the idle keyframes without a visible jump.

   Each rule scopes to `.aikc-chatbot[data-bubble-enter="<slug>"]
   .aikc-chatbot__bubble` so the per-preset attribute (set by JS via
   AIKC_Themes::ENTRY_ANIMS) drives the right keyframe.
   ─────────────────────────────────────────────────────────────────────── */

/* `none` is intentionally absent — the default state has no animation.

   Co-existence with `.is-pulse` and per-preset idle animations: each
   entry rule below sets the bubble's `animation` shorthand, which in
   the CSS cascade fully replaces the `is-pulse` two-animation shorthand
   declared in the global block at line ~133. To restore the idle pulse
   AFTER the entry completes we add a sibling rule that matches BOTH
   `data-bubble-enter="<slug>"` AND `.is-pulse`, layering entry + the
   two pulse keyframes with an animation-delay on the latter so pulse
   only kicks in after entry settles. Per-preset idle animations
   (bounce/glow/rotate-gradient, defined in the per-preset blocks)
   declare a single-name `animation` and DO get clobbered briefly during
   the entry — accepted trade-off, since the entry itself is a richer
   reveal than the idle loop.
*/

/* v4 entry delay: each rule that previously used `both` now also reads the
   `--aikc-cb-entry-delay` custom property (default 0ms, set by the JS when
   the admin configured a non-zero delay). `both` is shorthand for `backwards
   forwards`, so during the delay the bubble holds its 0% frame (opacity:0 on
   every entry keyframe) — invisible to the visitor. The pulse + bob channels
   on the .is-pulse rules add `calc(var(--aikc-cb-entry-delay,0ms) + <entry_duration>)`
   so the idle pulse only kicks in AFTER the entry settles, even with a
   delay. Without the calc(), pulse would tick away invisibly during the
   delay and start mid-cycle when the bubble finally appears. */
.aikc-chatbot[data-bubble-enter="fade"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-fade 360ms ease both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="fade"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-fade 360ms ease both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 360ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 360ms);
}
@keyframes aikc-cb-enter-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* `data-bubble-enter="none"` with a configured delay still needs to hide
   the bubble during the wait — otherwise the admin's "wait 5s before showing"
   intent leaks. We reuse the aikc-cb-enter-fade keyframe at 1ms duration so
   the visual is "invisible for delay → instantly visible", matching the
   "none" semantic (no perceptible entry animation, just a delayed appearance).
   When `--aikc-cb-entry-delay` is 0 / unset, the 1ms fade is imperceptible —
   indistinguishable from the pre-v4 behaviour. */
.aikc-chatbot[data-bubble-enter="none"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-fade 1ms linear both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="none"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-fade 1ms linear both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 1ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 1ms);
}

.aikc-chatbot[data-bubble-enter="spring-pop"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-spring-pop 480ms cubic-bezier(.34, 1.56, .64, 1) both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="spring-pop"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-spring-pop 480ms cubic-bezier(.34, 1.56, .64, 1) both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 480ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 480ms);
}
@keyframes aikc-cb-enter-spring-pop {
    0%   { opacity: 0; transform: scale(0); }
    50%  { opacity: 1; transform: scale(1.15); }
    75%  { transform: scale(0.95); }
    100% { transform: scale(1); }
}

.aikc-chatbot[data-bubble-enter="magnetic-slide"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-magnetic-slide 600ms cubic-bezier(.2, .9, .3, 1.1) both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="magnetic-slide"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-magnetic-slide 600ms cubic-bezier(.2, .9, .3, 1.1) both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 600ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 600ms);
}
@keyframes aikc-cb-enter-magnetic-slide {
    0%   { opacity: 0; transform: translate(120%, 30%) rotate(15deg); }
    100% { opacity: 1; transform: translate(0, 0) rotate(0); }
}

.aikc-chatbot[data-bubble-enter="iris-zoom"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-iris-zoom 500ms ease-out both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="iris-zoom"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-iris-zoom 500ms ease-out both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 500ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 500ms);
}
@keyframes aikc-cb-enter-iris-zoom {
    0%   { opacity: 0; clip-path: circle(0% at center); }
    100% { opacity: 1; clip-path: circle(75% at center); }
}

@keyframes aikc-cb-enter-liquid-blob {
    /* Per CSS Animations spec, `!important` inside a keyframe is invalid
       and silently dropped. To make the morphing border-radius actually
       override the per-preset `data-shape` rules (which DO use !important
       on border-radius), we declare the morph radii on the bubble
       container at a higher specificity — see the static rule directly
       below this keyframe. The keyframe values then animate THROUGH the
       intermediate radii using `transform` and `opacity` (which have no
       !important conflict). The morph itself is visually carried by the
       static `border-radius` value tweening to/from `50%`. */
    0%   { opacity: 0; transform: scale(0.7); }
    50%  { opacity: 1; transform: scale(1.05); }
    100% { opacity: 1; transform: scale(1); }
}
/* High-specificity override that beats the data-shape !important rule
   only while the liquid-blob entry is active. Animation runs once on
   mount and the rule remains in effect afterwards — visually a no-op
   because `50%` happens to be the circle shape's resolved value. For
   non-circle shapes we accept the visual "rounding off to a circle"
   during the brief entry — same outcome as the original liquid-blob
   brief, which described it as a circular morph. */
.aikc-chatbot[data-bubble-enter="liquid-blob"] .aikc-chatbot__bubble {
    border-radius: 50% !important;
    /* Layer a second animation that morphs through irregular radii via
       `clip-path` (no !important conflict on this property). */
    animation: aikc-cb-enter-liquid-blob 700ms ease-out both,
               aikc-cb-enter-liquid-blob-clip 700ms ease-out both;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="liquid-blob"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-liquid-blob 700ms ease-out both,
        aikc-cb-enter-liquid-blob-clip 700ms ease-out both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 700ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 700ms);
}
@keyframes aikc-cb-enter-liquid-blob-clip {
    0%   { clip-path: inset(0% round 40% 60% 60% 40% / 60% 40% 60% 40%); }
    50%  { clip-path: inset(0% round 60% 40% 40% 60% / 40% 60% 40% 60%); }
    100% { clip-path: inset(0% round 50%); }
}

.aikc-chatbot[data-bubble-enter="glitch-reveal"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-glitch-reveal 600ms steps(4, end) both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
.aikc-chatbot[data-bubble-enter="glitch-reveal"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-glitch-reveal 600ms steps(4, end) both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 600ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 600ms);
}
@keyframes aikc-cb-enter-glitch-reveal {
    0%   { opacity: 0; transform: translate( 3px, -2px); filter: hue-rotate(0deg); }
    25%  { opacity: 1; transform: translate(-3px,  2px); filter: hue-rotate(90deg); }
    50%  { opacity: 1; transform: translate( 2px,  3px); filter: hue-rotate(180deg); }
    75%  { opacity: 1; transform: translate(-2px, -3px); filter: hue-rotate(270deg); }
    100% { opacity: 1; transform: translate(0, 0);      filter: hue-rotate(0deg); }
}

/* beam-in: pseudo-element fires a vertical line that expands horizontally
   while the bubble fades in with a small delay. The bubble itself uses
   `aikc-cb-enter-beam-bubble`; the beam runs from `::before`. We set
   `position: relative` on the bubble so the absolute beam anchors there
   (the bubble is already a button — position works fine). */
.aikc-chatbot[data-bubble-enter="beam-in"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-beam-bubble 800ms ease-out both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
    position: relative;
    overflow: visible;
}
.aikc-chatbot[data-bubble-enter="beam-in"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-beam-bubble 800ms ease-out both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 800ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 800ms);
}
.aikc-chatbot[data-bubble-enter="beam-in"] .aikc-chatbot__bubble::before {
    content: '';
    position: absolute;
    left: 50%;
    top: -10%;
    width: 2px;
    height: 120%;
    background: currentColor;
    /* Lift above the bubble surface so the line is visible against the
       bubble's gradient/solid fill. */
    transform: translateX(-50%) scaleY(0);
    transform-origin: center;
    opacity: 0.9;
    pointer-events: none;
    animation: aikc-cb-enter-beam-line 800ms ease-out both;
    /* The beam pseudo-element must wait for the same entry-delay so the
       laser stays hidden until the bubble is about to reveal. `both` already
       holds the 0% frame (scaleY(0) → invisible) during the delay. */
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
@keyframes aikc-cb-enter-beam-bubble {
    0%, 25% { opacity: 0; transform: scale(0.9); }
    /* Bubble enters at the 200ms mark (25% of 800ms) — gives the beam
       enough lead-in to read as a "scan that materialises the bubble". */
    60%     { opacity: 1; transform: scale(1.02); }
    100%    { opacity: 1; transform: scale(1); }
}
@keyframes aikc-cb-enter-beam-line {
    0%   { transform: translateX(-50%) scaleY(0); width: 2px; opacity: 0.9; }
    25%  { transform: translateX(-50%) scaleY(1); width: 2px; opacity: 0.9; }
    60%  { transform: translateX(-50%) scaleY(1); width: 140%; opacity: 0.6; }
    100% { transform: translateX(-50%) scaleY(1); width: 0%;   opacity: 0; }
}

/* particle-assemble: 8 coloured points converge to the bubble centre.
   Because the bubble's static `box-shadow` is pinned `!important` by
   the per-preset rules (and `!important` in keyframes is invalid per
   spec), we render the particles on a sibling `::after` pseudo-element
   that we DO control end-to-end. The bubble itself just scales up. */
.aikc-chatbot[data-bubble-enter="particle-assemble"] .aikc-chatbot__bubble {
    animation: aikc-cb-enter-particle-assemble 700ms ease-out both;
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
    position: relative;
    overflow: visible;
}
.aikc-chatbot[data-bubble-enter="particle-assemble"] .aikc-chatbot__bubble.is-pulse {
    animation:
        aikc-cb-enter-particle-assemble 700ms ease-out both,
        aikc-cb-pulse 2.2s ease-in-out infinite,
        aikc-cb-bob 3.6s ease-in-out infinite;
    animation-delay:
        var(--aikc-cb-entry-delay, 0ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 700ms),
        calc(var(--aikc-cb-entry-delay, 0ms) + 700ms);
}
.aikc-chatbot[data-bubble-enter="particle-assemble"] .aikc-chatbot__bubble::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: transparent;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 2;
    /* 8 coloured points spread in a rough circle around the bubble;
       the keyframe converges them all to origin (0 0). box-shadow on
       a pseudo-element has NO !important conflict here. */
    animation: aikc-cb-enter-particle-assemble-dots 700ms ease-out both;
    /* Match the bubble's delay so the particles don't spawn during the
       wait period. The 0% keyframe has box-shadow on the 8 dots but the
       parent bubble is at opacity:0 during the delay anyway — strict
       layering: hidden until the bubble starts revealing. */
    animation-delay: var(--aikc-cb-entry-delay, 0ms);
}
@keyframes aikc-cb-enter-particle-assemble {
    0%   { opacity: 0; transform: scale(0.4); }
    60%  { opacity: 1; transform: scale(1.05); }
    100% { opacity: 1; transform: scale(1); }
}
@keyframes aikc-cb-enter-particle-assemble-dots {
    0% {
        opacity: 1;
        box-shadow:
             16px  20px 0 1px #ff6b6b,
            -18px  12px 0 1px #38bdf8,
             22px -14px 0 1px #fbbf24,
            -20px -16px 0 1px #a855f7,
              0px  26px 0 1px #14b8a6,
              0px -24px 0 1px #ec4899,
             24px   2px 0 1px #f97316,
            -24px   4px 0 1px #6366f1;
    }
    100% {
        opacity: 0;
        box-shadow: 0 0 0 0 transparent;
    }
}

/* ───────────────────────────────────────────────────────────────────────
   v3: 8 new PANEL OPEN effects. The 4 originals (slide/fade/bounce/none)
   stay where they were; everything below is additive.
   ─────────────────────────────────────────────────────────────────────── */

.aikc-chatbot__panel.is-open[data-effect="iris-dilate"] {
    animation: aikc-cb-open-iris-dilate 480ms ease-out;
}
@keyframes aikc-cb-open-iris-dilate {
    /* Default origin = bottom-right (matches the default bubble corner).
       Per-position overrides below adjust the `at X Y` coordinates so the
       iris always grows from the corner closest to the bubble. */
    from { opacity: 0; clip-path: circle(0% at calc(100% - 32px) calc(100% - 32px)); }
    to   { opacity: 1; clip-path: circle(150% at calc(100% - 32px) calc(100% - 32px)); }
}
.aikc-chatbot[data-pos="bottom-left"] .aikc-chatbot__panel.is-open[data-effect="iris-dilate"] {
    animation-name: aikc-cb-open-iris-dilate-bl;
}
@keyframes aikc-cb-open-iris-dilate-bl {
    from { opacity: 0; clip-path: circle(0% at 32px calc(100% - 32px)); }
    to   { opacity: 1; clip-path: circle(150% at 32px calc(100% - 32px)); }
}
.aikc-chatbot[data-pos="top-right"] .aikc-chatbot__panel.is-open[data-effect="iris-dilate"] {
    animation-name: aikc-cb-open-iris-dilate-tr;
}
@keyframes aikc-cb-open-iris-dilate-tr {
    from { opacity: 0; clip-path: circle(0% at calc(100% - 32px) 32px); }
    to   { opacity: 1; clip-path: circle(150% at calc(100% - 32px) 32px); }
}
.aikc-chatbot[data-pos="top-left"] .aikc-chatbot__panel.is-open[data-effect="iris-dilate"] {
    animation-name: aikc-cb-open-iris-dilate-tl;
}
@keyframes aikc-cb-open-iris-dilate-tl {
    from { opacity: 0; clip-path: circle(0% at 32px 32px); }
    to   { opacity: 1; clip-path: circle(150% at 32px 32px); }
}

.aikc-chatbot__panel.is-open[data-effect="origami-unfold"] {
    transform-origin: top center;
    animation: aikc-cb-open-origami-unfold 600ms cubic-bezier(.2, .9, .3, 1);
}
@keyframes aikc-cb-open-origami-unfold {
    from { opacity: 0; transform: perspective(1200px) rotateX(-90deg); }
    to   { opacity: 1; transform: perspective(1200px) rotateX(0deg); }
}

.aikc-chatbot__panel.is-open[data-effect="material-morph"] {
    /* Morph from a FAB-sized circle in the bubble corner into the full
       panel. transform-origin already inherits from the per-position
       rules higher up (bottom-right by default), which gives the morph
       the correct gravity. */
    animation: aikc-cb-open-material-morph 500ms cubic-bezier(.4, 0, .2, 1);
}
@keyframes aikc-cb-open-material-morph {
    from { opacity: 0; transform: scale(0); border-radius: 50%; }
    50%  { opacity: 1; border-radius: 30%; }
    to   { opacity: 1; transform: scale(1); border-radius: 16px; }
}

.aikc-chatbot__panel.is-open[data-effect="liquid-expand"] {
    animation: aikc-cb-open-liquid-expand 600ms ease-out;
}
@keyframes aikc-cb-open-liquid-expand {
    0% {
        opacity: 0;
        transform: scale(0.85);
        border-radius: 50%;
    }
    50% {
        opacity: 1;
        transform: scale(1.02);
        border-radius: 40% 60% 60% 40% / 60% 40% 60% 40%;
    }
    100% {
        opacity: 1;
        transform: scale(1);
        border-radius: 16px;
    }
}

/* stagger-stack: the panel itself fades in plainly; the children stagger
   in using the existing `.aikc-chatbot__msg` keyframe + a JS-set
   --aikc-stagger-idx custom property (set in chatbot-widget.js when the
   panel opens). The compose row tails the messages. */
.aikc-chatbot__panel.is-open[data-effect="stagger-stack"] {
    animation: aikc-cb-open-fade 260ms ease;
}
.aikc-chatbot__panel.is-open[data-effect="stagger-stack"] .aikc-chatbot__msg {
    /* Override the default 0-delay so the JS-set index pushes each msg
       further out in time. 80ms cumulative per index matches the brief. */
    animation: aikc-cb-msg-in 280ms cubic-bezier(.2,.9,.3,1) both;
    animation-delay: calc(var(--aikc-stagger-idx, 0) * 80ms);
}
.aikc-chatbot__panel.is-open[data-effect="stagger-stack"] .aikc-chatbot__compose {
    animation: aikc-cb-msg-in 280ms cubic-bezier(.2,.9,.3,1) both;
    animation-delay: calc(var(--aikc-stagger-idx, 0) * 80ms);
}
/* `aikc-cb-open-fade` reuses the existing fade vocabulary — kept named
   distinctly from `aikc-cb-fade` so we don't accidentally clobber the
   v1 default if someone tweaks its timing. */
@keyframes aikc-cb-open-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* scan-line: a horizontal accent line scans down the panel while the
   content reveals via clip-path. The line sits on a pseudo-element so
   it doesn't disturb child layout. */
.aikc-chatbot__panel.is-open[data-effect="scan-line"] {
    animation: aikc-cb-open-scan-content 700ms ease-out both;
    position: absolute; /* already absolute via the base rule */
}
.aikc-chatbot__panel.is-open[data-effect="scan-line"]::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 2px;
    background: var(--aikc-cb-panel-primary, var(--aikc-cb-primary));
    box-shadow: 0 0 12px var(--aikc-cb-panel-primary, var(--aikc-cb-primary));
    pointer-events: none;
    z-index: 2;
    animation: aikc-cb-open-scan-line 700ms ease-out both;
}
@keyframes aikc-cb-open-scan-content {
    0%   { opacity: 1; clip-path: inset(0 0 100% 0); }
    100% { opacity: 1; clip-path: inset(0); }
}
@keyframes aikc-cb-open-scan-line {
    0%   { top: 0;    opacity: 1; }
    90%  { top: 100%; opacity: 1; }
    100% { top: 100%; opacity: 0; }
}

/* mask-reveal: diagonal gradient mask sweeps across the panel. Uses
   `mask-image` so the underlying paint stays untouched (no extra
   pseudo-element required). */
.aikc-chatbot__panel.is-open[data-effect="mask-reveal"] {
    animation: aikc-cb-open-mask-reveal 600ms ease-out both;
    -webkit-mask-image: linear-gradient(135deg, #000 0%, #000 50%, transparent 60%);
            mask-image: linear-gradient(135deg, #000 0%, #000 50%, transparent 60%);
    -webkit-mask-size: 250% 250%;
            mask-size: 250% 250%;
}
@keyframes aikc-cb-open-mask-reveal {
    0% {
        opacity: 0;
        -webkit-mask-position: 100% 100%;
                mask-position: 100% 100%;
    }
    100% {
        opacity: 1;
        -webkit-mask-position: 0% 0%;
                mask-position: 0% 0%;
    }
}

.aikc-chatbot__panel.is-open[data-effect="flip-3d"] {
    /* The base rule already sets transform-origin: bottom right for the
       default position. Per-position rules in the existing block keep it
       in the right corner for the other 3 positions. */
    animation: aikc-cb-open-flip-3d 500ms cubic-bezier(.2, .9, .3, 1.05);
}
@keyframes aikc-cb-open-flip-3d {
    from { opacity: 0; transform: perspective(1000px) rotateY(-90deg); }
    to   { opacity: 1; transform: perspective(1000px) rotateY(0deg); }
}

.aikc-chatbot__panel.is-open[data-effect="quantum-fade"] {
    animation: aikc-cb-open-quantum-fade 500ms ease-out;
}
@keyframes aikc-cb-open-quantum-fade {
    from {
        opacity: 0;
        transform: scale(1.05);
        filter: blur(24px) saturate(0.5);
    }
    to {
        opacity: 1;
        transform: scale(1);
        filter: blur(0) saturate(1);
    }
}

/* ───────────────────────────────────────────────────────────────────────
   Reduced-motion: silence ALL of the v3 entry + open animations. Each
   selector below maps 1:1 to a keyframe above. Kept verbose (not a
   wildcard) so future selector additions don't accidentally lose this
   protection.
   ─────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .aikc-chatbot[data-bubble-enter="none"]              .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="fade"]              .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="spring-pop"]        .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="magnetic-slide"]    .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="iris-zoom"]         .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="liquid-blob"]       .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="glitch-reveal"]     .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="beam-in"]           .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="particle-assemble"] .aikc-chatbot__bubble,
    .aikc-chatbot[data-bubble-enter="none"]              .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="fade"]              .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="spring-pop"]        .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="magnetic-slide"]    .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="iris-zoom"]         .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="liquid-blob"]       .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="glitch-reveal"]     .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="beam-in"]           .aikc-chatbot__bubble.is-pulse,
    .aikc-chatbot[data-bubble-enter="particle-assemble"] .aikc-chatbot__bubble.is-pulse {
        animation: none !important;
        /* v4: when reduced-motion is on we also kill the entry-delay so the
           bubble doesn't stay invisible "waiting" for a delay that no
           longer triggers a reveal. Without this, `data-bubble-enter="none"`
           with a 5s delay + reduced-motion would silently keep the bubble
           hidden for the duration. The visitor expects "show me immediately,
           no animation"; reduced-motion is about removing motion, not
           introducing invisible waits. */
        animation-delay: 0ms !important;
    }
    .aikc-chatbot[data-bubble-enter="beam-in"] .aikc-chatbot__bubble::before,
    .aikc-chatbot[data-bubble-enter="particle-assemble"] .aikc-chatbot__bubble::after {
        animation: none !important;
        opacity: 0 !important;
    }
    .aikc-chatbot__panel.is-open[data-effect="iris-dilate"],
    .aikc-chatbot__panel.is-open[data-effect="origami-unfold"],
    .aikc-chatbot__panel.is-open[data-effect="material-morph"],
    .aikc-chatbot__panel.is-open[data-effect="liquid-expand"],
    .aikc-chatbot__panel.is-open[data-effect="stagger-stack"],
    .aikc-chatbot__panel.is-open[data-effect="scan-line"],
    .aikc-chatbot__panel.is-open[data-effect="mask-reveal"],
    .aikc-chatbot__panel.is-open[data-effect="flip-3d"],
    .aikc-chatbot__panel.is-open[data-effect="quantum-fade"] {
        animation: none !important;
        clip-path: none !important;
        -webkit-mask-image: none !important;
                mask-image: none !important;
        filter: none !important;
        transform: none !important;
        opacity: 1 !important;
    }
    .aikc-chatbot__panel.is-open[data-effect="stagger-stack"] .aikc-chatbot__msg,
    .aikc-chatbot__panel.is-open[data-effect="stagger-stack"] .aikc-chatbot__compose {
        animation: none !important;
        animation-delay: 0 !important;
    }
    .aikc-chatbot__panel.is-open[data-effect="scan-line"]::before {
        display: none !important;
    }
}

