/* ========================================================================
 * Animation Timing System - CSS Custom Properties
 * Centralizes timing values for the Start Meeting transition flow.
 * Coordinated with base.html skeleton delay (200ms in JS) for seamless handoff.
 *
 * Architecture:
 *   --transition-instant: Micro-feedback (button press, text swap)
 *   --transition-fast:    Primary animations (page-enter, skeleton fade)
 *   --transition-medium:  Secondary animations (form-launch, loading bar)
 *   --skeleton-delay:     Delay before skeleton appears (synced with JS)
 *
 * The skeleton delay (200ms JS) > button animations (150ms) ensures:
 *   Button click -> Form dims -> Form animates -> Skeleton appears
 *
 * TIMING ORCHESTRATION MAP - Start Meeting Flow
 * =============================================
 * This timeline shows how animations chain to create seamless UX:
 *
 *   0ms   Button click
 *         |-- Instant (50ms): Button :active scale feedback
 *         |-- Instant (50ms): Loading bar initial burst to 15%
 *         |-- Fast (150ms): Content dims (loading-dimmed class)
 *         |-- Fast (150ms): Footer dims (peripheral cohesion)
 *         |-- Fast (150ms): Button text crossfade begins
 *         |-- Fast (150ms): Button spinner bloom entrance
 *
 *  50ms   Form launch animation starts
 *         |-- Slow (300ms): Form scales + lifts (form-launch keyframes)
 *         |-- Button pulse animation (400ms total)
 *
 * 200ms   Skeleton delay timer fires (if request still pending)
 *         |-- NETWORK-AWARE: delay is 0ms (2G), 100ms (3G), or 200ms (4G/WiFi)
 *         |-- Medium (200ms): Skeleton fades in
 *         |-- Staggered children: 0/50/100/150ms delays
 *
 * ~500ms  Server response arrives (typical)
 *         |-- Fast (150ms): Skeleton fades out
 *         |-- Fast (150ms): Page entrance animation (slide up + fade)
 *         |-- Loading bar completes to 100% with glow
 *
 * ERROR RECOVERY (if request fails):
 *         |-- 500ms shake + fade recovery animation
 *         |-- Form wrapper recovery (400ms)
 *         |-- Button ready pulse (400ms)
 *
 * Key insight: Overlapping animations with staggered starts create
 * perceived continuity. No single frame should feel "stuck" or jarring.
 *
 * BROWSER-SPECIFIC OPTIMIZATIONS:
 *   Safari: Uses isolation + translateZ(0) for predictable GPU layer lifecycle.
 *           Explicit transform reset on layer removal prevents memory pressure.
 *   Mobile: touch-action: manipulation eliminates 300ms tap delay on all devices.
 *           Combined with -webkit-touch-callout: none for clean touch experience.
 *   Print:  @media print disables all animations/transitions and removes GPU hints.
 *           Ensures clean output when printing meeting transcripts or configs.
 *   Forced Colors: @media (forced-colors: active) ensures loading indicators
 *           remain visible in Windows High Contrast Mode using system colors.
 *   High Contrast: @media (prefers-contrast: more) enhances visibility for users
 *           who prefer higher contrast without fully overriding the design.
 *   Color Scheme: Explicit color-scheme declaration and smooth color transitions
 *           prevent flicker when OS switches light/dark mode mid-animation.
 *   Scroll Anchor: overflow-anchor: none during loading prevents browser scroll
 *           anchoring from fighting with programmatic scrollTo, eliminating jitter.
 *   Orientation: Device rotation during transitions applies strict containment
 *           and pauses animations to prevent GPU layer invalidation flicker.
 *   All:    contain: layout style prevents sibling reflows during transition.
 * ======================================================================== */
:root {
    --transition-instant: 0.05s;
    --transition-fast: 0.15s;
    --transition-medium: 0.2s;
    --transition-slow: 0.3s;
    --skeleton-delay: 320ms;
    --easing-smooth: ease-out;
    --easing-decel: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Alpine.js cloak - hides elements until Alpine initializes to prevent FOUC */
[x-cloak] {
    display: none !important;
}

/* Screen reader only - visually hidden but accessible to assistive tech */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Fade-in animation for refreshed content */
@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.animate-fade-in {
  animation: fade-in var(--transition-slow) ease-in;
}

.applicant-card {
  transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}

.applicant-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
}


/* Outer scrollbar configuration - document-level scroll behavior
 * This enables smooth scrolling for anchor links, keyboard navigation (Tab/Shift+Tab),
 * and skip-to-content links while respecting reduced motion preferences.
 * scroll-padding-top accounts for the fixed header height (pt-16 = 4rem = 64px)
 * so focused elements and anchor targets don't scroll under the header.
 *
 * This completes the outer scrollbar pattern by ensuring the browser's native
 * scroll behavior works correctly with the document.documentElement scroll container
 * used in autoscroll.js. */
html {
    scroll-behavior: smooth;
    scroll-padding-top: 4.5rem; /* Header height (4rem/64px) + small buffer for visual breathing room */
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

body {
    font-family: 'Roboto', sans-serif;
}

/* Smooth transition for content loading states */
#content {
    transition: opacity var(--transition-medium) var(--easing-smooth);
}

/* GPU compositing hint during active transitions
 * Applied via JS during htmx:beforeRequest, removed after htmx:afterSettle
 * Prevents micro-stutter by pre-promoting element to compositor layer
 * Only active during transitions to avoid idle memory overhead */
#content.will-animate {
    will-change: opacity, transform;
    /* Contain layout thrashing during transition - prevents sibling reflows */
    contain: layout style;
}

/* Safari-specific GPU layer optimization
 * Safari handles compositor layer promotion differently than Chrome/Firefox:
 * - More aggressive memory allocation per layer
 * - Slower layer release after will-change removal
 * - Benefits from explicit isolation context
 *
 * Detection: -webkit-backdrop-filter is Safari/WebKit only (not in Firefox)
 * The isolation property creates a stacking context that helps Safari
 * manage the GPU layer lifecycle more predictably. Combined with
 * transform: translateZ(0) as a fallback hint for older Safari versions.
 */
@supports (-webkit-backdrop-filter: blur(1px)) {
    #content.will-animate {
        isolation: isolate;
        -webkit-transform: translateZ(0);
        transform: translateZ(0);
    }

    /* Force layer release in Safari by explicitly resetting transform
     * Safari sometimes holds onto GPU layers after will-change removal;
     * this ensures the layer is properly released to free memory */
    #content:not(.will-animate) {
        -webkit-transform: none;
        transform: none;
    }
}

/* Skeleton entrance animation for smooth page transitions */
#content-loading-skeleton {
    opacity: 0;
    transition: opacity 0.2s ease-out;
}

#content-loading-skeleton:not(.hidden) {
    opacity: 1;
}

/* Skeleton staggered children animation - cascading reveal */
@keyframes skeleton-child-enter {
    from {
        opacity: 0;
        transform: translateY(4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

#content-loading-skeleton:not(.hidden) > div > * {
    opacity: 0;
    animation: skeleton-child-enter 0.2s ease-out forwards;
}

#content-loading-skeleton:not(.hidden) > div > *:nth-child(1) { animation-delay: 0ms; }
#content-loading-skeleton:not(.hidden) > div > *:nth-child(2) { animation-delay: 50ms; }
#content-loading-skeleton:not(.hidden) > div > *:nth-child(3) { animation-delay: 100ms; }
#content-loading-skeleton:not(.hidden) > div > *:nth-child(4) { animation-delay: 150ms; }

@media (prefers-reduced-motion: reduce) {
    #content-loading-skeleton:not(.hidden) > div > * {
        animation: none;
        opacity: 1;
        transform: none;
    }
}

/* Loading bar completion glow - signals success with satisfying finish
 * The color transition from indigo (working) to green (success) provides
 * clear psychological closure. Users perceive color change + glow as a
 * single unified "done" moment rather than just the bar reaching 100%.
 * The brief scaleY pulse creates physical "arrival" sensation. */
#loading-bar.loading-complete {
    background-color: #22c55e;
    box-shadow: 0 0 16px 3px rgba(34, 197, 94, 0.7),
                0 0 4px 1px rgba(34, 197, 94, 0.9);
    transform: scaleY(1.3);
    transition: background-color 0.1s ease-out,
                box-shadow 0.15s ease-out,
                transform 0.15s ease-out;
}

/* HTMX swap transition for smooth content changes
 * NOTE: Previously had opacity:0 here, but this conflicted with our
 * content-reveal animation which starts from 0.4 (matching loading-dimmed).
 * The 0->0.4 jump caused visible flicker. Now we maintain the dimmed state
 * through the swap, letting content-reveal handle the smooth 0.4->1 reveal.
 * The swap itself is instant - opacity continuity comes from matching states.
 *
 * Iteration 40: Added transform: translateZ(0) to pre-promote to compositor
 * layer. This ensures the element is GPU-composited BEFORE the DOM swap,
 * so the subsequent htmx-settling phase inherits an existing layer rather
 * than requesting a new one. Creates unbroken compositor continuity. */
#content.htmx-swapping {
    opacity: 0.4;
    transform: translateZ(0);
}

/* HTMX settling phase - maintain dimmed opacity until animation takes over
 * Critical: This bridges the gap between htmx-swapping (0.4) and when JS
 * applies content-entering animation (starts at 0.4). Without this, there
 * is a single-frame flash where opacity jumps 0.4 -> 1 -> 0.4 -> 1.
 *
 * Timeline:
 *   htmx-swapping: opacity 0.4
 *   htmx-settling: opacity 0.4 (this rule - holds the dimmed state)
 *   content-entering animation: 0.4 -> 1 (smooth reveal)
 *
 * The animation's forwards fill-mode ensures opacity stays at 1 after
 * completing, even when htmx-settling is eventually removed by HTMX.
 *
 * Iteration 40: Added transform: translateZ(0) to force compositor layer
 * continuity during the htmx-swapping -> htmx-settling class transition.
 * Without explicit GPU promotion, the browser may drop the compositor layer
 * when htmx-swapping is removed, causing a micro-repaint before htmx-settling
 * is evaluated. This 0-cost transform ensures the element stays composited
 * through the class change, eliminating the final frame-level flicker. */
#content.htmx-settling {
    opacity: 0.4;
    transform: translateZ(0);
}

/* ========================================================================
 * Page Entrance Animation - Smooth content reveal after HTMX swap
 * Creates visual continuity from loading skeleton to actual content
 *
 * NOTE: This animation handles ONLY the transform (slide-up effect).
 * Opacity is handled separately by content-reveal animation to prevent
 * competing opacity values (page-enter was 0->1, content-reveal is 0.4->1).
 * Single responsibility: page-enter = motion, content-reveal = opacity.
 * ======================================================================== */

@keyframes page-enter {
    from {
        transform: translateY(4px);
    }
    to {
        transform: translateY(0);
    }
}

/* Applied after htmx:afterSettle - new content slides up */
#content.page-enter-active {
    animation: page-enter var(--transition-fast) var(--easing-smooth) forwards;
}

/* Content reveal animation - bridges HTMX swap with smooth entrance
 * Creates a unified opacity transition from the dimmed loading state (0.4)
 * to full opacity (1.0). The htmx-swapping class also uses 0.4, creating
 * continuous opacity through the swap: loading-dimmed(0.4) -> swap(0.4) -> reveal(0.4->1).
 * This eliminates the opacity jumps that previously caused flicker. */
@keyframes content-reveal {
    from { opacity: 0.4; }
    to { opacity: 1; }
}

#content.content-entering {
    animation: content-reveal var(--transition-medium) var(--easing-smooth) forwards;
    will-change: opacity; /* Maintain compositor layer promotion during reveal */
    backface-visibility: hidden; /* Force 2D rendering for cleaner opacity blend, eliminating sub-pixel flicker */
}

@media (prefers-reduced-motion: reduce) {
    #content.page-enter-active {
        animation: none;
        opacity: 1;
        transform: none;
    }
    #content.content-entering {
        animation: none;
        opacity: 1;
    }
}

h1 {
    font-size: 24px;
    font-weight: 700;
}

h2 {
    font-size: 20px;
    font-weight: 500;
}

p, span, li {
    font-size: 16px;
    line-height: 1.5;
}

small {
    font-size: 14px;
    font-weight: 300;
}

.glow-border {
    position: relative;
    animation: glow 1.5s infinite alternate;
}

@keyframes glow {
    from {
        box-shadow: 0 0 5px rgba(134, 187, 216, 0.3), 0 0 10px rgba(134, 187, 216, 0.3), 0 0 15px rgba(134, 187, 216, 0.3);
    }
    to {
        box-shadow: 0 0 10px rgba(134, 187, 216, 0.6), 0 0 20px rgba(134, 187, 216, 0.6), 0 0 30px rgba(134, 187, 216, 0.6);
    }
}

button:hover { transform: scale(1.05); }
button { transition: transform 0.3s; }
img:not(.nozoom):hover { transform: scale(1.5);}
img {transition: transform 0.3s;}

/* Chat images - stable sizing to prevent layout shift on bfcache restore
 * Use contain: content (not layout style) for better browser compatibility
 * 128px max for thumbnails, prevents expansion on back navigation */
.chat-images {
  contain: content;
}
.chat-image {
  max-width: 128px !important;
  width: auto !important;
  height: auto !important;
  object-fit: contain;
}

.disabled { opacity: 0.5; pointer-events: none; }

.htmx-indicator {
  opacity: 0;
  transition: opacity 200ms ease-in;
}
.htmx-request .htmx-indicator {
  opacity: 1;
}
.htmx-request.htmx-indicator {
  opacity: 1;
}
.spinner {
  width: 20px;
  height: 20px;
  border: 2px solid #f3f3f3;
  border-top: 2px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}
@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.htmx-indicator{
    opacity:0;
    transition: opacity 500ms ease-in;
}
.htmx-request .htmx-indicator{
    opacity:1
}
.htmx-request.htmx-indicator{
    opacity:1
}

/* Main container for markdown content */
.prose {
    max-width: 75ch; /* Ideal width for readability */
    margin: auto; /* Center the content */
    padding: 1rem 0.75rem; /* Mobile: reduced padding */
    color: #e5e7eb; /* Light text for a dark background */
    line-height: 1.75; /* Smooth line flow */
    font-size: 1rem; /* Standard readable font size */
}

/* Tablet and up: restore original prose padding */
@media (min-width: 768px) {
    .prose {
        padding: 2rem 1rem;
    }
}

/* Headings */
.prose h1 {
    font-size: 2rem; /* Balanced size for main headings */
    font-weight: 700;
    color: #f97316; /* Distinctive orange for emphasis */
    margin-bottom: 1rem; /* Space below the heading */
}

.prose h2 {
    font-size: 1.5rem; /* Smaller than h1 for hierarchy */
    font-weight: 600;
    color: #fbbf24; /* Softer yellow for subheadings */
    margin-top: 2rem;
    margin-bottom: 1rem;
}

.prose h3 {
    font-size: 1.25rem; /* Tertiary size for sub-subheadings */
    font-weight: 600;
    color: #cbd5e1; /* Muted white for secondary emphasis */
    margin-top: 1.5rem;
    margin-bottom: 1rem;
}

/* Paragraphs */
.prose p {
    /* Keep spacing between paragraphs tight */
    margin-bottom: 0.25rem;
}

/* Lists */
.prose ul, .prose ol {
    margin-left: 1.5rem; /* Indent lists */
    margin-bottom: 0.5rem; /* Space between paragraphs */
}

.prose li {
    margin-bottom: 0.75rem; /* Space between list items */
}

/* Links */
.prose a {
    text-decoration: underline;
    color: #3b82f6; /* Soft blue for contrast */
    transition: color 0.2s ease;
}

.prose a:hover {
    color: #60a5fa; /* Brighter blue on hover */
}

/* Blockquotes */
.prose blockquote {
    border-left: 4px solid #f97316; /* Distinctive orange bar */
    padding-left: 1rem;
    color: #d1d5db;
    margin: 1.5rem 0;
    font-style: italic;
}

/* Code blocks */
.prose pre {
    background: #1e293b; /* Darker background for code */
    padding: 0.75rem;
    border-radius: 0.5rem; /* Smooth edges */
    white-space: pre-wrap; /* Wrap code lines */
    word-break: break-word; /* Break long tokens */
    overflow-wrap: anywhere; /* Ensure container width */
    color: #a6e3a1; /* Light green for code text */
    font-size: 0.8125rem; /* Slightly smaller on mobile */
    max-width: 100%;
    overflow-x: auto;
}

@media (min-width: 768px) {
    .prose pre {
        padding: 1rem;
        font-size: 0.875rem;
    }
}

.prose code {
    background: #334155; /* Subtle highlight */
    padding: 0.2rem 0.4rem;
    border-radius: 0.25rem;
    color: #a6e3a1; /* Light green */
}

/* Horizontal rule */
.prose hr {
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.2); /* Subtle line */
    margin: 2rem 0;
}

/* Images */
.prose img {
    display: block;
    max-width: 100%; /* Fully responsive */
    margin: 2rem auto; /* Center images */
    border-radius: 0.5rem; /* Rounded corners */
}

/* Streaming response images - constrain to container and prevent layout shift
 * 600px max for markdown-rendered images in AI responses
 * contain: content for layout stability on bfcache restore */
.streaming_response img {
    max-width: 600px;
    width: 100%;
    height: auto;
    contain: content;
}

/* Tables */
.prose table {
    width: 100%;
    border-collapse: collapse;
    margin: 2rem 0;
    font-size: 1rem;
}

.prose th, .prose td {
    border: 1px solid rgba(255, 255, 255, 0.2);
    padding: 0.75rem;
    text-align: left;
}

.prose th {
    background: #1e293b; /* Dark header */
    color: #e5e7eb;
}

#loading-bar {
  opacity: 0;
  /* Cubic-bezier for perceived progress: fast start, gradual slowdown
   * Creates illusion of "working hard then wrapping up" - waits feel shorter
   * 0.4,0,0.2,1 is Material Design standard easing for natural deceleration */
  transition: width 3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.15s ease-out 0.1s;
}

/* Loading bar becomes visible when actively loading
 * Subtle pulsing glow creates "breathing" effect during progress
 * Signals active work even when width progress slows near 90%
 * Connects visually to the button pulse that initiated the action */
#loading-bar.loading-active {
  opacity: 1;
  animation: loading-bar-pulse 2s ease-in-out infinite;
}

@keyframes loading-bar-pulse {
  0%, 100% {
    box-shadow: 0 0 8px 1px rgba(99, 102, 241, 0.4),
                0 0 2px 0 rgba(99, 102, 241, 0.6);
  }
  50% {
    box-shadow: 0 0 16px 3px rgba(99, 102, 241, 0.6),
                0 0 4px 1px rgba(99, 102, 241, 0.8);
  }
}

@media (prefers-reduced-motion: reduce) {
  #loading-bar.loading-active {
    animation: none;
    box-shadow: 0 0 8px 1px rgba(99, 102, 241, 0.5);
  }
}

/* Spinner container */
#spinner {
  justify-content: center;
  align-items: center;
  height: 16rem; /* equivalent to h-64 */
}

/* Spinner SVG */
.spinner-svg {
  width: 60px;
  height: 60px;
  animation: rotate 2s linear infinite;
}

/* Spinner path */
.spinner-path {
  stroke-dasharray: 150;
  stroke-dashoffset: 0;
  stroke-linecap: round;
  animation: dash 1.5s ease-in-out infinite;
  filter: drop-shadow(0 0 2px rgba(255, 255, 255, 0.7));
}

/* Communicating text */
.communicating-text {
  animation: pulse 2s ease-in-out infinite;
  color: #FFFFFF;
  text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
}

/* Rotate animation */
@keyframes rotate {
  100% { transform: rotate(360deg); }
}

/* Dash animation */
@keyframes dash {
  0% {
    stroke-dashoffset: 150;
  }
  50% {
    stroke-dashoffset: 75;
  }
  100% {
    stroke-dashoffset: 0;
  }
}

/* Pulse animation for text */
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

.streaming_response {
    position: relative;
    margin: 1.25em 2em;
    padding: 1.25em 1.5em;
    background: rgba(255, 255, 255, 0.02);  /* Much subtler */
    border-radius: 6px;
    width: auto;
    max-width: 90%;  /* Slightly wider */
    color: inherit;
    line-height: 1.5;
}

.user_message {
    position: relative;
    margin: 1.25em 0.75em;
    padding: 1em 1rem;
    background: rgba(255, 255, 255, 0.01);  /* Even subtler for user */
    border-radius: 6px;
    width: auto;
    max-width: 100%;
    color: inherit;
    line-height: 1.5;
}

/* Tablet and up: restore original spacing */
@media (min-width: 768px) {
    .user_message {
        margin: 1.25em 2em;
        padding: 1.25em 1.5em;
        max-width: 90%;
    }
}

/* ========================================================================
 * Chat Message Entrance Animations
 * Subtle animations for new messages to feel responsive and polished
 * ======================================================================== */

/* User message: slide in from right */
@keyframes message-enter-user {
    from {
        opacity: 0;
        transform: translateX(16px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* AI response: fade in with subtle rise */
@keyframes message-enter-ai {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* AI header: fade in */
@keyframes header-enter {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

/* Apply animations to chat elements */
.user_message {
    animation: message-enter-user 0.25s ease-out;
}

.streaming_response {
    animation: message-enter-ai 0.3s ease-out;
}

/* AI chat header container (parent of avatar and name) */
.flex.items-center.space-x-4.p-4.rounded-lg:has(img[id^="agent-"]) {
    animation: header-enter 0.2s ease-out;
}

/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
    .user_message,
    .streaming_response,
    .flex.items-center.space-x-4.p-4.rounded-lg:has(img[id^="agent-"]) {
        animation: none;
    }
}

/* ========================================================================
 * Tool Call Display - Cleaner formatting for tool executions
 * ======================================================================== */

.tool_called {
    display: block;
    margin-bottom: 0.75em;
    margin-left: 0.5em;
    margin-right: 0.5em;
    padding: 0;
    background: rgba(34, 197, 94, 0.08);
    border-left: 3px solid #22c55e;
    border-radius: 6px;
    width: auto;
    max-width: 100%;
    color: inherit;
    line-height: 1.5;
    overflow: hidden;
    /* Smooth transitions when state changes (pending -> complete/error) and hover */
    transition: background-color 0.3s ease,
                border-left-color 0.3s ease,
                transform 0.15s ease-out,
                box-shadow 0.15s ease-out;
}

/* Hover effect: subtle lift and enhanced glow */
.tool_called:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(34, 197, 94, 0.15),
                0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Pending state hover: yellow/amber glow */
.tool_called--pending:hover {
    box-shadow: 0 4px 12px rgba(251, 191, 36, 0.15),
                0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Error state hover: red glow */
.tool_called--error:hover {
    box-shadow: 0 4px 12px rgba(239, 68, 68, 0.15),
                0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Visual separator between consecutive tool calls for better distinction */
.tool_called + .tool_called {
    margin-top: 1em;
    position: relative;
}

/* Collapsed completed tool calls: tighter spacing for compact view */
details.tool_called:not([open]) + details.tool_called:not([open]) {
    margin-top: 0.35em;
}

/* Collapsed completed tool calls: muted styling */
details.tool_called:not([open]):not(.tool_called--pending):not(.tool_called--error) {
    background: rgba(34, 197, 94, 0.04);
    border-left-width: 2px;
}

details.tool_called:not([open]):not(.tool_called--pending):not(.tool_called--error) > .tool_called_header {
    background: rgba(34, 197, 94, 0.06);
    padding: 0.35rem 0.75rem;
}

details.tool_called:not([open]):not(.tool_called--pending):not(.tool_called--error) .tool_called_name {
    opacity: 0.8;
}

/* No separator line between collapsed calls - they're compact now */
details.tool_called:not([open]) + details.tool_called:not([open])::before {
    display: none;
}

/* Subtle connecting line between consecutive tool calls */
.tool_called + .tool_called::before {
    content: '';
    position: absolute;
    top: -0.625em; /* Half of the 1em margin-top + a bit */
    left: 1.5em;
    right: 1.5em;
    height: 1px;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.08) 20%,
        rgba(255, 255, 255, 0.08) 80%,
        transparent 100%
    );
    pointer-events: none;
}

/* Tablet and up: restore original spacing for tool calls */
@media (min-width: 768px) {
    .tool_called {
        margin-left: 2em;
        margin-right: 0;
        max-width: 95%;
    }

    /* Larger gap and wider separator line on desktop */
    .tool_called + .tool_called {
        margin-top: 1.25em;
    }

    .tool_called + .tool_called::before {
        top: -0.75em;
        left: 2em;
        right: 2em;
    }
}

/* Make tool_called a details element - hide default marker */
details.tool_called {
    list-style: none;
}

details.tool_called::-webkit-details-marker {
    display: none;
}

details.tool_called > summary {
    list-style: none;
}

details.tool_called > summary::-webkit-details-marker {
    display: none;
}

details.tool_called > summary::marker {
    display: none;
    content: '';
}

/* When collapsed, no bottom border on header */
details.tool_called:not([open]) > .tool_called_header {
    border-bottom: none;
}

.tool_called_header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: rgba(34, 197, 94, 0.12);
    border-bottom: 1px solid rgba(34, 197, 94, 0.15);
    font-weight: 500;
    transition: background-color 0.3s ease,
                border-bottom-color 0.3s ease;
    flex-wrap: wrap;
    cursor: pointer;
    user-select: none;
}

.tool_called_header:hover {
    background: rgba(34, 197, 94, 0.18);
}

/* Expand indicator on header */
.tool_called_header::after {
    content: '▶';
    margin-left: auto;
    font-size: 0.6rem;
    opacity: 0.5;
    transition: transform 0.2s ease;
}

details.tool_called[open] > .tool_called_header::after {
    transform: rotate(90deg);
}

/* Tool call body container */
.tool_called_body {
    padding: 0.75rem 1rem;
}

/* ========================================================================
 * Tool Call Group - Groups multiple completed calls into a single summary
 * ======================================================================== */

.tool_called_group {
    display: block;
    margin-bottom: 0.75em;
    margin-left: 0.5em;
    margin-right: 0.5em;
    background: rgba(34, 197, 94, 0.04);
    border-left: 2px solid rgba(34, 197, 94, 0.4);
    border-radius: 6px;
    overflow: hidden;
}

.tool_called_group::-webkit-details-marker {
    display: none;
}

.tool_called_group > summary {
    list-style: none;
}

.tool_called_group > summary::-webkit-details-marker {
    display: none;
}

.tool_called_group > summary::marker {
    display: none;
    content: '';
}

.tool_called_group_header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    background: rgba(34, 197, 94, 0.06);
    font-weight: 500;
    cursor: pointer;
    user-select: none;
    font-size: 0.85rem;
}

.tool_called_group_header:hover {
    background: rgba(34, 197, 94, 0.12);
}

/* Enhanced focus styles for keyboard navigation accessibility */
.tool_called_group_header:focus {
    outline: none;
}

.tool_called_group_header:focus-visible {
    outline: 2px solid rgba(74, 222, 128, 0.6);
    outline-offset: 2px;
    background: rgba(34, 197, 94, 0.12);
}

.tool_called_group_header::after {
    content: '▶';
    margin-left: auto;
    font-size: 0.6rem;
    opacity: 0.5;
    transition: transform 0.2s ease;
}

details.tool_called_group[open] > .tool_called_group_header::after {
    transform: rotate(90deg);
}

.tool_called_group_count {
    color: #4ade80;
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
    font-size: 0.8rem;
}

.tool_called_group_names {
    color: #9ca3af;
    font-size: 0.75rem;
    opacity: 0.8;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Use flex-based sizing instead of fixed percentage for responsive truncation */
    flex: 1 1 auto;
    min-width: 0;
}

.tool_called_group_body {
    padding: 0.5rem;
    border-top: 1px solid rgba(34, 197, 94, 0.1);
}

.tool_called_group_body .tool_called {
    margin-left: 0;
    margin-right: 0;
}

/* Inline summary for 1-2 completed calls - minimal visual footprint */
.tool_called_inline_summary {
    font-size: 0.75rem;
    color: #6b7280;
    margin-bottom: 0.5em;
    margin-left: 0.5em;
}

.tool_called_inline {
    display: inline-flex;
    align-items: center;
    gap: 0.2em;
    padding: 0.1em 0.4em;
    background: rgba(34, 197, 94, 0.06);
    border-radius: 3px;
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
}

.tool_called_inline_check {
    color: #4ade80;
    font-size: 0.7em;
}

@media (min-width: 768px) {
    .tool_called_group {
        margin-left: 2em;
        margin-right: 0;
        max-width: 95%;
    }
}

@media (min-width: 768px) {
    .tool_called_header {
        padding: 0.6rem 1rem;
        flex-wrap: nowrap;
    }
}

.tool_called_icon {
    font-size: 0.9rem;
    opacity: 0.9;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* Tool type icon (file, terminal, search, web, etc.) */
.tool_called_type_icon {
    display: inline-flex;
    opacity: 0.7;
}

.tool_called_type_icon svg {
    stroke: currentColor;
}

.tool_called_name {
    color: #4ade80;
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
    font-size: 0.8rem;
    transition: color 0.3s ease;
    min-width: 0;
    /* Text truncation for long tool names */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Spinner for pending state */
.tool_called_spinner {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid #fbbf24;
    border-top-color: transparent;
    border-radius: 50%;
    animation: tool-spinner 0.8s linear infinite;
}

@keyframes tool-spinner {
    to {
        transform: rotate(360deg);
    }
}

@media (min-width: 768px) {
    .tool_called_name {
        font-size: 0.875rem;
        /* Allow more space on desktop before truncating */
        max-width: 40ch;
    }
}

.tool_called_section {
    padding: 0.5rem 0.75rem;
    position: relative;
}

@media (min-width: 768px) {
    .tool_called_section {
        padding: 0.5rem 1rem;
    }
}

.tool_called_section + .tool_called_section {
    border-top: 1px solid rgba(255, 255, 255, 0.05);
}

.tool_called_label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #9ca3af; /* Improved contrast for WCAG AA */
    margin-bottom: 0.25rem;
    font-weight: 500;
}

/* Collapsible section styling for details/summary */
details.tool_called_section {
    /* Remove default marker spacing */
}

details.tool_called_section > summary.tool_called_label {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    user-select: none;
    transition: color 0.15s ease;
}

details.tool_called_section > summary.tool_called_label:hover {
    color: #d1d5db;
}

/* Focus styling for keyboard accessibility */
details.tool_called_section > summary.tool_called_label:focus {
    outline: none;
}

details.tool_called_section > summary.tool_called_label:focus-visible {
    outline: 2px solid #4ade80;
    outline-offset: 2px;
    border-radius: 2px;
}

/* Pending state focus uses yellow */
.tool_called--pending details.tool_called_section > summary.tool_called_label:focus-visible {
    outline-color: #fbbf24;
}

/* Error state focus uses red */
.tool_called--error details.tool_called_section > summary.tool_called_label:focus-visible {
    outline-color: #ef4444;
}

/* Custom disclosure triangle */
details.tool_called_section > summary.tool_called_label::before {
    content: '';
    display: inline-block;
    width: 0;
    height: 0;
    border-left: 4px solid currentColor;
    border-top: 3px solid transparent;
    border-bottom: 3px solid transparent;
    transition: transform 0.15s ease;
    flex-shrink: 0;
}

details[open].tool_called_section > summary.tool_called_label::before {
    transform: rotate(90deg);
}

/* Hide browser default marker */
details.tool_called_section > summary.tool_called_label::-webkit-details-marker {
    display: none;
}

details.tool_called_section > summary.tool_called_label::marker {
    display: none;
    content: '';
}

/* Smooth content reveal animation */
details.tool_called_section .tool_called_content {
    animation: tool-content-reveal 0.2s ease-out;
}

@keyframes tool-content-reveal {
    from {
        opacity: 0;
        transform: translateY(-4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.tool_called_status {
    font-size: 0.75rem;
    color: #9ca3af;
    margin-left: auto;
    font-weight: 400;
}

/* Execution timer for pending tool calls */
.tool_called_timer {
    font-size: 0.7rem;
    color: #9ca3af;
    font-variant-numeric: tabular-nums; /* Fixed-width digits prevent layout shift */
    margin-left: 0.5rem;
    opacity: 0.8;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.tool_called--pending .tool_called_timer {
    color: #fcd34d;
}

/* Heartbeat indicator - shows tool is actively processing */
.tool_called_heartbeat {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-left: 0.25rem;
}

.tool_called_heartbeat_dot {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: #fcd34d;
    opacity: 0.6;
    animation: heartbeat-pulse 1.2s ease-in-out infinite;
}

.tool_called_heartbeat_dot:nth-child(2) {
    animation-delay: 0.2s;
}

.tool_called_heartbeat_dot:nth-child(3) {
    animation-delay: 0.4s;
}

@keyframes heartbeat-pulse {
    0%, 100% {
        opacity: 0.3;
        transform: scale(0.8);
    }
    50% {
        opacity: 1;
        transform: scale(1);
    }
}

/* Stalled state - tool running longer than expected with no progress */
.tool_called_timer--stalled .tool_called_heartbeat_dot {
    background: #f97316; /* Orange for warning */
    animation: heartbeat-stalled 2s ease-in-out infinite;
}

@keyframes heartbeat-stalled {
    0%, 100% {
        opacity: 0.4;
    }
    50% {
        opacity: 0.8;
    }
}

/* Very long running indicator - amber warning after extended time */
.tool_called_timer--long {
    color: #f97316;
}

.tool_called_timer--long .tool_called_heartbeat_dot {
    background: #f97316;
}

/* Critical duration - red indicator for potentially stuck tools */
.tool_called_timer--critical {
    color: #ef4444;
}

.tool_called_timer--critical .tool_called_heartbeat_dot {
    background: #ef4444;
    animation: heartbeat-critical 0.8s ease-in-out infinite;
}

@keyframes heartbeat-critical {
    0%, 100% {
        opacity: 0.5;
        transform: scale(0.9);
    }
    50% {
        opacity: 1;
        transform: scale(1.1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .tool_called_heartbeat_dot,
    .tool_called_timer--stalled .tool_called_heartbeat_dot,
    .tool_called_timer--critical .tool_called_heartbeat_dot {
        animation: none;
        opacity: 0.8;
        transform: scale(1);
    }
}

/* Final duration display for completed tool calls */
.tool_called_duration {
    font-size: 0.7rem;
    color: #6b7280;
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

/* Tool count badge in message header */
.tool_count_badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.7rem;
    padding: 0.15rem 0.5rem;
    border-radius: 9999px;
    font-variant-numeric: tabular-nums;
    margin-left: 0.5rem;
    transition: background 0.2s ease, color 0.2s ease;
}

.tool_count_badge--pending {
    background: rgba(234, 179, 8, 0.15);
    color: #eab308;
}

.tool_count_badge--complete {
    background: rgba(34, 197, 94, 0.15);
    color: #22c55e;
}

.tool_count_badge--error {
    background: rgba(239, 68, 68, 0.15);
    color: #ef4444;
}

.tool_count_badge--disconnected {
    background: rgba(107, 114, 128, 0.15);
    color: #9ca3af;
}

/* Tool filter bar - filter visible tools by type */
.tool_filter_bar {
    display: none; /* Hidden by default, shown via JS when >3 tools */
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.5rem;
    background: rgba(255, 255, 255, 0.02);
    border-radius: 4px;
    border: 1px solid rgba(255, 255, 255, 0.05);
}

.tool_filter_bar--visible {
    display: flex;
}

.tool_filter_btn {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    font-size: 0.7rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 9999px;
    background: transparent;
    color: #9ca3af;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.tool_filter_btn:hover {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(255, 255, 255, 0.2);
    color: #d1d5db;
}

.tool_filter_btn--active {
    background: rgba(74, 222, 128, 0.15);
    border-color: rgba(74, 222, 128, 0.3);
    color: #4ade80;
}

.tool_filter_btn--active:hover {
    background: rgba(74, 222, 128, 0.2);
    border-color: rgba(74, 222, 128, 0.4);
}

.tool_filter_btn:focus-visible {
    outline: 2px solid #4ade80;
    outline-offset: 1px;
}

.tool_filter_btn svg {
    width: 10px;
    height: 10px;
    stroke: currentColor;
}

/* Hide filtered-out tools */
.tool_called--filtered {
    display: none !important;
}

/* Expand/collapse all toggle buttons */
.tool_called_toggle_all {
    display: flex;
    gap: 0.25rem;
    margin-left: 0.5rem;
    opacity: 0;
    transition: opacity 0.15s ease;
}

.tool_called:hover .tool_called_toggle_all,
.tool_called_toggle_all:focus-within {
    opacity: 1;
}

.tool_called_toggle_btn {
    background: transparent;
    border: none;
    color: #6b7280;
    padding: 0.125rem 0.25rem;
    cursor: pointer;
    border-radius: 0.25rem;
    font-size: 0.65rem;
    line-height: 1;
    transition: background 0.15s ease, color 0.15s ease;
}

.tool_called_toggle_btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #d1d5db;
}

.tool_called_toggle_btn:focus-visible {
    outline: 2px solid #4ade80;
    outline-offset: 1px;
}

/* Global keyboard shortcut hints in filter bar */
.tool_shortcut_hints {
    display: none;
    align-items: center;
    gap: 0.75rem;
    margin-left: auto;
    padding-left: 0.75rem;
    border-left: 1px solid rgba(255, 255, 255, 0.1);
    font-size: 0.65rem;
    color: #6b7280;
}

/* Show hints on desktop when filter bar is visible */
@media (min-width: 768px) {
    .tool_filter_bar--visible .tool_shortcut_hints {
        display: flex;
    }
}

.tool_shortcut_hint {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    white-space: nowrap;
}

.tool_shortcut_kbd {
    display: inline-block;
    padding: 0.1rem 0.3rem;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 3px;
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
    font-size: 0.6rem;
    color: #9ca3af;
    line-height: 1;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
}

/* Subtle hover effect on shortcut hints */
.tool_shortcut_hint:hover .tool_shortcut_kbd {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.25);
    color: #d1d5db;
}

/* Active flash when shortcut is triggered */
.tool_shortcut_hint--active {
    animation: shortcut-flash 0.3s ease-out;
}

.tool_shortcut_hint--active .tool_shortcut_kbd {
    background: rgba(74, 222, 128, 0.3);
    border-color: rgba(74, 222, 128, 0.5);
    color: #4ade80;
}

@keyframes shortcut-flash {
    0% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.05);
    }
    100% {
        transform: scale(1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .tool_shortcut_hint--active {
        animation: none;
    }
}

/* Retry button for failed tool calls */
.tool_called_retry {
    background: transparent;
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: #ef4444;
    padding: 0.25rem 0.5rem;
    cursor: pointer;
    border-radius: 0.25rem;
    font-size: 0.7rem;
    line-height: 1;
    margin-left: auto;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.tool_called_retry:hover {
    background: rgba(239, 68, 68, 0.1);
    border-color: rgba(239, 68, 68, 0.5);
}

.tool_called_retry:focus-visible {
    outline: 2px solid #ef4444;
    outline-offset: 1px;
}

.tool_called_retry:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.tool_called_content {
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
    font-size: 0.8rem;
    color: #d1d5db;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-wrap: anywhere;
    max-height: none; /* Default: show all content */
    overflow-y: visible;
    position: relative;
    /* Enhanced monospace typography */
    line-height: 1.4; /* Tighter than prose for code/log output */
    letter-spacing: -0.01em; /* Slight tightening for monospace clarity */
    tab-size: 4; /* Standard tab width for formatted output */
    -moz-tab-size: 4;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-variant-ligatures: none; /* Disable ligatures in code */
    font-feature-settings: 'liga' 0, 'calt' 0; /* Explicit ligature disable */
}

/* Truncated state for large content */
.tool_called_content--truncated {
    max-height: 8em;
    overflow: hidden;
}

/* Expanded state for very large content */
.tool_called_content--expanded {
    max-height: 600px;
    overflow-y: auto;
}

/* Show more/less toggle button */
.tool_called_show_more {
    display: none; /* Hidden by default, shown via JS when content overflows */
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: #9ca3af;
    font-size: 0.7rem;
    padding: 0.25rem 0.5rem;
    margin-top: 0.5rem;
    cursor: pointer;
    border-radius: 0.25rem;
    transition: background 0.15s ease, color 0.15s ease;
}

.tool_called_show_more:hover {
    background: rgba(255, 255, 255, 0.05);
    color: #d1d5db;
}

.tool_called_show_more:focus-visible {
    outline: 2px solid #4ade80;
    outline-offset: 1px;
}

/* Inline argument value truncation for long values */
.tool_called_arg_value--truncated {
    display: inline;
}

.tool_called_arg_value--truncated .tool_called_arg_preview {
    color: #9ca3af;
}

.tool_called_arg_value--truncated .tool_called_arg_full {
    display: none;
}

.tool_called_arg_value--expanded .tool_called_arg_preview {
    display: none;
}

.tool_called_arg_value--expanded .tool_called_arg_full {
    display: inline;
    white-space: pre-wrap;
}

.tool_called_arg_toggle {
    color: #60a5fa;
    cursor: pointer;
    font-size: 0.75em;
    margin-left: 0.25em;
    border: none;
    background: none;
    padding: 0;
    font-family: inherit;
}

.tool_called_arg_toggle:hover {
    color: #93c5fd;
    text-decoration: underline;
}

.tool_called_arg_toggle:focus-visible {
    outline: 1px solid #60a5fa;
    outline-offset: 2px;
}

.tool_called_content--truncated + .tool_called_show_more,
.tool_called_content--expanded + .tool_called_show_more {
    display: inline-block;
}

/* Truncation fade gradient for overflowing tool content - only show when scrollable */
.tool_called_content::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 32px;
    background: linear-gradient(
        to bottom,
        rgba(34, 197, 94, 0) 0%,
        rgba(34, 197, 94, 0.06) 50%,
        rgba(34, 197, 94, 0.12) 100%
    );
    pointer-events: none;
    border-radius: 0 0 4px 4px;
    opacity: 0;
    transition: opacity 0.2s ease;
}

/* Show gradient only when content overflows (JS adds this class) */
.tool_called_content--scrollable::after {
    opacity: 1;
}

/* Hide gradient when scrolled to bottom */
.tool_called_content--scrolled-bottom::after {
    opacity: 0;
}

/* Scroll indicator arrow - appears when content is scrollable */
.tool_called_scroll_indicator {
    position: absolute;
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
    display: none;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    background: rgba(34, 197, 94, 0.15);
    border: 1px solid rgba(74, 222, 128, 0.25);
    border-radius: 50%;
    color: #4ade80;
    font-size: 10px;
    opacity: 0;
    transition: opacity 0.2s ease, transform 0.2s ease;
    pointer-events: none;
    z-index: 2;
    animation: scroll-indicator-bounce 1.5s ease-in-out infinite;
}

/* Show indicator when content is scrollable */
.tool_called_content--scrollable ~ .tool_called_scroll_indicator {
    display: flex;
    opacity: 0.8;
}

/* Hide indicator when scrolled to bottom */
.tool_called_content--scrolled-bottom ~ .tool_called_scroll_indicator {
    opacity: 0;
}

@keyframes scroll-indicator-bounce {
    0%, 100% {
        transform: translateX(-50%) translateY(0);
    }
    50% {
        transform: translateX(-50%) translateY(3px);
    }
}

/* Pending state scroll indicator - yellow theme */
.tool_called--pending .tool_called_scroll_indicator {
    background: rgba(251, 191, 36, 0.15);
    border-color: rgba(251, 191, 36, 0.25);
    color: #fbbf24;
}

/* Error state scroll indicator - red theme */
.tool_called--error .tool_called_scroll_indicator {
    background: rgba(239, 68, 68, 0.15);
    border-color: rgba(239, 68, 68, 0.25);
    color: #f87171;
}

@media (prefers-reduced-motion: reduce) {
    .tool_called_scroll_indicator {
        animation: none;
    }
}

/* Scrollbar styling for tool content - WebKit */
.tool_called_content::-webkit-scrollbar {
    width: 6px;
}

.tool_called_content::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.1);
    border-radius: 3px;
}

.tool_called_content::-webkit-scrollbar-thumb {
    background: rgba(74, 222, 128, 0.3);
    border-radius: 3px;
}

.tool_called_content::-webkit-scrollbar-thumb:hover {
    background: rgba(74, 222, 128, 0.5);
}

/* Scrollbar styling for tool content - Firefox */
.tool_called_content {
    scrollbar-width: thin;
    scrollbar-color: rgba(74, 222, 128, 0.3) transparent;
}

/* Copy button for tool results */
.tool_called_content_wrapper {
    position: relative;
}

.tool_called_copy {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid rgba(74, 222, 128, 0.2);
    border-radius: 4px;
    background: rgba(34, 197, 94, 0.1);
    color: #9ca3af;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s ease,
                background-color 0.15s ease,
                color 0.15s ease,
                border-color 0.15s ease;
    z-index: 1;
}

.tool_called_content_wrapper:hover .tool_called_copy,
.tool_called_copy:focus {
    opacity: 1;
}

.tool_called_copy:hover {
    background: rgba(34, 197, 94, 0.2);
    border-color: rgba(74, 222, 128, 0.4);
    color: #4ade80;
}

.tool_called_copy:focus {
    outline: none;
}

.tool_called_copy:focus-visible {
    outline: 2px solid #4ade80;
    outline-offset: 2px;
    opacity: 1;
}

.tool_called_copy:active {
    transform: scale(0.95);
}

/* Icon states: default shows copy icon, success shows checkmark */
.tool_called_copy_check {
    display: none;
}

.tool_called_copy--success .tool_called_copy_icon {
    display: none;
}

.tool_called_copy--success .tool_called_copy_check {
    display: block;
    color: #4ade80;
}

.tool_called_copy--success {
    opacity: 1;
    background: rgba(34, 197, 94, 0.25);
    border-color: #4ade80;
}

/* Error state copy button - red theme to match error section */
.tool_called_copy--error {
    border-color: rgba(248, 113, 113, 0.2);
    background: rgba(239, 68, 68, 0.1);
}

.tool_called_copy--error:hover {
    background: rgba(239, 68, 68, 0.2);
    border-color: rgba(248, 113, 113, 0.4);
    color: #f87171;
}

.tool_called_copy--error:focus-visible {
    outline-color: #ef4444;
}

.tool_called_copy--error.tool_called_copy--success {
    background: rgba(239, 68, 68, 0.25);
    border-color: #f87171;
}

.tool_called_copy--error.tool_called_copy--success .tool_called_copy_check {
    color: #f87171;
}

/* ------------------------------------------------------------------------
 * Tool Call States - Pending (yellow) and Error (red)
 * Creates visual progression: Blue (waiting) -> Yellow (executing) -> Green (done)
 * ------------------------------------------------------------------------ */

/* Pending/In-Progress State */
.tool_called--pending {
    background: rgba(251, 191, 36, 0.08);
    border-left-color: #fbbf24;
    /* Animation defined below in animation section */
}

.tool_called--pending .tool_called_header {
    background: rgba(251, 191, 36, 0.12);
    border-bottom-color: rgba(251, 191, 36, 0.15);
}

.tool_called--pending .tool_called_name {
    color: #fcd34d;
}

.tool_called--pending .tool_called_icon {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.tool_called--pending .tool_called_icon::after {
    content: '';
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 2px solid rgba(251, 191, 36, 0.3);
    border-top-color: #fbbf24;
    border-radius: 50%;
    animation: loadingstream-spin 0.8s linear infinite;
}

@keyframes tool-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.8; }
}

/* Disconnected State - for tools interrupted by SSE connection loss */
.tool_called--disconnected {
    background: rgba(107, 114, 128, 0.08);
    border-left-color: #6b7280;
}

.tool_called--disconnected .tool_called_header {
    background: rgba(107, 114, 128, 0.12);
    border-bottom-color: rgba(107, 114, 128, 0.15);
}

.tool_called--disconnected .tool_called_name {
    color: #9ca3af;
}

.tool_called--disconnected .tool_called_status {
    color: #6b7280;
    font-style: italic;
}

.tool_called_disconnected_icon {
    color: #6b7280;
    font-size: 0.85rem;
}

/* Disconnected state hover: gray glow */
.tool_called--disconnected:hover {
    box-shadow: 0 4px 12px rgba(107, 114, 128, 0.15),
                0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Bottom gradient for disconnected state - gray tint */
.tool_called--disconnected .tool_called_content::after {
    background: linear-gradient(
        to bottom,
        rgba(107, 114, 128, 0) 0%,
        rgba(107, 114, 128, 0.06) 50%,
        rgba(107, 114, 128, 0.12) 100%
    );
}

/* Disconnected state scroll indicator - gray theme */
.tool_called--disconnected .tool_called_scroll_indicator {
    background: rgba(107, 114, 128, 0.15);
    border-color: rgba(107, 114, 128, 0.25);
    color: #9ca3af;
}

/* Error State */
.tool_called--error {
    background: rgba(239, 68, 68, 0.08);
    border-left-color: #ef4444;
}

.tool_called--error .tool_called_header {
    background: rgba(239, 68, 68, 0.12);
    border-bottom-color: rgba(239, 68, 68, 0.15);
}

.tool_called--error .tool_called_name {
    color: #f87171;
}

.tool_called--error .tool_called_content {
    scrollbar-color: rgba(248, 113, 113, 0.3) transparent;
}

.tool_called--error .tool_called_content::-webkit-scrollbar-thumb {
    background: rgba(248, 113, 113, 0.3);
}

.tool_called--error .tool_called_content::-webkit-scrollbar-thumb:hover {
    background: rgba(248, 113, 113, 0.5);
}

/* Bottom gradient for pending state - yellow/amber tint */
.tool_called--pending .tool_called_content::after {
    background: linear-gradient(
        to bottom,
        rgba(251, 191, 36, 0) 0%,
        rgba(251, 191, 36, 0.06) 50%,
        rgba(251, 191, 36, 0.12) 100%
    );
}

/* Bottom gradient for error state - red tint */
.tool_called--error .tool_called_content::after {
    background: linear-gradient(
        to bottom,
        rgba(239, 68, 68, 0) 0%,
        rgba(239, 68, 68, 0.06) 50%,
        rgba(239, 68, 68, 0.12) 100%
    );
}

/* Entrance animation for tool calls */
.tool_called {
    animation: tool-enter 0.25s ease-out;
}

@keyframes tool-enter {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Pending state: combine entrance animation with continuous pulse */
.tool_called--pending {
    animation: tool-enter 0.25s ease-out,
               tool-pulse 2s ease-in-out 0.25s infinite;
}

/* Completing state: smooth transition from pending to complete */
.tool_called--completing {
    animation: tool-complete-flash 0.4s ease-out forwards;
}

@keyframes tool-complete-flash {
    0% {
        background: rgba(251, 191, 36, 0.08);
        border-left-color: #fbbf24;
    }
    50% {
        background: rgba(34, 197, 94, 0.15);
        border-left-color: #4ade80;
    }
    100% {
        background: rgba(34, 197, 94, 0.08);
        border-left-color: #22c55e;
    }
}

.tool_called--completing .tool_called_header {
    animation: tool-header-complete 0.4s ease-out forwards;
}

@keyframes tool-header-complete {
    0% {
        background: rgba(251, 191, 36, 0.12);
        border-bottom-color: rgba(251, 191, 36, 0.15);
    }
    100% {
        background: rgba(34, 197, 94, 0.12);
        border-bottom-color: rgba(34, 197, 94, 0.15);
    }
}

/* Spinner fade-out during completion */
.tool_called--completing .tool_called_spinner {
    animation: spinner-fade-out 0.2s ease-out forwards;
}

@keyframes spinner-fade-out {
    to {
        opacity: 0;
        transform: scale(0.5);
    }
}

/* Checkmark fade-in during completion */
.tool_called_checkmark {
    display: inline-block;
    opacity: 0;
    transform: scale(0.5);
    animation: checkmark-fade-in 0.3s ease-out 0.15s forwards;
    color: #4ade80;
}

@keyframes checkmark-fade-in {
    to {
        opacity: 1;
        transform: scale(1);
    }
}

/* Checkmark draw animation for candidate card success state */
@keyframes checkmark-draw {
    from { stroke-dashoffset: 24; }
    to { stroke-dashoffset: 0; }
}

.checkmark-draw-animation path {
    stroke-dasharray: 24;
    animation: checkmark-draw 0.3s ease-out forwards;
}

/* Error state: add brief attention-grabbing shake on appearance */
.tool_called--error {
    animation: tool-enter 0.25s ease-out,
               tool-error-shake 0.4s ease-out 0.25s;
}

@keyframes tool-error-shake {
    0%, 100% { transform: translateX(0); }
    20%, 60% { transform: translateX(-3px); }
    40%, 80% { transform: translateX(3px); }
}

/* ========================================================================
 * Loading Stream Indicator - Animated feedback during AI response generation
 * ======================================================================== */

.loadingstream {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0;
    color: #9ca3af;
    font-size: 0.9rem;
}

.loadingstream::before {
    content: '';
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(156, 163, 175, 0.3);
    border-top-color: #60a5fa;
    border-radius: 50%;
    animation: loadingstream-spin 0.8s linear infinite;
}

@keyframes loadingstream-spin {
    to { transform: rotate(360deg); }
}

/* Typing dots animation alternative */
.loadingstream-dots {
    display: inline-flex;
    gap: 4px;
    align-items: center;
}

.loadingstream-dots span {
    width: 6px;
    height: 6px;
    background: #60a5fa;
    border-radius: 50%;
    animation: loadingstream-bounce 1.4s ease-in-out infinite;
}

.loadingstream-dots span:nth-child(1) { animation-delay: 0s; }
.loadingstream-dots span:nth-child(2) { animation-delay: 0.2s; }
.loadingstream-dots span:nth-child(3) { animation-delay: 0.4s; }

@keyframes loadingstream-bounce {
    0%, 80%, 100% {
        transform: scale(0.6);
        opacity: 0.5;
    }
    40% {
        transform: scale(1);
        opacity: 1;
    }
}

/* Smooth fade-out when content arrives */
.loadingstream[style*="display: none"] {
    animation: loadingstream-fadeout 0.2s ease-out;
}

@keyframes loadingstream-fadeout {
    from { opacity: 1; }
    to { opacity: 0; }
}

.thinking_block {
    display: block;
    margin: 1.25em 0.75em;
    padding: 1em 1rem;
    background: rgba(107, 114, 128, 0.1);
    border-left: 4px solid #6b7280;
    border-radius: 6px;
    width: auto;
    max-width: 100%;
    color: inherit;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* Tablet and up: restore original spacing for thinking blocks */
@media (min-width: 768px) {
    .thinking_block {
        margin: 1.25em 2em;
        padding: 1.25em 1.5em;
        max-width: 90%;
    }
}

.thinking_block pre {
    white-space: pre-wrap;
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------------
 * 1.   Harmonise fonts / spacing between live SSE chunks and the final
 *      server‑rendered page refresh.
 *      – During streaming we show <div class="streaming_response">…</div>
 *      – After the session finishes the server sends blocks that use
 *        .ai_response (or historic .assistant_response).
 *      By pointing all three selectors at the *same* rule‑set we eliminate
 *      the “font jump” and style drift the user reported.
 * --------------------------------------------------------------------- */

.ai_response,
.assistant_response,   /* legacy alias still used in a few templates   */
.streaming_response {  /* keep existing class for backward‑compat      */
    position: relative;
    margin: 1.25em 0.75em;
    padding: 1em 1rem;
    background: rgba(255, 255, 255, 0.02);
    border-radius: 6px;
    width: auto;
    max-width: 100%;
    color: inherit;
    line-height: 1.5;
}

/* Tablet and up: restore original spacing */
@media (min-width: 768px) {
    .ai_response,
    .assistant_response,
    .streaming_response {
        margin: 1.25em 2em;
        padding: 1.25em 1.5em;
        max-width: 90%;
    }
}

/* Code blocks with copy buttons */
.code-container {
    position: relative;
}

.copy-btn {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    background: #374151;
    color: #ffffff;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    font-size: 0.75rem;
    cursor: pointer;
}

/* Shared hero headline styling */
.hero-headline {
    text-align: center;
    margin-top: 2rem;
    margin-bottom: 2rem;
    padding: 1rem;
    font-family: 'Poppins', sans-serif;
    font-weight: 800;
    font-size: 2.25rem; /* 4xl */
    background-color: #15181a; /* primaryDark-900 */
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    background-image: linear-gradient(to right, #fde047, #fb923c, #ef4444);
    text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
}

@media (min-width: 768px) {
    .hero-headline {
        font-size: 3.75rem; /* 6xl */
    }
}

@media (min-width: 1024px) {
    .hero-headline {
        font-size: 4.5rem; /* 7xl */
    }
}

/* ========================================================================
 * Accessibility - Reduced Motion Support
 * Respects user preference for reduced motion (vestibular disorders, etc.)
 * WCAG 2.3.3 (Animation from Interactions)
 * ======================================================================== */

@media (prefers-reduced-motion: reduce) {
    /* Disable all spinning/pulsing animations */
    .loadingstream::before,
    .tool_called--pending .tool_called_icon::after,
    .spinner,
    .spinner-svg {
        animation: none;
    }

    /* Disable entrance and attention animations */
    .tool_called,
    .tool_called--pending,
    .tool_called--completing,
    .tool_called--error {
        animation: none;
    }

    /* Disable hover lift effect, keep subtle shadow feedback */
    .tool_called:hover,
    .tool_called--pending:hover,
    .tool_called--error:hover {
        transform: none;
    }

    /* Disable completing state animations */
    .tool_called--completing .tool_called_header,
    .tool_called--completing .tool_called_spinner,
    .tool_called_checkmark {
        animation: none;
        opacity: 1;
        transform: none;
    }

    /* Disable bouncing dots */
    .loadingstream-dots span {
        animation: none;
        opacity: 1;
        transform: scale(1);
    }

    /* Keep static visual indicators visible */
    .loadingstream::before {
        border-color: #60a5fa;
        opacity: 0.7;
    }

    .tool_called--pending .tool_called_icon::after {
        border-color: #fbbf24;
        opacity: 0.7;
    }

    /* Disable text pulse animation */
    .communicating-text {
        animation: none;
        opacity: 1;
    }

    /* Keep transitions - they're less likely to cause issues and provide feedback */
    /* Transitions are intentionally NOT disabled */
}

/* ========================================================================
 * Skeleton Loading - Shimmer effect for loading placeholders
 * Use for cards, lists, and content areas during data fetch
 * ======================================================================== */

.skeleton {
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.03) 25%,
        rgba(255, 255, 255, 0.08) 50%,
        rgba(255, 255, 255, 0.03) 75%
    );
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.5s ease-in-out infinite;
    border-radius: 4px;
}

.skeleton-text {
    height: 1em;
    margin-bottom: 0.5em;
    border-radius: 4px;
}

.skeleton-text:last-child {
    width: 60%;
}

.skeleton-button {
    height: 2.5rem;
    width: 8rem;
    border-radius: 0.5rem;
}

@keyframes skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .skeleton {
        animation: none;
        background: rgba(255, 255, 255, 0.05);
    }
}

/* ========================================================================
 * Loading State - Inline loading indicator with text
 * Use for buttons, inline content, and small waiting states
 * ======================================================================== */

.loading-inline {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: #9ca3af;
    font-size: 0.875rem;
}

.loading-inline::before {
    content: '';
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid rgba(156, 163, 175, 0.3);
    border-top-color: #60a5fa;
    border-radius: 50%;
    animation: loadingstream-spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .loading-inline::before {
        animation: none;
        border-color: #60a5fa;
        opacity: 0.7;
    }
}

/* Slow loading state - amber/yellow to indicate delay */
.loading-inline.text-amber-400 {
    color: #fbbf24;
}

.loading-inline.text-amber-400::before {
    border-top-color: #fbbf24;
    animation-duration: 1.2s; /* Slower spin for slow state */
}

@media (prefers-reduced-motion: reduce) {
    .loading-inline.text-amber-400::before {
        border-color: #fbbf24;
    }
}

/* ========================================================================
 * Field Editor - Shared styles for array preview in persona/organization editors
 * Works with static/field-editor.js for real-time YAML array parsing
 * ======================================================================== */

/* Empty state text - adapts to parent theme */
.text-preview-empty {
    color: #9ca3af;  /* gray-400 - neutral works for both themes */
}

/* Item count indicator - green for success */
.text-preview-count {
    color: #4ade80;  /* green-400 */
}

/* Parsed item badge - subtle background */
.preview-item {
    display: inline-block;
    background: rgba(255, 255, 255, 0.08);
    padding: 0.125rem 0.375rem;
    border-radius: 0.25rem;
    margin-right: 0.25rem;
    margin-bottom: 0.25rem;
}

/* Theme overrides for persona editor (gray theme) */
.bg-gray-800 .text-preview-empty,
.bg-gray-900 .text-preview-empty {
    color: #6b7280;  /* gray-500 */
}

.bg-gray-800 .preview-item,
.bg-gray-900 .preview-item {
    background: rgba(75, 85, 99, 0.5);  /* gray-600/50 */
}

/* Theme overrides for organization editor (primaryDark theme) */
.bg-primaryDark-800 .text-preview-empty {
    color: var(--color-primaryLight-500, #9ca3af);
}

.bg-primaryDark-800 .preview-item {
    background: rgba(var(--color-primaryDark-600-rgb, 55, 65, 81), 0.5);
}

/* Drag-and-drop placeholder animation */
.field-row-placeholder {
    transition: all 0.15s ease-out;
    animation: placeholder-pulse 1.5s ease-in-out infinite;
}

@keyframes placeholder-pulse {
    0%, 100% {
        opacity: 0.8;
        box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
    }
    50% {
        opacity: 1;
        box-shadow: 0 0 0 4px rgba(59, 130, 246, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .field-row-placeholder {
        animation: none;
    }
}

/* Dirty state indicator styling */
.dirty-indicator {
    transition: all 0.3s ease-out;
    padding: 0.25rem 0.75rem;
    border-radius: 0.375rem;
    font-size: 0.875rem;
    font-weight: 500;
}

.dirty-indicator.clean {
    color: #6b7280;
    background: rgba(107, 114, 128, 0.1);
}

.dirty-indicator.dirty {
    color: #f59e0b;
    background: rgba(245, 158, 11, 0.15);
    animation: dirty-pulse 2s ease-in-out infinite;
}

@keyframes dirty-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.3);
    }
    50% {
        box-shadow: 0 0 0 3px rgba(245, 158, 11, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .dirty-indicator.dirty {
        animation: none;
        box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.3);
    }
}

/* Drag source visual feedback */
.field-row-dragging {
    opacity: 0.7 !important;
    transform: scale(1.02);
    box-shadow: 0 10px 25px rgba(59, 130, 246, 0.3),
                0 0 0 2px rgba(59, 130, 246, 0.5);
    border-radius: 0.5rem;
    transition: transform 0.15s ease-out, box-shadow 0.15s ease-out;
    z-index: 100;
    position: relative;
}

@media (prefers-reduced-motion: reduce) {
    .field-row-dragging {
        transform: none;
        box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);
    }
}

/* Save button success feedback */
.save-button-success {
    animation: save-success-pulse 0.6s ease-out;
}

@keyframes save-success-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.7);
        background-color: rgba(34, 197, 94, 0.2);
    }
    50% {
        box-shadow: 0 0 0 8px rgba(34, 197, 94, 0);
        background-color: rgba(34, 197, 94, 0.3);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(34, 197, 94, 0);
        background-color: transparent;
    }
}

@media (prefers-reduced-motion: reduce) {
    .save-button-success {
        animation: none;
        background-color: rgba(34, 197, 94, 0.2);
        transition: background-color 0.3s ease-out;
    }
}

/* Array preview entrance animation */
.array-preview {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 0.3s ease-out, opacity 0.2s ease-out, padding 0.3s ease-out;
    padding-top: 0;
    padding-bottom: 0;
}

.array-preview.active {
    max-height: 200px;
    opacity: 1;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}

/* Subtle connection line to textarea */
.array-preview.active::before {
    content: '';
    display: block;
    width: 2px;
    height: 8px;
    background: rgba(59, 130, 246, 0.3);
    margin: 0 auto 0.5rem auto;
    border-radius: 1px;
}

@media (prefers-reduced-motion: reduce) {
    .array-preview {
        transition: none;
    }
    .array-preview.active {
        max-height: none;
    }
}

/* Field row hover states */
.field-row {
    transition: background-color 0.15s ease-out, box-shadow 0.15s ease-out;
    border-radius: 0.5rem;
}

.field-row:hover {
    background-color: rgba(255, 255, 255, 0.03);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Preview item hover states */
.preview-item {
    transition: background-color 0.15s ease-out, transform 0.1s ease-out;
    cursor: default;
}

.preview-item:hover {
    background: rgba(59, 130, 246, 0.2);
    transform: translateY(-1px);
}

/* Move button active states */
.move-btn:active {
    transform: scale(0.9);
    background-color: rgba(59, 130, 246, 0.3);
}

@media (prefers-reduced-motion: reduce) {
    .field-row,
    .preview-item,
    .move-btn {
        transition: none;
    }
    .preview-item:hover {
        transform: none;
    }
    .move-btn:active {
        transform: none;
    }
}

/* Textarea focus styling */
.field-textarea:focus {
    outline: 2px solid rgba(59, 130, 246, 0.6);
    outline-offset: 2px;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
    border-color: #3b82f6;
    transition: outline 0.15s ease-out, box-shadow 0.15s ease-out, border-color 0.15s ease-out;
}

/* Array preview connection when textarea focused */
.field-textarea:focus + .array-preview.active,
.field-textarea:focus ~ .array-preview.active {
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
    border-radius: 0.375rem;
}

/* Enhanced placeholder styling */
.field-textarea::placeholder {
    color: rgba(156, 163, 175, 0.5);
    font-style: italic;
}

.field-textarea:focus::placeholder {
    color: rgba(156, 163, 175, 0.7);
}

@media (prefers-reduced-motion: reduce) {
    .field-textarea:focus {
        transition: none;
    }
}

/* Save button "saving" state */
button[type="submit"].saving {
    opacity: 0.8;
    pointer-events: none;
    animation: save-in-progress 1s ease-in-out infinite;
}

@keyframes save-in-progress {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
    }
    50% {
        box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
    }
}

@media (prefers-reduced-motion: reduce) {
    button[type="submit"].saving {
        animation: none;
        box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
    }
}

/* ========================================================================
 * Navigation Loading State - Smooth dimming during page transitions
 * Prevents jarring instant opacity snap when isLoading becomes true.
 * The nav sits in peripheral vision; abrupt changes feel glitchy.
 * ======================================================================== */

nav[aria-label="Main navigation"] {
    transition: opacity var(--transition-fast) var(--easing-smooth);
}

/* ========================================================================
 * Footer Loading State - Subtle peripheral dimming during transitions
 * The footer sits at the bottom of the viewport during page navigation.
 * When content above dims and animates, a static footer feels "anchored"
 * and disconnected from the unified page transition motion.
 *
 * Solution: Apply a subtle opacity reduction to the footer when the
 * content area enters loading state. The dim is lighter than content
 * (0.7 vs 0.4) because peripheral elements need less emphasis change.
 * This creates cohesive "whole page transitioning" perception.
 *
 * Triggered via JS: footer gets 'footer-loading' class alongside
 * #content.loading-dimmed, removed on htmx:afterOnLoad.
 * ======================================================================== */

footer[role="contentinfo"] {
    transition: opacity var(--transition-fast) var(--easing-smooth);
}

footer[role="contentinfo"].footer-loading {
    opacity: 0.7;
    pointer-events: none;
}

/* ========================================================================
 * Start Meeting Button - Click-to-load visual bridge
 * Creates perceptual continuity between button press and loading bar
 * The upward pulse draws the eye toward the loading bar at the top
 * ======================================================================== */

@keyframes start-meeting-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(168, 85, 247, 0.6),
                    0 4px 12px rgba(168, 85, 247, 0.3);
        transform: scale(1);
    }
    30% {
        box-shadow: 0 0 0 8px rgba(168, 85, 247, 0),
                    0 -8px 20px rgba(168, 85, 247, 0.4);
        transform: scale(0.98);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(168, 85, 247, 0),
                    0 0 0 rgba(168, 85, 247, 0);
        transform: scale(1);
    }
}

/* Applied when isStarting becomes true */
button[hx-post="/meetings"]:disabled {
    animation: start-meeting-pulse 0.4s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    button[hx-post="/meetings"]:disabled {
        animation: none;
    }
}

/* Instant press feedback - sub-frame response to click */
button[hx-post="/meetings"]:active:not(:disabled) {
    transform: scale(0.97);
    transition: transform var(--transition-instant) var(--easing-smooth);
}

/* ========================================================================
 * Mobile Touch Optimization - Eliminate 300ms tap delay
 * touch-action: manipulation tells the browser this element only needs
 * standard touch gestures (pan, pinch-zoom) - no double-tap-to-zoom.
 * This guarantees instant touch response on all mobile browsers/devices,
 * even on older iOS Safari or Android WebView where the viewport meta
 * alone may not fully eliminate the legacy 300ms tap delay.
 *
 * Combined with the :active scale feedback above, mobile users get
 * immediate tactile confirmation that their tap was registered.
 * ======================================================================== */
button[hx-post="/meetings"] {
    touch-action: manipulation;
    /* Prevent text selection on long-press (which can interfere with tap) */
    -webkit-user-select: none;
    user-select: none;
    /* Disable iOS Safari's default touch callout menu */
    -webkit-touch-callout: none;
}

/* ========================================================================
 * Form Launch Animation - Unified lift-off when starting meeting
 * Creates single continuous motion from form to loading state
 * ======================================================================== */

@keyframes form-launch {
    0% {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
    100% {
        opacity: 0.5;
        transform: scale(0.99) translateY(-4px);
    }
}

/* Target the meeting form wrapper when isStarting triggers opacity-50 */
.bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 {
    animation: form-launch var(--transition-slow) var(--easing-smooth) forwards;
}

@media (prefers-reduced-motion: reduce) {
    .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 {
        animation: none;
    }
}

/* ========================================================================
 * Content Loading State - Immediate visual feedback on navigation start
 * Coordinates with form-launch: dims content synchronously (not waiting
 * for skeleton delay) to eliminate the 20ms gap between button press
 * and visual feedback. The skeleton appears later (320ms) for polish,
 * but the content dims immediately for perceived responsiveness.
 * ======================================================================== */

#content.loading-dimmed {
    opacity: 0.4;
    transition: opacity var(--transition-fast) var(--easing-smooth);
    pointer-events: none;
}

/* Ensure content returns to full opacity smoothly after load
 * IMPORTANT: Exclude content-entering to prevent competing with reveal animation.
 * When content-entering is active, the animation property solely owns opacity;
 * a parallel transition creates micro-flicker from conflicting interpolators. */
#content:not(.loading-dimmed):not(.content-entering) {
    transition: opacity var(--transition-fast) var(--easing-smooth);
}

/* ========================================================================
 * Scroll Anchoring Control During Transitions
 * Iteration 38: Prevents browser scroll anchoring from interfering with
 * programmatic scrollTo during the Start Meeting transition.
 *
 * Problem: When content dims and skeleton appears, browser's native scroll
 * anchoring tries to maintain scroll position relative to visible elements.
 * This conflicts with our explicit scrollTo({ top: 0 }) call, causing
 * competing scroll behaviors that manifest as flicker/jitter.
 *
 * Solution: Disable scroll anchoring on the content container during
 * loading transitions. This allows our smooth scroll to complete
 * uncontested, then re-enables anchoring for normal page behavior.
 *
 * Browser support: overflow-anchor is supported in Chrome 56+, Firefox 66+,
 * Edge 79+. Safari lacks support but safely ignores the property.
 * ======================================================================== */

#content.loading-dimmed {
    overflow-anchor: none;
}

/* Re-enable scroll anchoring after transition completes for normal UX */
#content:not(.loading-dimmed) {
    overflow-anchor: auto;
}

/* ========================================================================
 * Focus Persistence During Transition - Accessibility Enhancement
 * When keyboard users trigger Start Meeting, the button becomes disabled
 * and loses its focus ring. This leaves a momentary gap (up to 320ms)
 * where there's no visible focus indicator during the transition.
 *
 * Solution: Apply a subtle focus indicator to the form wrapper when
 * it enters the loading/launching state. This maintains continuous
 * visual feedback for keyboard users and assistive technology.
 *
 * The ring uses the same purple accent as the button for visual continuity.
 * ======================================================================== */

.bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50:focus-within,
.bg-primaryDark-800.shadow-lg.rounded-lg[class*="opacity-50"] {
    outline: 2px solid rgba(168, 85, 247, 0.4);
    outline-offset: 2px;
    transition: outline var(--transition-fast) var(--easing-smooth),
                opacity var(--transition-slow) var(--easing-smooth),
                transform var(--transition-slow) var(--easing-smooth);
}

/* Remove outline when not in loading state to avoid interfering with normal focus */
.bg-primaryDark-800.shadow-lg.rounded-lg:not(.opacity-50):not([class*="opacity-50"]) {
    outline: none;
}

@media (prefers-reduced-motion: reduce) {
    .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50:focus-within,
    .bg-primaryDark-800.shadow-lg.rounded-lg[class*="opacity-50"] {
        transition: none;
    }
}

/* ========================================================================
 * Button Text Crossfade - Smooth transition between button states
 * Creates visual continuity when "Start Meeting" becomes "Starting..."
 * The overlap creates a morphing effect rather than an abrupt text swap
 * ======================================================================== */

.btn-text-crossfade {
    transition: opacity var(--transition-fast) var(--easing-smooth), transform var(--transition-fast) var(--easing-smooth);
}

/* Entering state - text fades in and settles into position */
.btn-text-enter {
    opacity: 1;
    transform: translateY(0);
}

/* Exiting state - text fades out with subtle upward drift */
.btn-text-exit {
    opacity: 0;
    transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
    .btn-text-crossfade {
        transition: opacity var(--transition-fast) var(--easing-smooth);
        transform: none !important;
    }
    .btn-text-exit {
        transform: none;
    }
}

/* ========================================================================
 * Button Spinner Entrance - Scale + fade for energy continuity
 * The spinner "blooms" from the button press, connecting the click pulse
 * to the loading state. Creates perception of energy transfer.
 * ======================================================================== */

@keyframes btn-spinner-enter {
    0% {
        opacity: 0;
        transform: scale(0.7);
    }
    60% {
        opacity: 1;
        transform: scale(1.05);
    }
    100% {
        opacity: 1;
        transform: scale(1);
    }
}

/* Override Alpine's x-transition with coordinated entrance */
button[hx-post="/meetings"] svg.animate-spin {
    animation: btn-spinner-enter var(--transition-fast) var(--easing-smooth) forwards, spin 1s linear var(--transition-fast) infinite;
}

@media (prefers-reduced-motion: reduce) {
    button[hx-post="/meetings"] svg.animate-spin {
        animation: none;
        opacity: 1;
        transform: scale(1);
    }
}

/* ========================================================================
 * Meeting Page Entrance - Coordinated reveal for chat interface
 * Creates visual continuity from skeleton/loading to the live chat view
 *
 * IMPORTANT: The #content parent already animates opacity via page-enter-active.
 * If we also animate opacity here, we get a "double opacity" flicker where
 * (parent opacity 0->1) * (child opacity 0->1) = very dark initial frame.
 * Solution: Only animate transform here, let parent handle opacity reveal.
 * ======================================================================== */

@keyframes chat-container-enter {
    from {
        transform: scale(0.995) translateY(4px);
    }
    to {
        transform: scale(1) translateY(0);
    }
}

/* Applied to the main meeting chat wrapper on page load */
#chat-container {
    animation: chat-container-enter var(--transition-fast) var(--easing-decel) forwards;
}

/* Staggered entrance for sidebar (meeting mode) - appears slightly after chat */
aside[aria-label="Meeting participants"] {
    animation: chat-container-enter var(--transition-fast) var(--easing-decel) var(--transition-instant) forwards;
}

@media (prefers-reduced-motion: reduce) {
    #chat-container,
    aside[aria-label="Meeting participants"] {
        animation: none;
        opacity: 1;
        transform: none;
    }
}

/* ========================================================================
 * Error Recovery Animation - Graceful return from failed transitions
 * When an HTMX request fails (network error, server error, timeout),
 * the UI needs to return to an interactive state. Without this, the
 * loading-dimmed content and disabled buttons snap back instantly,
 * creating a jarring "break" in the otherwise smooth experience.
 *
 * This animation provides:
 * 1. Visual acknowledgment that something happened (subtle shake)
 * 2. Smooth return to full opacity (gentle undim)
 * 3. Clear "ready to retry" signal
 *
 * Applied via JS in htmx:afterRequest when xhr.status indicates failure.
 * ======================================================================== */

@keyframes error-recovery {
    0% {
        opacity: 0.4;
        transform: translateX(0);
    }
    15% {
        opacity: 0.5;
        transform: translateX(-3px);
    }
    30% {
        opacity: 0.6;
        transform: translateX(3px);
    }
    45% {
        opacity: 0.75;
        transform: translateX(-2px);
    }
    60% {
        opacity: 0.85;
        transform: translateX(1px);
    }
    100% {
        opacity: 1;
        transform: translateX(0);
    }
}

#content.error-recovering {
    animation: error-recovery 0.5s var(--easing-smooth) forwards;
}

/* Form wrapper recovery - undoes the form-launch animation smoothly */
@keyframes form-recovery {
    0% {
        opacity: 0.5;
        transform: scale(0.99) translateY(-4px);
    }
    100% {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
}

.form-error-recovering {
    animation: form-recovery 0.4s var(--easing-smooth) forwards !important;
}

/* Button recovery - re-enables with subtle pulse to signal ready state */
@keyframes button-recovery {
    0% {
        opacity: 0.75;
        transform: scale(0.98);
    }
    50% {
        opacity: 1;
        transform: scale(1.02);
        box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.2);
    }
    100% {
        opacity: 1;
        transform: scale(1);
        box-shadow: none;
    }
}

button.error-recovering {
    animation: button-recovery 0.4s var(--easing-smooth) forwards;
}

@media (prefers-reduced-motion: reduce) {
    #content.error-recovering {
        animation: none;
        opacity: 1;
        transform: none;
    }

    .form-error-recovering {
        animation: none !important;
        opacity: 1;
        transform: none;
    }

    button.error-recovering {
        animation: none;
        opacity: 1;
        transform: none;
    }
}

/* ========================================================================
 * Print Styles - Disable animations and GPU hints for clean print output
 * ========================================================================
 * When users print meeting transcripts or agent configurations, animations
 * running during print can cause:
 *   - Blank pages (animation mid-frame captured)
 *   - Visual artifacts from GPU-promoted layers
 *   - Elements hidden mid-transition appearing invisible
 *   - Wasted CPU/GPU resources during print spooling
 *
 * This media query ensures:
 *   1. All animations are disabled (instant state, no motion)
 *   2. GPU hints removed (will-change, contain can confuse print renderer)
 *   3. Loading UI hidden (skeleton, loading bar irrelevant on paper)
 *   4. Full opacity on all content (no dimmed states)
 *   5. Transitions disabled (prevents state capture mid-transition)
 * ======================================================================== */
@media print {
    /* Disable all animations globally */
    *, *::before, *::after {
        animation: none !important;
        transition: none !important;
    }

    /* Remove GPU compositing hints that can interfere with print rendering */
    #content,
    #content.will-animate {
        will-change: auto !important;
        contain: none !important;
        isolation: auto !important;
        transform: none !important;
        -webkit-transform: none !important;
    }

    /* Ensure content is fully visible, not in loading/dimmed state */
    #content,
    #content.loading-dimmed,
    #content.htmx-swapping,
    #content.htmx-settling {
        opacity: 1 !important;
        pointer-events: auto !important;
    }

    /* Hide loading UI elements - irrelevant on paper */
    #loading-bar,
    #content-loading-skeleton,
    .btn-spinner,
    .nav-tab-spinner,
    .htmx-indicator,
    .spinner,
    .spinner-svg {
        display: none !important;
    }

    /* Ensure footer is visible (not in loading-dimmed state) */
    footer[role="contentinfo"],
    footer.footer-loading {
        opacity: 1 !important;
    }

    /* Reset button states - show text, not loading state */
    .btn-loading .btn-text {
        display: inline !important;
    }

    /* Remove hover/active transforms that could affect print layout */
    button,
    .applicant-card,
    img {
        transform: none !important;
    }

    /* Ensure skeleton shimmer is not visible */
    .skeleton {
        background: #e5e7eb !important;
        animation: none !important;
    }
}

/* ========================================================================
 * Windows High Contrast Mode / Forced Colors - Accessibility
 * Iteration 34: Ensures loading indicators remain visible when users
 * enable Windows High Contrast Mode or other forced-colors environments.
 *
 * Problem: Custom colors (indigo loading bar, green tool indicators,
 * gradient skeleton shimmer) are overridden to system colors, making
 * loading states invisible to users who depend on high contrast.
 *
 * Solution: Use CSS system color keywords (CanvasText, Highlight, etc.)
 * and replace gradient-based animations with border-based indicators
 * that survive forced-colors mode.
 *
 * System color keywords used:
 *   - Highlight: System selection/accent color (visible, high contrast)
 *   - CanvasText: Text color on Canvas background
 *   - ButtonText: Text color for buttons
 *   - LinkText: Hyperlink color
 * ======================================================================== */
@media (forced-colors: active) {
    /* Loading bar - use system Highlight color for visibility */
    #loading-bar {
        background: Highlight !important;
        /* Border provides visibility when background is clipped */
        border: 2px solid CanvasText;
        forced-color-adjust: none;
    }

    /* Loading bar glow effects become solid borders in forced colors */
    #loading-bar.loading-active,
    #loading-bar.loading-complete {
        box-shadow: none !important;
        /* Thicker border pulses instead of glow */
        border-width: 3px;
    }

    /* Skeleton loading - replace gradient shimmer with pulsing border */
    .skeleton {
        background: transparent !important;
        border: 2px solid CanvasText;
        /* Simple opacity pulse instead of gradient sweep */
        animation: skeleton-pulse-hc 1.5s ease-in-out infinite !important;
    }

    @keyframes skeleton-pulse-hc {
        0%, 100% { opacity: 0.4; }
        50% { opacity: 1; }
    }

    /* Button spinners - ensure visibility with system colors */
    .spinner,
    .spinner-svg,
    .btn-spinner svg,
    .nav-tab-spinner svg,
    .tool_called_spinner {
        border-color: CanvasText !important;
        border-top-color: transparent !important;
        stroke: CanvasText !important;
        forced-color-adjust: none;
    }

    /* Start Meeting button pulse - use border instead of box-shadow */
    button[hx-post="/meetings"]:active {
        outline: 3px solid Highlight !important;
        outline-offset: 2px;
    }

    /* Tool call status indicators - borders instead of background colors */
    .tool_called {
        border-left: 4px solid CanvasText !important;
        background: transparent !important;
    }

    .tool_called--pending {
        border-left-color: Highlight !important;
    }

    .tool_called--error {
        border-left-color: LinkText !important;
    }

    .tool_called_header {
        background: transparent !important;
        border-bottom: 1px solid CanvasText !important;
    }

    .tool_called_name {
        color: CanvasText !important;
    }

    /* Content dimming - use reduced opacity only, no color changes */
    #content.loading-dimmed {
        opacity: 0.5 !important;
    }

    /* Footer loading state */
    footer.footer-loading {
        opacity: 0.5 !important;
    }

    /* Focus indicators - ensure keyboard focus is always visible */
    :focus-visible {
        outline: 3px solid Highlight !important;
        outline-offset: 2px !important;
    }

    /* Heartbeat dots - solid borders instead of colored backgrounds */
    .tool_called_heartbeat_dot {
        background: CanvasText !important;
        border: 1px solid CanvasText;
    }
}

/* ========================================================================
 * High Contrast Preference - Enhanced visibility for users who prefer
 * more contrast but are not in forced-colors mode.
 *
 * This is a softer enhancement that increases visibility without
 * completely overriding the design palette.
 * ======================================================================== */
@media (prefers-contrast: more) {
    /* Increase loading bar visibility */
    #loading-bar {
        height: 4px;
        box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3);
    }

    #loading-bar.loading-active {
        box-shadow: 0 0 8px 2px rgba(99, 102, 241, 0.8),
                    0 0 0 1px rgba(0, 0, 0, 0.3);
    }

    /* Skeleton loading - higher contrast shimmer */
    .skeleton {
        background: linear-gradient(
            90deg,
            rgba(255, 255, 255, 0.15) 0%,
            rgba(255, 255, 255, 0.4) 50%,
            rgba(255, 255, 255, 0.15) 100%
        );
    }

    /* Stronger dimming for loading states */
    #content.loading-dimmed {
        opacity: 0.3;
    }

    /* Higher contrast focus rings */
    :focus-visible {
        outline-width: 3px;
    }

    /* Tool call borders more prominent */
    .tool_called {
        border-left-width: 4px;
    }

    /* Button active state more visible */
    button:active {
        transform: scale(0.97);
        box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
    }
}

/* ========================================================================
 * Color Scheme Transition Handling - Smooth adaptation during theme changes
 * Iteration 36: Prevents flicker when OS switches between light/dark mode
 * while animations are in progress.
 *
 * Problem: When users have "auto" color scheme (matching system preference)
 * and the OS transitions at dawn/dusk or via manual toggle, browsers trigger
 * a forced style recalculation. If this occurs during the Start Meeting
 * animation sequence (loading-dimmed, form-launch, skeleton, etc.), GPU-
 * composited layers may be interrupted, causing micro-flicker or stuttering.
 *
 * Solution: Define explicit color-scheme property and add transition smoothing
 * for color-related properties during scheme changes. The browser can then
 * batch color updates more efficiently without disrupting transform/opacity
 * animations on separate compositor layers.
 *
 * Key techniques:
 *   1. Explicit color-scheme declaration enables browser optimization for
 *      native controls (scrollbars, form inputs) during transitions
 *   2. Transition on color/background-color properties allows gradual
 *      adaptation rather than instant repaint
 *   3. GPU-promoted elements (will-animate class) maintain their compositor
 *      layer through color scheme changes, preventing layer thrashing
 * ======================================================================== */

/* Declare supported color schemes - allows browser to optimize native controls */
:root {
    color-scheme: dark light;
}

/* Smooth color transitions during scheme changes for key UI elements
 * These elements may have color-dependent styles that change with scheme */
#loading-bar,
.skeleton,
#content-loading-skeleton,
footer[role="contentinfo"] {
    transition: background-color 0.3s ease-out,
                border-color 0.3s ease-out,
                box-shadow 0.3s ease-out;
}

/* Ensure transform/opacity animations on GPU layer are not disrupted by
 * color scheme changes - the will-animate class already promotes to compositor,
 * this ensures color changes don't force a layer rebuild */
#content.will-animate {
    /* Isolate color changes from transform animations */
    transition: opacity var(--transition-medium) var(--easing-smooth),
                background-color 0.3s ease-out;
}

/* During active loading, prioritize animation stability over color smoothing
 * The loading state has specific opacity values that should not be affected
 * by color scheme transitions mid-flight */
#content.loading-dimmed {
    /* Color scheme changes during loading should not affect dimming opacity */
    transition: opacity var(--transition-fast) var(--easing-smooth),
                background-color 0s; /* Instant color change, preserve opacity animation */
}

/* Loading bar maintains its indigo/green colors regardless of scheme
 * but glow effects should adapt smoothly if scheme changes mid-progress */
#loading-bar.loading-active {
    transition: width 3s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.15s ease-out,
                box-shadow 0.3s ease-out;
}

/* Skeleton shimmer should adapt colors smoothly during scheme transition
 * without interrupting the sweep animation */
@keyframes skeleton-shimmer-scheme-safe {
    0% {
        background-position: -200% 0;
    }
    100% {
        background-position: 200% 0;
    }
}

/* Form wrapper during launch should maintain transform animation integrity
 * even if color scheme changes mid-animation */
.bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 {
    /* Separate transform/opacity from color transitions */
    transition: transform var(--transition-slow) var(--easing-smooth),
                opacity var(--transition-slow) var(--easing-smooth),
                background-color 0.3s ease-out,
                box-shadow 0.3s ease-out;
}

/* Respect reduced motion - disable smooth color transitions too */
@media (prefers-reduced-motion: reduce) {
    #loading-bar,
    .skeleton,
    #content-loading-skeleton,
    footer[role="contentinfo"],
    #content.will-animate,
    .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 {
        transition: none;
    }
}

/* ========================================================================
 * Network-Aware Loading - Adaptive feedback for slow connections
 * When Network Information API detects slow connection (2G/3G/saveData),
 * JS applies 'network-slow' class to body. This enables immediate skeleton
 * display and enhanced visual feedback to reduce perceived wait time.
 *
 * Browsers supporting Network Information API: Chrome, Edge, Opera, Android
 * Fallback: Safari, Firefox desktop get default 200ms delay behavior
 * ======================================================================== */

body.network-slow #content-loading-skeleton {
    /* On slow networks, skeleton fades in faster for immediate feedback */
    transition: opacity 0.1s ease-out;
}

body.network-slow #content.loading-dimmed {
    /* Slightly stronger dimming on slow networks signals "working hard" */
    opacity: 0.35;
}

/* Skeleton pulse animation - active waiting indicator for slow connections
 * Subtle opacity pulse creates perception of "actively working" which
 * reduces perceived wait time compared to static dimmed content */
@keyframes skeleton-network-pulse {
    0%, 100% {
        opacity: 1;
    }
    50% {
        opacity: 0.85;
    }
}

body.network-slow #content-loading-skeleton:not(.hidden) {
    animation: skeleton-network-pulse 2s ease-in-out infinite;
}

/* Loading bar on slow networks - slower, steadier progression
 * Prevents the bar from racing ahead of actual network progress */
body.network-slow #loading-bar.loading-active {
    transition: width 5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.15s ease-out;
}

@media (prefers-reduced-motion: reduce) {
    body.network-slow #content-loading-skeleton:not(.hidden) {
        animation: none;
    }
}

/* ========================================================================
 * Token Counter Progress Animation
 * Sliding progress bar for token counter to show active processing.
 * Creates sense of forward momentum during AI inference.
 * ======================================================================== */
@keyframes token-progress {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(400%); }
}

.animate-token-progress {
    animation: token-progress 1.2s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .animate-token-progress {
        animation: none;
        transform: translateX(0);
    }
}

/* ========================================================================
 * Device Orientation Change Handling - Animation Stability
 * Iteration 39: Prevents flicker when device rotates during transitions.
 *
 * Problem: When users rotate their device (portrait <-> landscape) during
 * the Start Meeting animation sequence, the browser performs a full layout
 * recalculation. GPU-composited layers (will-animate class) can be
 * invalidated, causing micro-flicker as compositor layers are rebuilt.
 * Additionally, viewport resize triggers reflows that propagate to
 * animated elements, desynchronizing opacity/transform animations.
 *
 * Solution: Apply layout containment during orientation transitions to
 * isolate animated elements from viewport resize reflows. The
 * `contain: layout paint` property creates a boundary that prevents
 * ancestor reflows from affecting the contained element's rendering.
 *
 * JS in base.html listens for orientationchange event and applies
 * 'orientation-transitioning' class briefly during the resize.
 * ======================================================================== */

/* During orientation change, strengthen containment on animated elements
 * to prevent viewport resize from invalidating GPU layers */
body.orientation-transitioning #content.will-animate {
    /* Full containment during orientation change - isolates from viewport reflow */
    contain: strict;
    /* Maintain compositor layer through orientation change */
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}

/* Loading skeleton should maintain position during orientation change */
body.orientation-transitioning #content-loading-skeleton {
    contain: layout paint;
    /* Prevent size recalculation flash */
    min-height: 200px;
}

/* Loading bar should not flicker during orientation change */
body.orientation-transitioning #loading-bar {
    contain: layout;
    /* Keep bar visible and stable */
    position: fixed;
    top: 0;
    left: 0;
    right: auto;
    width: var(--loading-bar-width, 0%);
}

/* Form wrapper during launch should survive orientation change gracefully */
body.orientation-transitioning .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 {
    contain: layout paint;
    /* Pause transform animation during orientation change to prevent jitter */
    animation-play-state: paused;
}

/* Resume animations after orientation change completes */
body:not(.orientation-transitioning) .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 {
    animation-play-state: running;
}

/* Skeleton shimmer should pause during orientation to prevent tearing */
body.orientation-transitioning .skeleton {
    animation-play-state: paused;
}

/* Footer loading state should remain stable */
body.orientation-transitioning footer.footer-loading {
    contain: layout;
}

@media (prefers-reduced-motion: reduce) {
    /* Users with reduced motion already have animations disabled,
     * but ensure containment still applies for layout stability */
    body.orientation-transitioning #content,
    body.orientation-transitioning #content-loading-skeleton {
        contain: layout;
    }
}

/* ========================================================================
 * Low-End Device / Memory Pressure Safeguards - Final Polish
 * Iteration 40: Ensures smooth transitions even on constrained devices.
 *
 * Problem: On low-end devices (low RAM, weak GPU) or when the browser is
 * under memory pressure (many tabs, background apps), the overlapping
 * animations during Start Meeting transition can cause frame drops:
 *   - Button pulse creates GPU layer
 *   - Form launch creates GPU layer
 *   - Content dimming affects large area
 *   - Skeleton shimmer requires continuous repainting
 *   - Loading bar pulse adds another animated layer
 *
 * When memory is constrained, the browser may garbage collect mid-animation
 * or fail to maintain all compositor layers, causing micro-stutters that
 * manifest as the "flicker" users report on lower-end hardware.
 *
 * Solutions implemented:
 *   1. content-visibility: auto on skeleton - lets browser skip rendering
 *      off-screen skeleton elements, reducing memory footprint
 *   2. contain-intrinsic-size hints - prevents layout thrashing when
 *      content-visibility toggles rendering on/off
 *   3. Animation simplification layer - when compositor layers are stressed,
 *      reduce concurrent animations to prioritize the most visible ones
 *   4. will-change budgeting - explicitly scope GPU layer hints to active
 *      transition period only (already done in JS, reinforced here)
 *
 * Browser support:
 *   - content-visibility: Chrome 85+, Edge 85+, Opera 71+
 *   - Safari/Firefox safely ignore (progressive enhancement)
 * ======================================================================== */

/* Skeleton optimization - allow browser to skip rendering when off-screen
 * During the transition, skeleton may extend below viewport fold; no need
 * to render those elements until they scroll into view */
#content-loading-skeleton {
    content-visibility: auto;
    contain-intrinsic-size: auto 400px;
}

/* Individual skeleton items - help browser estimate size for layout */
#content-loading-skeleton .bg-primaryDark-800 {
    contain-intrinsic-size: auto 120px;
}

/* Animation budget control - limit concurrent expensive animations
 * When form is launching (opacity-50), deprioritize skeleton shimmer
 * to reduce GPU layer count. The form animation is more important
 * visually as it is the direct result of the user action. */
.bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50 ~ #content-loading-skeleton .skeleton,
.bg-primaryDark-800.shadow-lg.rounded-lg[class*="opacity-50"] ~ #content-loading-skeleton .skeleton {
    /* Pause shimmer during form launch to reduce layer count */
    animation-play-state: paused;
    /* Simpler static background instead of animated gradient */
    background: rgba(255, 255, 255, 0.05);
}

/* Restore shimmer after form launch completes (form returns to full opacity) */
.bg-primaryDark-800.shadow-lg.rounded-lg:not(.opacity-50):not([class*="opacity-50"]) ~ #content-loading-skeleton .skeleton {
    animation-play-state: running;
}

/* Loading bar memory optimization - use simpler animation when multiple
 * transitions are active. The pulsing glow is beautiful but expensive;
 * during the critical 0-200ms window, prioritize smoothness over flourish */
#content.loading-dimmed ~ #loading-bar.loading-active,
#content.will-animate ~ #loading-bar.loading-active {
    /* Reduce box-shadow complexity during heavy transition period */
    animation: none;
    /* Static subtle glow instead of pulsing - still visible, less GPU work */
    box-shadow: 0 0 8px 1px rgba(99, 102, 241, 0.5);
}

/* Re-enable pulse after content transition settles (will-animate removed) */
#content:not(.will-animate):not(.loading-dimmed) ~ #loading-bar.loading-active {
    animation: loading-bar-pulse 2s ease-in-out infinite;
}

/* Compositor layer budget hint - explicit will-change removal strategy
 * Elements should only have will-change during their active animation.
 * This reinforces the JS-based class toggling with CSS fallback. */
#content:not(.will-animate):not(.loading-dimmed):not(.page-enter-active):not(.content-entering) {
    will-change: auto;
    contain: none;
}

/* Skeleton should not maintain GPU layer when hidden */
#content-loading-skeleton.hidden {
    will-change: auto;
    contain: none;
    content-visibility: hidden;
}

/* Form wrapper - release GPU resources after animation completes */
.bg-primaryDark-800.shadow-lg.rounded-lg:not(.opacity-50):not([class*="opacity-50"]):not(.form-error-recovering) {
    will-change: auto;
}

/* Final defensive measure: if somehow all animations fire simultaneously
 * (race condition, rapid clicks), ensure at least transform animations
 * complete without competing for compositor bandwidth */
@supports (animation-composition: replace) {
    /* Modern browsers: ensure animations replace rather than accumulate
     * Prevents "animation stacking" that can occur with rapid interactions */
    button[hx-post="/meetings"]:disabled,
    .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50,
    #content.page-enter-active {
        animation-composition: replace;
    }
}

/* Ultra-low-end fallback: for browsers that struggle even with optimizations,
 * this query detects "update: slow" media feature (devices with slow refresh)
 * and simplifies to the bare minimum transitions */
@media (update: slow) {
    /* Instant transitions on e-ink or very slow displays */
    #content,
    #content.loading-dimmed,
    #content-loading-skeleton,
    .bg-primaryDark-800.shadow-lg.rounded-lg.opacity-50,
    button[hx-post="/meetings"] {
        animation: none !important;
        transition-duration: 0.05s !important;
    }

    /* Keep skeleton static - no shimmer */
    .skeleton {
        animation: none !important;
        background: rgba(255, 255, 255, 0.05) !important;
    }

    /* Minimal loading bar - just width, no glow */
    #loading-bar {
        animation: none !important;
        box-shadow: none !important;
        transition: width 0.5s linear !important;
    }
}

/* Pipeline box hover lift animations - respect reduced motion preference
 * The hover:-translate-y-0.5 lift effect can trigger motion sickness
 * for vestibular-sensitive users. Disable transform while preserving
 * color/border hover feedback. */
@media (prefers-reduced-motion: reduce) {
    .hover\:-translate-y-0\.5:hover {
        transform: none !important;
    }
}
