/* ================================================================
   N.Y.R.A FRONTEND — Dark Glass UI
   ================================================================

   DESIGN SYSTEM OVERVIEW
   ----------------------
   This stylesheet powers a single-page AI chat assistant with a
   futuristic, dark "glass-morphism" aesthetic. Key design pillars:

   1. DARK THEME — Near-black background (#050510) with layered
      semi-transparent surfaces. All colour is delivered through
      translucent whites and a purple/teal accent palette.

   2. GLASS-MORPHISM — Panels use `backdrop-filter: blur()` to
      create a frosted-glass look, letting a decorative animated
      "orb" glow through from behind.

   3. CSS CUSTOM PROPERTIES — Every shared colour, radius, timing
      function, and font is stored in :root variables so the entire
      theme can be adjusted from one place.

   4. LAYOUT — A full-viewport flex column: Header → Chat → Input.
      The animated orb sits behind everything with `position: fixed`.

   5. RESPONSIVE — Two breakpoints (768 px tablets, 480 px phones)
      progressively hide decorative elements and tighten spacing
      while preserving usability. iOS safe-area insets are honoured.

   FILE STRUCTURE (top → bottom):
     • CSS Custom Properties (:root)
     • Reset / Base
     • Glass Panel utility class
     • App Layout shell
     • Orb (animated background decoration)
     • Header  (logo, mode switch, status badge, new-chat button)
     • Chat Area  (message list, welcome screen, message bubbles,
                   typing indicator, streaming cursor)
     • Input Bar  (textarea, action buttons — mic, TTS, send)
     • Scrollbar customisation
     • Keyframe Animations
     • Responsive Breakpoints
   ================================================================ */


/* ================================================================
   CSS CUSTOM PROPERTIES (Design Tokens)
   ================================================================
   Everything that might be reused or tweaked lives here.
   Changing a single variable updates the whole UI consistently.
   ================================================================ */
:root {
    /* ---- Backgrounds ---- */
    --bg: #050510;                                /* Page-level dark background */
    --glass-bg: rgba(10, 10, 28, 0.72);          /* Semi-transparent fill for glass panels (header, input bar) */
    --glass-border: rgba(255, 255, 255, 0.06);   /* Subtle white border that outlines glass panels */
    --glass-hover: rgba(255, 255, 255, 0.10);    /* Slightly brighter fill on hover */

    /* ---- Accent colours ---- */
    --accent: #7c6aef;                            /* Primary purple accent — buttons, highlights, glows */
    --accent-glow: rgba(124, 106, 239, 0.35);    /* Soft purple used for box-shadows / focus rings */
    --accent-secondary: #4ecdc4;                  /* Teal complement — used in gradients alongside --accent */

    /* ---- Text ---- */
    --text: rgba(255, 255, 255, 0.93);            /* Primary readable text — near-white */
    --text-dim: rgba(255, 255, 255, 0.50);        /* Secondary / de-emphasised text */
    --text-muted: rgba(255, 255, 255, 0.28);      /* Tertiary — labels, meta info, placeholders */

    /* ---- Semantic colours ---- */
    --danger: #ff6b6b;                            /* Destructive / recording state (mic listening) */
    --success: #51cf66;                           /* Online status, success feedback */

    /* ---- Border radii ---- */
    --radius: 16px;                               /* Large radius — panels, bubbles */
    --radius-sm: 10px;                            /* Medium radius — buttons, avatars */
    --radius-xs: 6px;                             /* Small radius — notched bubble corners */

    /* ---- Layout ---- */
    --header-h: 60px;                             /* Fixed header height — used to reserve space */

    /* ---- Motion ---- */
    --transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    /* Shared easing curve (Material "standard" ease) for all micro-interactions.
       Starts slow, accelerates, then decelerates for a natural feel. */

    /* ---- Typography ---- */
    --font: 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif;
    /* Poppins as primary; system fonts as fallback for fast initial render. */
}


/* ================================================================
   RESET & BASE STYLES
   ================================================================
   A minimal "universal reset" that strips browser defaults so
   every element starts from zero. `box-sizing: border-box` makes
   padding/border count inside the declared width/height — the most
   intuitive model for layout work.
   ================================================================ */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

/* Full viewport height; overflow hidden because the chat area
   manages its own scrolling internally. */
html, body { height: 100%; overflow: hidden; }

body {
    font-family: var(--font);
    background: var(--bg);
    color: var(--text);
    -webkit-font-smoothing: antialiased;          /* Smoother font rendering on macOS/iOS WebKit */
    -webkit-tap-highlight-color: transparent;      /* Removes the blue tap flash on mobile WebKit */
}

/* Reset native button / textarea styling so we control everything */
button { font-family: var(--font); cursor: pointer; border: none; background: none; color: inherit; }
textarea { font-family: var(--font); color: var(--text); }


/* ================================================================
   GLASS PANEL — Reusable Utility Class
   ================================================================
   The signature "frosted glass" look. Applied to the header and
   input bar (any element that needs a translucent panel).

   HOW IT WORKS:
   • `background` — a dark, semi-transparent fill (72 % opacity).
   • `backdrop-filter: blur(32px) saturate(1.2)` — blurs whatever
     is *behind* the element (the orb glow, the chat) and slightly
     boosts colour saturation for a richer look.
   • `-webkit-backdrop-filter` — Safari still needs the prefix.
   • `border` — a faint 6 %-white hairline that catches light at
     the edges, reinforcing the glass illusion.
   ================================================================ */
.glass-panel {
    background: var(--glass-bg);
    backdrop-filter: blur(32px) saturate(1.2);
    -webkit-backdrop-filter: blur(32px) saturate(1.2);
    border: 1px solid var(--glass-border);
}


/* ================================================================
   APP LAYOUT SHELL
   ================================================================
   The top-level `.app` container is a vertical flex column that
   fills the entire viewport: Header (fixed) → Chat (grows) → Input
   (fixed).

   `100dvh` (dynamic viewport height) is the modern replacement for
   `100vh` on mobile browsers — it accounts for the URL bar sliding
   in and out. The plain `100vh` above it is a fallback for older
   browsers that don't understand `dvh`.
   ================================================================ */
.app {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100vh;              /* Fallback for browsers without dvh support */
    height: 100dvh;             /* Preferred: adjusts for mobile browser chrome */
    overflow: hidden;
}


/* ================================================================
   ORB BACKGROUND — Animated Decorative Element
   ================================================================
   The "orb" is a large, softly-glowing circle (rendered by JS /
   canvas inside #orb-container) that sits dead-centre behind all
   content. It provides ambient motion and reacts to AI state.

   POSITIONING:
   • `position: fixed` + `top/left 50%` + `translate -50% -50%`
     centres it in the viewport regardless of scroll.
   • `min(600px, 80vw)` — caps the orb at 600 px but lets it shrink
     on small screens so it never overflows.
   • `z-index: 0` — behind everything; content layers sit above.
   • `pointer-events: none` — clicks pass straight through.
   • `opacity: 0.35` — subtle by default; it brightens on activity.
   ================================================================ */
#orb-container {
    position: fixed;
    top: 50%;
    left: 50%;
    translate: -50% -50%;
    width: min(600px, 80vw);
    height: min(600px, 80vw);
    z-index: 0;
    pointer-events: none;
    opacity: 0.35;
    transition: opacity 0.5s ease, transform 0.5s ease;
}

/* ORB ACTIVE STATES
   When the AI is actively processing (.active) or speaking aloud
   (.speaking), the orb ramps to full opacity and plays a gentle
   breathing scale animation (orbPulse) so the user sees the AI
   is "alive". */
#orb-container.active,
#orb-container.speaking {
    opacity: 1;
    animation: orbPulse 1.6s ease-in-out infinite;
}

/* No overlay/scrim on the orb — the orb is the only background effect.
   Previously a radial gradient darkened the edges; removed so only the
   central orb remains visible without circular shades. */


/* ================================================================
   HEADER
   ================================================================
   A horizontal flex row pinned to the top of the app.

   LAYOUT:
   • `justify-content: space-between` pushes left group (logo) and
     right group (status / new-chat) to opposite edges; the mode
     switch sits in the centre via the gap.
   • `z-index: 10` ensures the header floats above the chat area
     and the orb scrim.
   • Bottom border-radius rounds only the lower corners, creating
     a "floating shelf" look that separates it from chat content.
   • `flex-shrink: 0` prevents the header from collapsing when the
     chat area needs space.
   ================================================================ */
.header {
    position: relative;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: var(--header-h);
    padding: 0 20px;
    border-radius: 0 0 var(--radius) var(--radius);
    border-top: none;
    flex-shrink: 0;
}

/* HEADER LEFT — Logo + Tagline
   `align-items: baseline` aligns the tall logo text and the
   smaller tagline along their text baselines. */
.header-left { display: flex; align-items: baseline; gap: 10px; }

/* LOGO
   Gradient text effect: a linear gradient is painted as the
   background, then `background-clip: text` masks it to only show
   through the letter shapes. `-webkit-text-fill-color: transparent`
   makes the original text colour invisible so the gradient shows. */
.logo {
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: 3px;
    background: linear-gradient(135deg, var(--accent), var(--accent-secondary));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

/* TAGLINE — small muted descriptor beneath / beside the logo */
.tagline {
    font-size: 0.68rem;
    font-weight: 300;
    color: var(--text-muted);
    letter-spacing: 0.5px;
}

/* ----------------------------------------------------------------
   MODE SWITCH — Chat / Voice Toggle
   ----------------------------------------------------------------
   A pill-shaped toggle with two buttons and a sliding highlight.
   
   STRUCTURE:
   • `.mode-switch` — the outer pill (flex row, dark bg, rounded).
   • `.mode-slider` — an absolutely-positioned coloured rectangle
     that slides left↔right to indicate the active mode.
   • `.mode-btn` — individual clickable labels ("Chat", "Voice").

   The slider width is `calc(50% - 4px)` — half the pill minus
   the padding — so it exactly covers one button. When `.right` is
   added (by JS), `translateX(calc(100% + 2px))` shifts it over
   to highlight the second button.
   ---------------------------------------------------------------- */
.mode-switch {
    position: relative;
    display: flex;
    background: rgba(255, 255, 255, 0.04);
    border-radius: 12px;
    padding: 3px;
    gap: 2px;
}
.mode-slider {
    position: absolute;
    top: 3px;
    left: 3px;
    width: calc(50% - 4px);           /* Exactly covers one button */
    height: calc(100% - 6px);         /* Full height minus top+bottom padding */
    background: var(--accent);
    border-radius: 10px;
    transition: transform var(--transition);
    opacity: 0.18;                     /* Tinted, not solid — keeps it subtle */
}
.mode-slider.right {
    transform: translateX(calc(100% + 2px)); /* Slide to the second button */
}
.mode-btn {
    position: relative;
    z-index: 1;                        /* Above the slider background */
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 16px;
    font-size: 0.76rem;
    font-weight: 500;
    border-radius: 10px;
    color: var(--text-dim);
    transition: color var(--transition);
    white-space: nowrap;               /* Prevents label from wrapping at narrow widths */
}
.mode-btn.active { color: var(--text); }          /* Active mode gets full-white text */
.mode-btn svg { opacity: 0.7; }                   /* Dim icon by default */
.mode-btn.active svg { opacity: 1; }              /* Full opacity when active */

/* ----------------------------------------------------------------
   HEADER RIGHT — Status Badge & Utility Buttons
   ---------------------------------------------------------------- */
.header-right { display: flex; align-items: center; gap: 10px; }

/* STATUS BADGE — shows a coloured dot + "Online" / "Offline" label */
.status-badge {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.7rem;
    font-weight: 400;
    color: var(--text-dim);
}

/* STATUS DOT
   A small circle with a coloured glow (box-shadow). The `pulse-dot`
   animation fades it in and out to convey a "heartbeat" while online. */
.status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 6px var(--success);
    animation: pulse-dot 2s ease-in-out infinite;
}
/* When the server is unreachable, switch to red and stop pulsing */
.status-dot.offline {
    background: var(--danger);
    box-shadow: 0 0 6px var(--danger);
    animation: none;
}

/* ICON BUTTON — generic small square button (e.g. "New Chat").
   `display: grid; place-items: center` is the quickest way to
   perfectly centre a single child (the SVG icon). */
.btn-icon {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--glass-border);
    transition: background var(--transition), border-color var(--transition);
}
.btn-icon:hover {
    background: var(--glass-hover);
    border-color: rgba(255, 255, 255, 0.14);
}


/* ================================================================
   CHAT AREA
   ================================================================
   The scrollable middle section between header and input bar.

   `flex: 1` makes it absorb all remaining vertical space.
   The inner `.chat-messages` div does the actual scrolling
   (`overflow-y: auto`) so the header and input bar stay fixed.
   `scroll-behavior: smooth` gives programmatic scrollTo() calls
   a gentle animation.
   ================================================================ */
.chat-area {
    position: relative;
    z-index: 5;
    flex: 1;
    overflow: hidden;           /* Outer container clips; inner scrolls */
    display: flex;
    flex-direction: column;
}
.chat-messages {
    flex: 1;
    overflow-y: auto;           /* Vertical scroll when messages overflow */
    overflow-x: hidden;
    padding: 20px 20px;
    display: flex;
    flex-direction: column;     /* Messages stack top→bottom */
    gap: 6px;                   /* Consistent spacing between messages */
    scroll-behavior: smooth;
}

/* ----------------------------------------------------------------
   WELCOME SCREEN
   ----------------------------------------------------------------
   Shown when the conversation is empty. A vertically & horizontally
   centred splash with a title, subtitle, and suggestion chips.
   `flex: 1` + centering fills the entire chat area.
   `fadeIn` animation slides it up gently on first load.
   ---------------------------------------------------------------- */
.welcome-screen {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    flex: 1;
    gap: 12px;
    padding: 40px 20px;
    animation: fadeIn 0.6s ease;
}
.welcome-icon {
    color: var(--accent);
    opacity: 0.5;
    margin-bottom: 6px;
}
/* Same gradient-text technique as the logo */
.welcome-title {
    font-size: 1.7rem;
    font-weight: 600;
    background: linear-gradient(135deg, var(--text), var(--accent));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}
.welcome-sub {
    font-size: 0.9rem;
    color: var(--text-dim);
    font-weight: 300;
}

/* SUGGESTION CHIPS — quick-tap prompts */
.welcome-chips {
    display: flex;
    flex-wrap: wrap;            /* Wraps to multiple rows on narrow screens */
    justify-content: center;
    gap: 8px;
    margin-top: 18px;
}
.chip {
    padding: 8px 18px;
    font-size: 0.76rem;
    font-weight: 400;
    border-radius: 20px;       /* Fully rounded pill shape */
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--glass-border);
    color: var(--text-dim);
    transition: all var(--transition);
}
.chip:hover {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
    transform: translateY(-1px);  /* Subtle "lift" effect on hover */
}


/* ================================================================
   MESSAGE BUBBLES
   ================================================================
   Each message is a horizontal flex row: avatar + body.
   `max-width: 760px` + `margin: 0 auto` centres the conversation
   in a readable column on wide screens.

   User vs. Assistant differentiation:
   • `.message.user` reverses the flex direction so the avatar
     appears on the right.
   • Background colours differ: assistant is neutral white-tint,
     user is purple-tinted (matching --accent).
   • One corner of each bubble is given a smaller radius to create
     a "speech bubble notch" that points toward the avatar.
   ================================================================ */
.message {
    display: flex;
    gap: 10px;
    max-width: 760px;
    width: 100%;
    margin: 0 auto;
    animation: msgIn 0.3s ease;  /* Slide-up entrance for each new message */
}
.message.user { flex-direction: row-reverse; } /* Avatar on the right for user */

/* MESSAGE AVATAR — small icon square beside each bubble */
.msg-avatar {
    width: 30px;
    height: 30px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    font-size: 0.7rem;
    font-weight: 600;
    flex-shrink: 0;             /* Never let the avatar shrink */
    margin-top: 4px;            /* Align with the first line of text */
}
/* SVG icon inside avatar — sized to fit the circle, inherits color from parent */
.msg-avatar .msg-avatar-icon {
    width: 18px;
    height: 18px;
}
/* Assistant avatar: purple→teal gradient to match the brand */
.message.assistant .msg-avatar {
    background: linear-gradient(135deg, var(--accent), var(--accent-secondary));
    color: #fff;
}
/* User avatar: neutral dark chip */
.message.user .msg-avatar {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-dim);
}

/* MSG-BODY — column wrapper for label + content bubble.
   `min-width: 0` is a flex-child fix that allows long words to
   trigger `word-wrap: break-word` instead of overflowing. */
.msg-body {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

/* MSG-CONTENT — the actual text bubble */
.msg-content {
    padding: 11px 15px;
    border-radius: var(--radius);
    font-size: 0.87rem;
    line-height: 1.65;           /* Generous line-height for readability */
    font-weight: 400;
    word-wrap: break-word;
    white-space: pre-wrap;       /* Preserves newlines from the AI response */
}
/* Assistant bubble: neutral grey-white tint, notch top-left */
.message.assistant .msg-content {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-top-left-radius: var(--radius-xs);     /* Notch pointing toward avatar */
}
/* User bubble: purple-tinted, notch top-right */
.message.user .msg-content {
    background: rgba(124, 106, 239, 0.13);
    border: 1px solid rgba(124, 106, 239, 0.16);
    border-top-right-radius: var(--radius-xs);    /* Notch pointing toward avatar */
}

/* MSG-LABEL — tiny "RADHA" / "You" text above the bubble */
.msg-label {
    font-size: 0.66rem;
    font-weight: 500;
    color: var(--text-muted);
    padding: 0 4px;
}
.message.user .msg-label { text-align: right; }  /* Right-align label for user */

/* ----------------------------------------------------------------
   TYPING INDICATOR — Three Bouncing Dots
   ----------------------------------------------------------------
   Displayed in an assistant message while waiting for a response.
   Three <span> dots animate with staggered delays (0 → 0.15 → 0.3s)
   to create a wave-like bounce.
   ---------------------------------------------------------------- */
.typing-dots {
    display: inline-flex;
    gap: 4px;
    padding: 4px 0;
}
.typing-dots span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-dim);
    animation: dotBounce 1.2s ease-in-out infinite;
}
.typing-dots span:nth-child(2) { animation-delay: 0.15s; }  /* Second dot lags slightly */
.typing-dots span:nth-child(3) { animation-delay: 0.3s; }   /* Third dot lags more */

/* STREAMING CURSOR — blinking pipe character appended while the AI
   streams its response token-by-token. */
.stream-cursor {
    animation: blink 0.8s step-end infinite;
    color: var(--accent);
    margin-left: 1px;
}


/* ================================================================
   INPUT BAR
   ================================================================
   Pinned to the bottom of the app. Like the header, it uses the
   glass-panel class for the frosted look.

   iOS SAFE-AREA HANDLING:
   `padding-bottom: max(10px, env(safe-area-inset-bottom, 10px))`
   ensures the input never hides behind the iPhone home-indicator
   bar. `env(safe-area-inset-bottom)` is a CSS environment variable
   injected by WebKit on notched iPhones; the `max()` guarantees
   at least 10 px even on devices without a home bar.

   `flex-shrink: 0` prevents the input bar from being squished when
   the chat area grows.
   ================================================================ */
.input-bar {
    position: relative;
    z-index: 10;
    padding: 10px 20px 10px;
    padding-bottom: max(10px, env(safe-area-inset-bottom, 10px));
    border-radius: var(--radius) var(--radius) 0 0;  /* Top corners rounded */
    border-bottom: none;
    flex-shrink: 0;
}

/* INPUT WRAPPER — the rounded pill that holds textarea + buttons.
   `align-items: flex-end` keeps action buttons bottom-aligned when
   the textarea grows taller (multi-line input). */
.input-wrapper {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--glass-border);
    border-radius: 14px;
    padding: 5px 5px 5px 14px;
    transition: border-color var(--transition), box-shadow var(--transition);
}
/* Focus ring: purple border + subtle outer glow when typing */
.input-wrapper:focus-within {
    border-color: rgba(124, 106, 239, 0.35);
    box-shadow: 0 0 0 3px rgba(124, 106, 239, 0.08);
}

/* TEXTAREA — auto-growing text input (height controlled by JS).
   `resize: none` disables the browser's drag-to-resize handle.
   `max-height: 120px` caps growth so it doesn't consume the screen. */
.input-wrapper textarea {
    flex: 1;
    background: none;
    border: none;
    outline: none;
    resize: none;
    font-size: 0.87rem;
    line-height: 1.5;
    padding: 8px 0;
    max-height: 120px;
    color: var(--text);
}
.input-wrapper textarea::placeholder { color: var(--text-muted); }

/* ACTION BUTTONS ROW — sits to the right of the textarea */
.input-actions {
    display: flex;
    gap: 6px;
    padding-bottom: 2px;       /* Micro-nudge to visually centre with one-line textarea */
    flex-shrink: 0;
}

/* ----------------------------------------------------------------
   ACTION BUTTON — Base Style (Mic, TTS, Send)
   ----------------------------------------------------------------
   All three input buttons share this base: a fixed-size square
   with rounded corners and a subtle background. `display: grid;
   place-items: center` perfectly centres the SVG icon.
   ---------------------------------------------------------------- */
.action-btn {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    min-width: 38px;            /* Prevents flex from shrinking the button */
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.08);
    transition: all var(--transition);
    color: var(--text-dim);
    flex-shrink: 0;
}
.action-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.16);
    color: var(--text);
    transform: translateY(-1px);  /* Lift effect */
}
.action-btn:active {
    transform: translateY(0);      /* Press-down snap back */
}

/* ----------------------------------------------------------------
   SEND BUTTON — Accent-Coloured Call-to-Action
   ----------------------------------------------------------------
   Uses `!important` to override the generic `.action-btn` styles
   because both selectors have the same specificity. This is the
   only button that's always visually prominent (purple fill).
   ---------------------------------------------------------------- */
.send-btn {
    background: var(--accent) !important;
    border-color: var(--accent) !important;
    color: #fff !important;
    box-shadow: 0 2px 8px rgba(124, 106, 239, 0.25);  /* Purple underglow */
}
.send-btn:hover {
    background: #6a58e0 !important;       /* Slightly darker purple on hover */
    border-color: #6a58e0 !important;
    box-shadow: 0 4px 14px rgba(124, 106, 239, 0.35); /* Stronger glow */
}
/* Disabled state: greyed out, no glow, no cursor, no lift */
.send-btn:disabled {
    opacity: 0.4;
    cursor: default;
    box-shadow: none;
    transform: none;
}

/* ----------------------------------------------------------------
   MIC BUTTON — Default + Listening States
   ----------------------------------------------------------------
   Two SVG icons live inside the button; only one is visible at a
   time via `display: none` toggling.

   DEFAULT: muted grey square (inherits .action-btn).
   LISTENING (.listening): red-tinted background + border + danger
   colour text, plus a pulsing red ring animation (micPulse) to
   convey "recording in progress".
   ---------------------------------------------------------------- */
.mic-btn .mic-icon-active { display: none; }           /* Hidden when NOT listening */
.mic-btn.listening .mic-icon { display: none; }        /* Hide default icon */
.mic-btn.listening .mic-icon-active { display: block; } /* Show active icon */
.mic-btn.listening {
    background: rgba(255, 107, 107, 0.18);             /* Red-tinted fill */
    border-color: rgba(255, 107, 107, 0.3);
    color: var(--danger);
    animation: micPulse 1.5s ease-in-out infinite;     /* Expanding red ring */
}

/* ----------------------------------------------------------------
   TTS (TEXT-TO-SPEECH) BUTTON — Default + Active + Speaking States
   ----------------------------------------------------------------
   Similar icon-swap pattern to the mic button.

   DEFAULT: muted grey (inherits .action-btn). Speaker-off icon.
   ACTIVE (.tts-active): TTS is enabled — purple tint to show it's
     toggled on. Speaker-on icon.
   SPEAKING (.tts-speaking): TTS is currently playing audio —
     pulsing purple ring (ttsPulse) for visual feedback.
   ---------------------------------------------------------------- */
.tts-btn .tts-icon-on { display: none; }              /* Hidden when TTS is off */
.tts-btn.tts-active .tts-icon-off { display: none; }  /* Hide "off" icon */
.tts-btn.tts-active .tts-icon-on { display: block; }  /* Show "on" icon */
.tts-btn.tts-active {
    background: rgba(124, 106, 239, 0.18);            /* Purple-tinted fill */
    border-color: rgba(124, 106, 239, 0.3);
    color: var(--accent);
}
.tts-btn.tts-speaking {
    animation: ttsPulse 1.5s ease-in-out infinite;     /* Expanding purple ring */
}

/* INPUT META — small row below the input showing mode label + hints */
.input-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 5px 8px 0;
    font-size: 0.66rem;
    color: var(--text-muted);
}
.mode-label { font-weight: 500; }


/* ================================================================
   SEARCH RESULTS WIDGET (Realtime — Tavily data)
   ================================================================
   Fixed panel on the right: query, AI answer, source cards. Themed
   scrollbars, responsive width, no overflow or layout bugs.
   ================================================================ */
.search-results-widget {
    position: fixed;
    top: 0;
    right: 0;
    width: min(380px, 95vw);
    min-width: 0;
    max-height: 100vh;
    height: 100%;
    z-index: 20;
    display: flex;
    flex-direction: column;
    border-radius: var(--radius) 0 0 var(--radius);
    border-right: none;
    box-shadow: -8px 0 32px rgba(0, 0, 0, 0.4);
    overflow: hidden;
    transform: translateX(100%);
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
.search-results-widget.open {
    transform: translateX(0);
}
.search-results-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    border-bottom: 1px solid var(--glass-border);
    flex-shrink: 0;
}
.search-results-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.search-results-title::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 8px var(--success);
    animation: pulse-dot 2s ease-in-out infinite;
    flex-shrink: 0;
}
.search-results-close {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--glass-border);
    color: var(--text-dim);
    cursor: pointer;
    transition: all var(--transition);
    flex-shrink: 0;
}
.search-results-close:hover {
    background: rgba(255, 255, 255, 0.12);
    color: var(--text);
}
.search-results-query {
    padding: 12px 16px;
    font-size: 0.75rem;
    color: var(--accent);
    font-weight: 500;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    flex-shrink: 0;
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;
}
.search-results-answer {
    padding: 14px 16px;
    font-size: 0.85rem;
    line-height: 1.55;
    color: var(--text);
    background: rgba(124, 106, 239, 0.08);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    flex-shrink: 0;
    max-height: 200px;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    word-wrap: break-word;
    overflow-wrap: break-word;
}
.search-results-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px 16px 24px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    scroll-behavior: smooth;
}
.search-result-card {
    padding: 12px 14px;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
    transition: background var(--transition), border-color var(--transition);
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.search-result-card:hover {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.1);
}
.search-result-card .card-title {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text);
    line-height: 1.35;
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;
}
.search-result-card .card-content {
    font-size: 0.76rem;
    color: var(--text-dim);
    line-height: 1.5;
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.search-result-card .card-url {
    font-size: 0.7rem;
    color: var(--accent);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
}
.search-result-card .card-url:hover {
    text-decoration: underline;
}
.search-result-card .card-score {
    font-size: 0.68rem;
    color: var(--text-muted);
}
/* Themed scrollbars for search widget (match app dark theme) */
.search-results-answer::-webkit-scrollbar,
.search-results-list::-webkit-scrollbar {
    width: 6px;
}
.search-results-answer::-webkit-scrollbar-track,
.search-results-list::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.03);
    border-radius: 10px;
}
.search-results-answer::-webkit-scrollbar-thumb,
.search-results-list::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.12);
    border-radius: 10px;
}
.search-results-answer::-webkit-scrollbar-thumb:hover,
.search-results-list::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.2);
}
@supports (scrollbar-color: rgba(255,255,255,0.12) rgba(255,255,255,0.03)) {
    .search-results-answer,
    .search-results-list {
        scrollbar-color: rgba(255, 255, 255, 0.12) rgba(255, 255, 255, 0.03);
        scrollbar-width: thin;
    }
}


/* ================================================================
   SCROLLBAR CUSTOMISATION (WebKit / Chromium)
   ================================================================
   A nearly-invisible 4 px scrollbar that only reveals itself on
   hover. Keeps the glass aesthetic clean without hiding scroll
   affordance entirely.
   ================================================================ */
.chat-messages::-webkit-scrollbar { width: 4px; }
.chat-messages::-webkit-scrollbar-track { background: transparent; }
.chat-messages::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.08);
    border-radius: 10px;
}
.chat-messages::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.14); }


/* ================================================================
   KEYFRAME ANIMATIONS
   ================================================================
   All animations are defined here for easy reference and reuse.

   fadeIn     — Welcome screen entrance: fade up from 12 px below.
   msgIn      — New chat message entrance: fade up from 8 px below
                (shorter travel than fadeIn for subtlety).
   dotBounce  — Typing-indicator dots: each dot jumps up 5 px then
                falls back down. Staggered delays on nth-child
                create the wave pattern.
   blink      — Streaming cursor: toggles opacity on/off every
                half-cycle. `step-end` makes the transition instant
                (no gradual fade), mimicking a real text cursor.
   pulse-dot  — Status dot heartbeat: gently fades to 40 % and back
                over 2 s.
   micPulse   — Mic "listening" ring: an expanding, fading box-shadow
                ring in danger-red. Grows from 0 to 8 px then fades
                to transparent, repeating every 1.5 s.
   ttsPulse   — TTS "speaking" ring: same expanding ring technique
                but in accent-purple.
   orbPulse   — Background orb breathing: scales from 1× to 1.10×
                while nudging opacity from 0.92 → 1, creating a
                gentle "inhale / exhale" effect.
   ================================================================ */
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes msgIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes dotBounce {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
    30%           { transform: translateY(-5px); opacity: 1; }
}
@keyframes blink {
    50% { opacity: 0; }
}
@keyframes pulse-dot {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.4; }
}
@keyframes micPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 107, 107, 0.3); }
    50%      { box-shadow: 0 0 0 8px rgba(255, 107, 107, 0); }
}
@keyframes ttsPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(124, 106, 239, 0.3); }
    50%      { box-shadow: 0 0 0 8px rgba(124, 106, 239, 0); }
}
@keyframes orbPulse {
    0%, 100% { transform: scale(1); opacity: 0.92; }
    50%      { transform: scale(1.10); opacity: 1; }
}


/* ================================================================
   RESPONSIVE BREAKPOINTS
   ================================================================

   TABLET — max-width: 768 px
   ----------------------------------------------------------------
   At this size the sidebar (if any) is gone and horizontal space
   is tighter. Changes:
   • Header padding/gap shrinks; tagline is hidden entirely.
   • Logo shrinks from 1.1 rem → 1 rem.
   • Mode-switch buttons lose their SVG icons (text-only) and get
     tighter padding, so the toggle still fits.
   • Status badge hides its text label — only the dot remains.
   • Chat message padding and font sizes reduce slightly.
   • Action buttons go from 38 px → 36 px.
   • Avatars shrink from 30 px → 26 px.
   • Input bar honours iOS safe-area at the smaller padding value.
   ================================================================ */
@media (max-width: 768px) {
    .header { padding: 0 12px; gap: 8px; }
    .tagline { display: none; }
    .logo { font-size: 1rem; }
    .mode-btn { padding: 6px 10px; font-size: 0.72rem; }
    .mode-btn svg { display: none; }
    .status-badge .status-text { display: none; }
    .chat-messages { padding: 14px 10px; }
    .input-bar { padding: 8px 10px 8px; padding-bottom: max(8px, env(safe-area-inset-bottom, 8px)); }
    .input-wrapper { padding: 4px 4px 4px 12px; }
    .action-btn { width: 36px; height: 36px; min-width: 36px; border-radius: 9px; }
    .msg-content { font-size: 0.84rem; padding: 10px 13px; }
    .welcome-title { font-size: 1.3rem; }
    .message { gap: 8px; }
    .msg-avatar { width: 26px; height: 26px; font-size: 0.62rem; }
    .msg-avatar .msg-avatar-icon { width: 16px; height: 16px; }
    .search-results-widget { width: min(100vw, 360px); }
    .search-results-header { padding: 12px 14px; }
    .search-results-query,
    .search-results-answer { padding: 10px 14px; }
    .search-results-list { padding: 10px 14px 20px; gap: 10px; }
    .search-result-card { padding: 10px 12px; }
}

/* PHONE — max-width: 480 px
   ----------------------------------------------------------------
   The narrowest target. Every pixel counts.
   • Mode switch stretches to full width and centres; each button
     gets `flex: 1` so they split evenly.
   • "New Chat" button is hidden to save space.
   • Suggestion chips get smaller padding and font.
   • Action buttons shrink further to 34 px; SVG icons scale down.
   • Gaps tighten across the board.
   ---------------------------------------------------------------- */
@media (max-width: 480px) {
    .header-center { flex: 1; justify-content: center; display: flex; }
    .mode-switch { width: 100%; }
    .mode-btn { flex: 1; justify-content: center; }
    .new-chat-btn { display: none; }
    .welcome-chips { gap: 6px; }
    .chip { font-size: 0.72rem; padding: 6px 14px; }
    .action-btn { width: 34px; height: 34px; min-width: 34px; border-radius: 8px; }
    .action-btn svg { width: 17px; height: 17px; }
    .input-actions { gap: 5px; }
    .input-wrapper { gap: 4px; }
    .search-results-widget { width: 100vw; max-width: 100%; }
    .search-results-header { padding: 10px 12px; }
    .search-results-query { font-size: 0.72rem; padding: 10px 12px; }
    .search-results-answer { font-size: 0.82rem; padding: 10px 12px; max-height: 160px; }
    .search-results-list { padding: 8px 12px 16px; gap: 8px; }
    .search-result-card { padding: 10px 12px; }
    .search-result-card .card-title { font-size: 0.76rem; }
    .search-result-card .card-content { font-size: 0.72rem; -webkit-line-clamp: 3; }
}