/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/* Generated by scripts/build-demo-site.sh: styles/ flattened into one
   stylesheet to avoid a nested @import waterfall. Edit the modules under
   rource-wasm/www/styles/, never this file. */

/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - CSS Module Index
 *
 * This file imports all CSS modules in the correct order.
 * This is the production entry point for all styles.
 *
 * Architecture:
 * - variables.css: Design tokens (colors, spacing, etc.)
 * - reset.css: Normalize and base styles
 * - components/: Reusable UI components
 * - sections/: Page-specific sections
 * - features/: Feature-specific styles
 *
 * Migration Status: COMPLETE
 * All styles have been extracted from the monolithic styles.css into
 * this modular architecture for better maintainability.
 */

/* =============================================================================
   Foundation
   ============================================================================= */

/* ---- styles/variables.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - CSS Custom Properties (Design Tokens)
 *
 * Central location for all design tokens including colors, spacing, and transitions.
 * These variables are used throughout the application for consistent theming.
 */

:root {
    /* Colors - Dark Theme (default) */
    --bg-primary: #0d1117;
    --bg-secondary: #161b22;
    --bg-tertiary: #21262d;
    --bg-canvas: #010409;

    /* Accent Colors
     *
     * `--accent` and `--accent-surface` are deliberately different values.
     * On a dark theme one colour cannot do both jobs: as *text* it must be
     * light enough to clear 4.5:1 against the page (needs relative luminance
     * >= 0.200), and as a *background behind white text* it must be dark
     * enough to clear 4.5:1 against white (needs <= 0.183). Those ranges do
     * not overlap, so the roles are split:
     *
     *   --accent          text, icons, borders, graphical fills
     *   --accent-surface  a background that carries --text-on-accent
     *   --accent-hover    hover background only (never used as text)
     */
    --accent: #e94560;                    /* 4.94:1 on bg-primary as text */
    --accent-surface: #d23e56;            /* 4.60:1 with white text */
    --accent-hover: #ba374c;              /* 5.62:1 with white text */
    --accent-light: #ff9a9e;              /* Gradient accent (pink) */
    --accent-secondary: #238636;          /* 4.63:1 with white text */
    --accent-secondary-hover: #1f7730;    /* 5.62:1 with white text */
    --accent-blue: #58a6ff;
    --accent-blue-light: #4d9eff;         /* Timeline scrubbing state */
    --accent-purple: #a855f7;
    --accent-orange: #ff6b35;             /* Uncapped FPS indicator */

    /* Surface variants of the semantic colours.
     *
     * Same role split as --accent above: the values tuned to be readable *as
     * text* on a dark page are far too light to sit *behind* white text. Any
     * rule that paints one of these as a background and relies on
     * --text-on-accent must use the -surface variant.
     *
     * Yellow and orange are the exception — no yellow dark enough for white
     * text is still recognisably yellow — so they pair with --text-on-warning
     * instead, which is the conventional dark-on-amber treatment. */
    --accent-blue-surface: #1f6feb;        /* 4.63:1 with white text */
    --accent-blue-surface-hover: #1a5fd0;  /* 5.53:1 with white text */
    --error-surface: #d1242f;              /* 5.24:1 with white text */
    --warning-surface: #d29922;            /* 7.50:1 with --text-on-warning */
    --accent-orange-surface: #ff6b35;      /* 6.67:1 with --text-on-warning */
    --text-on-warning: #0d1117;            /* dark text for amber surfaces */
    --accent-gold: #d4a72c;               /* Special highlight (GitHub link) */
    --accent-gold-hover: #f0c142;         /* Special highlight hover */

    /* Text Colors - All meet WCAG AA 4.5:1 contrast against bg-primary */
    --text-primary: #f0f6fc;              /* ~15.5:1 contrast */
    --text-secondary: #9ca3ab;            /* ~5.7:1 contrast (was #8b949e) */
    --text-interactive: #c9d1d9;          /* ~10.3:1 contrast - for tabs, chips, nav items */
    --text-muted: #8b949e;                /* ~4.86:1 contrast (was #6e7681 - failed WCAG) */
    --text-on-accent: #ffffff;            /* White text on accent backgrounds */

    /* Border Colors */
    --border: #30363d;
    --border-light: #484f58;

    /* Semantic Colors */
    --success: #3fb950;
    --error: #f85149;
    --warning: #d29922;

    /* Shadows & Overlays */
    --shadow: rgba(0, 0, 0, 0.4);
    --shadow-light: rgba(0, 0, 0, 0.1);   /* Subtle elevation on hover */
    --backdrop: rgba(0, 0, 0, 0.4);       /* Modal/overlay backdrop */
    --backdrop-blur: rgba(0, 0, 0, 0.85); /* Stronger backdrop for modals */
    --focus-ring: rgba(88, 166, 255, 0.2); /* Focus ring glow (accent-blue at 20%) */

    /* Spacing Scale */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 0.75rem;
    --spacing-lg: 1rem;
    --spacing-xl: 1.5rem;
    --spacing-2xl: 2rem;
    --spacing-3xl: 3rem;

    /* Border Radius */
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 8px;
    --radius-xl: 12px;
    --radius-full: 9999px;

    /* Transitions */
    --transition-fast: 0.15s;
    --transition-normal: 0.2s;
    --transition-slow: 0.3s;

    /* Typography */
    --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
    --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
    --font-size-xs: 0.75rem;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-size-xl: 1.25rem;
    --font-size-2xl: 1.5rem;
    --line-height: 1.5;

    /* Z-index Scale (organized by layer)
     * ─────────────────────────────────
     * Base layer:          1
     * Canvas overlays:     50-60
     * Dropdowns/headers:   100
     * Sidebars/drawers:    140-151
     * Sticky elements:     200-250
     * Modals/sheets:       299-300
     * Popovers:            400
     * Overlays:            500-550
     * Toasts:              600
     * Speed select:        1001
     * Fullscreen:          9999-10002
     */
    --z-base: 1;
    --z-canvas-overlays: 50;      /* Legend, stats overlays on canvas */
    --z-canvas-perf: 60;          /* Performance overlay (above other overlays) */
    --z-dropdown: 100;
    --z-sidebar-overlay: 140;     /* Sidebar backdrop (tablet breakpoint) */
    --z-sidebar-drawer: 150;      /* Slide-out sidebar (tablet breakpoint) */
    --z-sidebar-scroll: 151;      /* Scroll indicator in sidebar */
    --z-sticky: 200;
    --z-modal-backdrop: 299;      /* Modal/sheet backdrop */
    --z-modal: 300;               /* Modal dialogs, bottom sheets */
    --z-fab: 350;                 /* Floating action buttons (above modal for mobile UX) */
    --z-popover: 400;
    --z-overlay: 500;             /* Full-screen overlays (help, etc.) */
    --z-gesture: 550;             /* Gesture indicators */
    --z-toast: 600;
    --z-onboarding: 600;          /* Onboarding hints (same as toast) */
    --z-speed-select: 1001;       /* Speed dropdown (above toast) */
    --z-fullscreen: 9999;         /* Pseudo-fullscreen container */
    --z-fullscreen-timeline: 10000;  /* Timeline in fullscreen mode */
    --z-fullscreen-exit: 10002;   /* Exit fullscreen button (topmost) */

    /* Sidebar Dimensions */
    --sidebar-width: 380px;
    --sidebar-max-width: 420px;
}


/* ---- styles/reset.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Reset & Base Styles
 *
 * Normalize browser defaults and establish base styles.
 */

/* Box sizing reset */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Document setup */
html, body {
    height: 100%;
    overflow: hidden;
}

body {
    font-family: var(--font-family);
    background: var(--bg-primary);
    color: var(--text-primary);
    line-height: var(--line-height);
    display: flex;
    flex-direction: column;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Focus styles for accessibility (WCAG 2.1 AA) */
:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* Links */
a {
    color: var(--accent-blue);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

/* Skip to content link - accessibility */
.skip-link {
    position: absolute;
    top: -40px;
    left: 0;
    background: var(--accent-surface);
    color: var(--text-on-accent);
    padding: 8px 16px;
    z-index: var(--z-fullscreen);
    text-decoration: none;
    border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
    top: 0;
}

/* Hide elements visually but keep accessible to screen readers */
.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;
}

/* Hidden utility */
.hidden {
    display: none;
}

/* =============================================================================
   Selection Styles
   ============================================================================= */

::selection {
    /* Fallback for browsers without color-mix() support */
    background: rgba(88, 166, 255, 0.3);
    color: var(--text-primary);
}

::-moz-selection {
    /* Fallback for browsers without color-mix() support */
    background: rgba(88, 166, 255, 0.3);
    color: var(--text-primary);
}

/* Modern browsers: use color-mix for theme-aware selection */
@supports (background: color-mix(in srgb, red 50%, blue)) {
    ::selection {
        background: color-mix(in srgb, var(--accent-blue) 30%, transparent);
    }

    ::-moz-selection {
        background: color-mix(in srgb, var(--accent-blue) 30%, transparent);
    }
}

/* =============================================================================
   Smooth Scrolling (respects reduced-motion)
   ============================================================================= */

@media (prefers-reduced-motion: no-preference) {
    html {
        scroll-behavior: smooth;
    }
}

/* =============================================================================
   Print Styles
   ============================================================================= */

@media print {
    /* Hide interactive elements */
    header,
    footer,
    .sidebar-panel,
    .sidebar-toggle,
    .bottom-sheet,
    .bottom-sheet-fab,
    .mobile-toolbar,
    .timeline-container,
    .modal-overlay,
    .help-overlay,
    .toast,
    .skip-link,
    #loading {
        display: none !important;
    }

    /* Reset background for printing */
    body {
        background: white;
        color: black;
    }

    /* Canvas container takes full page */
    .app-container {
        display: block;
    }

    .viz-panel {
        width: 100%;
        height: auto;
    }

    #canvas-container {
        border: 1px solid #ccc;
    }

    /* Ensure links show URLs */
    a[href]::after {
        content: " (" attr(href) ")";
        font-size: 0.8em;
        color: #666;
    }

    /* Page breaks */
    .panel {
        break-inside: avoid;
    }
}

/* =============================================================================
   Components
   ============================================================================= */

/* ---- styles/components/buttons.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Button Component Styles
 *
 * All button variants: primary, secondary, success, outline, and size modifiers.
 * Uses CSS custom properties from variables.css for theming.
 */

/* =============================================================================
   Base Button
   ============================================================================= */

.btn {
    background: var(--accent-surface);
    color: var(--text-on-accent);
    border: none;
    padding: 0.6rem var(--spacing-lg);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    transition: background-color var(--transition-normal),
                border-color var(--transition-normal),
                opacity var(--transition-normal),
                transform var(--transition-normal);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

.btn:hover {
    background: var(--accent-hover);
    text-decoration: none;
}

.btn:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.btn:disabled {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    cursor: not-allowed;
    opacity: 0.7;
}

/* =============================================================================
   Button Variants
   ============================================================================= */

/* Secondary (muted) button */
.btn-secondary {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-primary);
}

.btn-secondary:hover {
    background: var(--border);
    border-color: var(--border-light);
}

.btn-secondary.active {
    background: var(--accent-secondary);
    border-color: var(--accent-secondary);
    color: var(--text-on-accent);
}

.btn-secondary.active:hover {
    background: var(--accent-secondary-hover);
    border-color: var(--accent-secondary-hover);
}

/* Success (green) button */
.btn-success {
    background: var(--accent-secondary);
}

.btn-success:hover {
    background: var(--accent-secondary-hover);
}

/* Outline (ghost) button */
.btn-outline {
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
}

.btn-outline:hover {
    background: var(--accent-surface);
    color: var(--text-on-accent);
}

/* =============================================================================
   Button Sizes
   ============================================================================= */

.btn-sm {
    padding: 0.4rem 0.75rem;
    font-size: 0.8rem;
}

.btn-lg {
    padding: 0.75rem 1.5rem;
    font-size: 1rem;
}

/* =============================================================================
   Icon Button
   ============================================================================= */

.btn-icon {
    padding: 0.5rem;
    /* Touch target: 44px minimum (Apple HIG / WCAG 2.5.5) */
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
}

.btn-icon svg {
    width: 16px;
    height: 16px;
}


/* ---- styles/components/panels.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Panel Component Styles
 *
 * Panel containers with headers, bodies, badges, and collapsible behavior.
 * Used for settings panels, info panels, and grouped content areas.
 */

/* =============================================================================
   Base Panel
   ============================================================================= */

.panel {
    background: var(--bg-secondary);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border);
    overflow: hidden;
    min-width: 0; /* Prevent flex/grid blowout */
}

/* =============================================================================
   Panel Header
   ============================================================================= */

.panel-header {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: var(--bg-tertiary);
    gap: 0.5rem;
}

.panel-header h2,
.panel-header h3 {
    font-size: 0.8rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.panel-header .badge {
    font-size: 0.75rem;
    padding: 0.15rem 0.4rem;
    background: var(--accent-surface);
    color: var(--text-on-accent);
    border-radius: 10px;
    font-weight: 500;
    flex-shrink: 0;
}

/* =============================================================================
   Panel Body
   ============================================================================= */

.panel-body {
    padding: 0.875rem;
    min-width: 0; /* Prevent content overflow */
    box-sizing: border-box;
}

/* =============================================================================
   Collapsible Panel
   ============================================================================= */

.panel.collapsible .panel-header {
    cursor: pointer;
    user-select: none;
    transition: background-color 0.2s;
    width: 100%;
    text-align: left;
    font: inherit;
    border: none;
    border-bottom: 1px solid var(--border);
    color: var(--text-primary);
    /* This header is a real <button>. Padding alone resolved to a 39px tall
       target, under the 44px minimum, and the mobile media query below trims
       the padding further. min-height guarantees the target regardless of
       font-size or padding overrides; the parent is already a centred flex
       row, so the extra height distributes evenly. */
    min-height: 44px;
}

.panel.collapsible .panel-header h2,
.panel.collapsible .panel-header h3 {
    color: var(--text-primary);
}

.panel.collapsible .panel-header:hover {
    background: var(--border);
}

.panel.collapsible .panel-header:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: -2px;
}

.panel.collapsible .panel-toggle {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    transition: transform 0.2s;
}

.panel.collapsible.collapsed .panel-toggle {
    transform: rotate(-90deg);
}

.panel.collapsible.collapsed .panel-body {
    display: none;
}

.panel.collapsible.collapsed .tab-nav,
.panel.collapsible.collapsed .tab-content {
    display: none;
}

/* =============================================================================
   Responsive Adjustments
   ============================================================================= */

@media (max-width: 1400px) {
    .panel-header {
        padding: 0.6rem 0.75rem;
    }

    .panel-body {
        padding: 0.75rem;
    }
}


/* ---- styles/components/toast.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Toast Notification Styles
 *
 * Toast notifications for success/error messages.
 * Positioned at bottom center of viewport with slide-up animation.
 */

/* =============================================================================
   Toast Container
   ============================================================================= */

.toast {
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%) translateY(100px);
    background: var(--bg-secondary);
    border-radius: var(--radius-lg);
    padding: var(--spacing-md) var(--spacing-lg);
    box-shadow: 0 4px 20px var(--shadow);
    z-index: var(--z-toast);
    transition: transform var(--transition-slow) ease, visibility var(--transition-slow);
    max-width: 90%;
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    border: 1px solid var(--border);
    /* Hidden by default - transform alone is insufficient as the close button
       can peek into viewport on some browsers/zoom levels */
    visibility: hidden;
}

/* =============================================================================
   Toast States
   ============================================================================= */

.toast.visible {
    transform: translateX(-50%) translateY(0);
    visibility: visible;
}

.toast.error {
    border-left: 3px solid var(--error);
}

.toast.success {
    border-left: 3px solid var(--success);
}

.toast.warning {
    border-left: 3px solid var(--warning);
}

.toast.info {
    border-left: 3px solid var(--accent-blue);
}

/* =============================================================================
   Toast Content
   ============================================================================= */

.toast-message {
    flex: 1;
    font-size: 0.875rem;
}

.toast-close {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0.25rem;
    font-size: 1.25rem;
    line-height: 1;
    transition: color var(--transition-fast);
}

.toast-close:hover {
    color: var(--text-primary);
}

.toast-close:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* =============================================================================
   Mobile Responsive Adjustments
   =============================================================================

   On mobile, position toast at TOP of screen (iOS notification pattern).
   This avoids overlap with:
   - Timeline controls at bottom
   - Bottom sheet when open
   - Mobile toolbar
   - FAB button
*/

@media (max-width: 768px) {
    .toast {
        /* iOS-style top positioning to avoid all bottom overlaps */
        bottom: auto;
        /* L4 FIX: Position toast to the right of stats panel area
           Stats panel is at top-left (max-width: 200px).
           Move toast to right side of screen to avoid overlap. */
        top: max(12px, calc(env(safe-area-inset-top, 0px) + 8px));
        left: auto;
        right: max(12px, env(safe-area-inset-right, 0px));
        transform: translateX(0) translateY(-100px);
        /* Slide down animation instead of up */
        /* Narrower padding for smaller screens */
        padding: var(--spacing-sm) var(--spacing-md);
        /* Constrain width to avoid overlapping stats on left */
        max-width: min(85%, calc(100vw - 220px));
        /* Smaller font for mobile */
        font-size: 0.8125rem;
        /* Compact border radius for top position */
        border-radius: var(--radius-lg);
        /* Subtle shadow for depth */
        box-shadow: 0 4px 16px var(--shadow), 0 2px 4px rgba(0, 0, 0, 0.2);
    }

    .toast.visible {
        transform: translateX(0) translateY(0);
    }

    .toast-message {
        font-size: 0.8125rem;
        line-height: 1.4;
    }

    .toast-close {
        padding: 0.35rem;
        font-size: 1.1rem;
        /* Touch target: 44px minimum (Apple HIG / WCAG 2.5.5) */
        min-width: 44px;
        min-height: 44px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
}

/* Extra small screens */
@media (max-width: 375px) {
    .toast {
        top: max(10px, calc(env(safe-area-inset-top, 0px) + 6px));
        right: max(8px, env(safe-area-inset-right, 0px));
        padding: var(--spacing-xs) var(--spacing-sm);
        /* Smaller screens: allow more width since stats panel also smaller */
        max-width: min(88%, calc(100vw - 180px));
    }

    .toast-message {
        font-size: 0.75rem;
    }
}

/* Landscape mode: toast positioned closer to top due to reduced height */
@media (max-width: 768px) and (orientation: landscape) {
    .toast {
        top: max(6px, env(safe-area-inset-top, 0px));
        right: max(8px, env(safe-area-inset-right, 0px));
    }
}


/* ---- styles/components/first-run-hint.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - First-Run Hint
 *
 * A non-blocking replacement for the first-visit help modal.
 *
 * The modal it replaces covered the whole viewport with several hundred words
 * about files, users, beams and directories — while the visualization those
 * words describe ran, dimmed and unreadable, behind it. Measured cold-load
 * behaviour: the canvas had content at 2.3s and the modal was still up at 12s,
 * so first contact was a wall of text explaining a thing the visitor was being
 * prevented from seeing.
 *
 * This points at the help button instead. The explanation is one click away
 * for anyone who wants it, and invisible to anyone who does not.
 */

.first-run-hint {
    position: fixed;
    /* Centred over the canvas rather than tucked into a corner: every corner
       already holds something (perf readout, file types, authors, stats), and
       anchoring right put this on top of the sidebar's primary call to action.
       The gap along the top of the canvas is the one place nothing else
       occupies at any viewport width. */
    top: 76px;
    left: 50%;
    z-index: var(--z-popover);

    display: flex;
    align-items: center;
    gap: var(--spacing-sm);

    max-width: min(360px, calc(100vw - 32px));
    padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-sm) var(--spacing-lg);

    background: var(--bg-secondary);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-full);
    box-shadow: 0 8px 24px var(--shadow);
    color: var(--text-primary);
    font-size: var(--font-size-sm);
    line-height: 1.3;

    /* Enter animation; the element is inert until .visible is applied.
       translateX(-50%) is part of the resting position, so it has to be
       carried through both states or the hint jumps sideways as it fades in. */
    opacity: 0;
    transform: translate(-50%, -8px);
    pointer-events: none;
    transition: opacity var(--transition-slow) ease, transform var(--transition-slow) ease;
}

.first-run-hint.visible {
    opacity: 1;
    transform: translate(-50%, 0);
    pointer-events: auto;
}

/* The UA rule is `[hidden] { display: none }`, but `display: flex` above is an
 * author rule and outranks it. Without this the hint is laid out even when the
 * attribute says it is hidden — the exact defect that made every toast in the
 * app invisible (F1). */
.first-run-hint[hidden] {
    display: none;
}

.first-run-hint-text {
    flex: 1 1 auto;
    min-width: 0;
}

.first-run-hint-open {
    flex: none;
    min-height: 44px;
    padding: 0 var(--spacing-lg);
    border: none;
    border-radius: var(--radius-full);
    background: var(--accent-surface);
    color: var(--text-on-accent);
    font-size: var(--font-size-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background var(--transition-fast);
}

.first-run-hint-open:hover {
    background: var(--accent-hover);
}

.first-run-hint-dismiss {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    transition: color var(--transition-fast), background var(--transition-fast);
}

.first-run-hint-dismiss:hover {
    color: var(--text-primary);
    background: var(--bg-tertiary);
}

/* Sits above the bottom sheet's own chrome on small screens, where the header
 * help button is not present. */
@media (max-width: 768px) {
    .first-run-hint {
        top: auto;
        bottom: 96px;
        left: 16px;
        right: 16px;
        max-width: none;
        justify-content: space-between;
        transform: translateY(8px);
    }

    .first-run-hint.visible {
        transform: translateY(0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .first-run-hint,
    .first-run-hint.visible {
        transition: none;
        /* Keep the centring transform; only the motion is dropped. */
        transform: translate(-50%, 0);
    }
}

@media (prefers-reduced-motion: reduce) and (max-width: 768px) {
    .first-run-hint,
    .first-run-hint.visible {
        transform: none;
    }
}


/* ---- styles/components/prose.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Prose Utilities
 *
 * Small, named classes for the explanatory copy in the sidebar, help panel and
 * docs sections.
 *
 * These replace inline `style=""` attributes. CLAUDE.md lists inline styles as
 * an anti-pattern, and the reason is not tidiness: an inline declaration
 * outranks every class selector, so one of them silently suppressed every toast
 * in the application (F1). Keeping presentation in stylesheets keeps the
 * cascade predictable and keeps values on design tokens rather than on
 * hand-typed rems.
 *
 * Dynamic values that genuinely cannot live in a stylesheet — a per-author
 * colour, for instance — are passed as a CSS custom property instead, so the
 * rule still owns everything except the one thing that varies.
 */

/* Vertical rhythm ---------------------------------------------------------- */

.prose-gap-sm {
    margin-top: var(--spacing-sm);
}

.prose-gap {
    margin-top: var(--spacing-md);
}

.prose-gap-below {
    margin-bottom: var(--spacing-md);
}

/* A divider above a related block, e.g. the credits under a docs section. */
.prose-divided {
    margin-top: var(--spacing-md);
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--border);
}

/* Emphasis levels ---------------------------------------------------------- */

.prose-note {
    font-size: var(--font-size-sm);
    color: var(--text-secondary);
}

.prose-note-relaxed {
    font-size: var(--font-size-sm);
    color: var(--text-secondary);
    line-height: 1.5;
}

.prose-muted {
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

/* Secondary aside inside a line of body text. */
.prose-aside {
    font-size: var(--font-size-xs);
}

.prose-term {
    color: var(--text-secondary);
}

.prose-caption {
    margin-top: var(--spacing-sm);
    font-size: var(--font-size-sm);
    color: var(--text-muted);
}

/* Ordered list inside explanatory copy. */
.prose-steps {
    margin: var(--spacing-sm) 0 0 1.2rem;
    padding: 0;
}

/* Colour swatches ---------------------------------------------------------- */

/*
 * The swatch colour is per-item data (a file type or an author), so it arrives
 * as the --swatch custom property. Everything else about the element stays
 * here, and the template no longer interpolates a full declaration into an
 * HTML string.
 */
.swatch {
    background-color: var(--swatch, var(--text-muted));
}


/* ---- styles/components/tabs.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Tab Navigation Styles
 *
 * Tab navigation component with nav bar, tab buttons, and tab content panels.
 */

/* =============================================================================
   Tab Navigation
   ============================================================================= */

.tab-nav {
    display: flex;
    border-bottom: 1px solid var(--border);
    background: var(--bg-tertiary);
    width: 100%;
}

/* -----------------------------------------------------------------------------
   Tab Buttons
   ----------------------------------------------------------------------------- */

.tab-btn {
    flex: 1 1 0;
    padding: 0.5rem 0.4rem;
    background: transparent;
    border: none;
    color: var(--text-interactive);
    cursor: pointer;
    font-size: 0.75rem;
    font-weight: 500;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    text-align: center;
}

.tab-btn:hover {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.03);
}

.tab-btn.active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

/* -----------------------------------------------------------------------------
   Tab Content
   ----------------------------------------------------------------------------- */

.tab-content {
    display: none;
    padding: 0.875rem;
}

.tab-content.active {
    display: block;
}


/* ---- styles/components/inputs.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Input and Form Styles
 *
 * Form inputs, textareas, file upload areas, and related components.
 * Includes GitHub URL input, repo chips, fetch status, and command boxes.
 */

/* =============================================================================
   GitHub URL Input
   ============================================================================= */

.github-input-group {
    display: flex;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
    width: 100%;
}

.github-input-group input {
    flex: 1 1 0;
    min-width: 0; /* Allow shrinking below content size */
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-primary);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-md);
    font-size: var(--font-size-xs);
    width: 100%;
}

.github-input-group input:focus {
    outline: none;
    border-color: var(--accent-blue);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-blue) 20%, transparent);
}

.github-input-group input::placeholder {
    color: var(--text-muted);
    font-size: var(--font-size-xs);
}

.github-input-group .btn {
    flex-shrink: 0;
    white-space: nowrap;
}

/* =============================================================================
   Popular Repos / Chips
   ============================================================================= */

.popular-repos {
    margin-top: var(--spacing-md);
}

.popular-repos-label {
    font-size: var(--font-size-xs);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: var(--spacing-sm);
    display: block;
}

.repo-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
}

.repo-chip {
    background: var(--bg-tertiary);
    border: 1px solid var(--border-light);
    color: var(--text-interactive);
    padding: var(--spacing-sm) var(--spacing-md);
    min-height: 44px;
    border-radius: var(--radius-full);
    font-size: var(--font-size-sm);
    font-weight: 500;
    cursor: pointer;
    transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
}

.repo-chip:hover {
    /* The border and tinted fill carry the hover state; recolouring the label
       to --accent drops it to 3.6:1 (dark) / 3.3:1 (light) against that tint.
       Keeping --text-interactive holds it at 9.0:1 / 8.3:1, and the border
       still clears the 3:1 required of a non-text state indicator. */
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.repo-chip:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* Cached repo chips - indicate pre-loaded data (no API calls) */
.repo-chip-cached {
    border-color: color-mix(in srgb, var(--success) 60%, var(--border));
    background: color-mix(in srgb, var(--success) 10%, var(--bg-tertiary));
}

.repo-chip-cached::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    background: var(--success);
    border-radius: 50%;
    margin-right: 2px;
    flex-shrink: 0;
}

.repo-chip-cached:hover {
    /* As above: --success on its own 18% tint is 4.4:1 (dark) / 3.3:1 (light). */
    border-color: var(--success);
    background: color-mix(in srgb, var(--success) 18%, var(--bg-tertiary));
}

.repo-chip svg {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

/* =============================================================================
   Fetch Status
   ============================================================================= */

.fetch-status {
    margin-top: var(--spacing-md);
    padding: var(--spacing-md);
    background: var(--bg-tertiary);
    border-radius: var(--radius-md);
    font-size: var(--font-size-xs);
    display: none;
}

.fetch-status.visible {
    display: block;
}

.fetch-status.loading {
    color: var(--accent-blue);
}

.fetch-status.error {
    color: var(--error);
    background: color-mix(in srgb, var(--error) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--error) 30%, transparent);
}

.fetch-status.success {
    color: var(--success);
    background: color-mix(in srgb, var(--success) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
}

.fetch-progress {
    margin-top: var(--spacing-sm);
    height: 4px;
    background: var(--bg-primary);
    border-radius: 2px;
    overflow: hidden;
}

.fetch-progress-bar {
    height: 100%;
    background: var(--accent-blue);
    width: 0%;
    transition: width var(--transition-slow);
}

/* =============================================================================
   Rate Limit Status
   ============================================================================= */

.rate-limit-note {
    display: block;
    margin-top: var(--spacing-xs);
    color: var(--text-muted);
    font-size: var(--font-size-xs);
}

.rate-limit-status {
    margin-top: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-xs);
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.rate-limit-status.hidden {
    display: none;
}

.rate-limit-status.ok {
    background: color-mix(in srgb, var(--success) 10%, transparent);
    color: var(--success);
    border: 1px solid color-mix(in srgb, var(--success) 20%, transparent);
}

.rate-limit-status.low {
    background: color-mix(in srgb, var(--warning) 10%, transparent);
    color: var(--warning);
    border: 1px solid color-mix(in srgb, var(--warning) 20%, transparent);
}

.rate-limit-status.exhausted {
    background: color-mix(in srgb, var(--error) 10%, transparent);
    color: var(--error);
    border: 1px solid color-mix(in srgb, var(--error) 20%, transparent);
}

.rate-limit-icon {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

/* =============================================================================
   Textarea
   ============================================================================= */

textarea {
    width: 100%;
    height: 100px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-primary);
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    resize: vertical;
    margin-bottom: var(--spacing-md);
}

textarea:focus {
    outline: none;
    border-color: var(--accent-blue);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-blue) 20%, transparent);
}

/* =============================================================================
   File Upload
   ============================================================================= */

.file-upload-area {
    border: 2px dashed var(--border);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    text-align: center;
    margin-bottom: var(--spacing-md);
    cursor: pointer;
    transition: border-color var(--transition-fast), background var(--transition-fast);
}

.file-upload-area:hover {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 5%, transparent);
}

.file-upload-area.dragover {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.file-upload-area input[type="file"] {
    display: none;
}

.file-upload-icon {
    margin-bottom: var(--spacing-sm);
    color: var(--text-muted);
}

.file-upload-icon svg {
    width: 48px;
    height: 48px;
}

.file-upload-area:hover .file-upload-icon {
    color: var(--accent);
}

.file-upload-text {
    font-size: var(--font-size-xs);
    color: var(--text-secondary);
}

.file-upload-text strong {
    color: var(--accent);
}

.file-upload-privacy {
    font-size: var(--font-size-xs);
    color: var(--text-muted);
    margin-top: var(--spacing-sm);
    opacity: 0.8;
}

.file-name {
    margin-bottom: var(--spacing-md);
    color: var(--text-secondary);
    font-size: var(--font-size-xs);
    padding: var(--spacing-sm);
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    word-break: break-all;
}

/* =============================================================================
   Command Box
   ============================================================================= */

.command-box {
    background: var(--bg-tertiary);
    padding: var(--spacing-md);
    border-radius: var(--radius-md);
    font-family: var(--font-mono);
    font-size: var(--font-size-xs);
    overflow-x: auto;
    overflow-y: hidden;
    margin-bottom: var(--spacing-md);
    border: 1px solid var(--border);
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

.command-box code {
    color: var(--text-primary);
    white-space: nowrap;
    display: block;
    line-height: 1.4;
}

/* =============================================================================
   Help Text
   ============================================================================= */

.help-text {
    font-size: var(--font-size-xs);
    color: var(--text-muted);
    line-height: 1.6;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.help-text code {
    background: var(--bg-tertiary);
    padding: 0.1rem var(--spacing-xs);
    border-radius: 3px;
    font-size: var(--font-size-xs);
    word-break: break-all;
}


/* ---- styles/components/cards.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Card Styles
 *
 * Card-based components including tech info panels with
 * stat grids and badges. Includes collapsible card variants.
 */

/* =============================================================================
   Technical Info Panel
   ============================================================================= */

.tech-info-panel {
    background: linear-gradient(135deg, rgba(88, 166, 255, 0.08) 0%, rgba(233, 69, 96, 0.08) 100%);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.875rem;
    margin-bottom: 0.75rem;
    min-width: 0;
    box-sizing: border-box;
}

.tech-info-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    font-weight: 600;
    font-size: 0.8rem;
    color: var(--text-primary);
}

.tech-info-header svg {
    color: var(--accent-blue);
    flex-shrink: 0;
    width: 16px;
    height: 16px;
}

/* -----------------------------------------------------------------------------
   Tech Grid
   ----------------------------------------------------------------------------- */

.tech-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.4rem;
}

.tech-item {
    background: rgba(0, 0, 0, 0.2);
    border-radius: 4px;
    padding: 0.4rem;
    text-align: center;
    min-width: 0;
}

.tech-item-value {
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--accent-blue);
    font-variant-numeric: tabular-nums;
}

.tech-item-label {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* -----------------------------------------------------------------------------
   Tech Badges
   ----------------------------------------------------------------------------- */

.tech-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.5rem;
}

.tech-badge {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    padding: 0.15rem 0.4rem;
    background: var(--bg-tertiary);
    border-radius: 10px;
    color: var(--text-secondary);
    border: 1px solid var(--border);
    white-space: nowrap;
}

.tech-badge.highlight {
    background: rgba(233, 69, 96, 0.15);
    border-color: var(--accent);
    color: var(--accent);
}

/* =============================================================================
   Collapsible Tech Info Panel
   ============================================================================= */

.tech-info-panel.collapsible .tech-info-header {
    cursor: pointer;
    user-select: none;
    transition: opacity 0.2s;
    margin-bottom: 0;
    width: 100%;
    text-align: left;
    font: inherit;
    border: none;
    background: transparent;
    padding: 0;
    color: inherit;
}

.tech-info-panel.collapsible:not(.collapsed) .tech-info-header {
    margin-bottom: 0.75rem;
}

.tech-info-panel.collapsible .tech-info-header:hover {
    opacity: 0.8;
}

.tech-info-panel.collapsible .tech-info-header:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.tech-info-panel.collapsible .panel-toggle {
    margin-left: auto;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    transition: transform 0.2s;
}

.tech-info-panel.collapsible.collapsed .panel-toggle {
    transform: rotate(-90deg);
}

.tech-info-panel.collapsible.collapsed .tech-grid,
.tech-info-panel.collapsible.collapsed .tech-badges {
    display: none;
}


/* ---- styles/components/modals.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Modal Styles
 *
 * Modal overlay, modal content, close button, and export modal
 * specific styles including sliders, checkboxes, and actions.
 */

/* =============================================================================
   Modal Overlay
   ============================================================================= */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.85);
    z-index: var(--z-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 1;
    visibility: visible;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, visibility 0.2s;
    backdrop-filter: blur(4px);
}

.modal-overlay.closing {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* =============================================================================
   Modal Content
   ============================================================================= */

.modal-content {
    background: var(--bg-secondary);
    border-radius: 12px;
    padding: 2rem;
    max-width: 480px;
    width: 90%;
    max-height: 90vh;
    max-height: 90dvh; /* Dynamic viewport for mobile */
    overflow-y: auto;
    border: 1px solid var(--border);
    position: relative;
    animation: modalSlideIn 0.2s ease-out;
    /* Firefox scrollbar styling */
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

@keyframes modalSlideIn {
    from {
        opacity: 0;
        transform: translateY(-20px) scale(0.95);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* -----------------------------------------------------------------------------
   Modal Close Button
   ----------------------------------------------------------------------------- */

.modal-close {
    position: absolute;
    top: 1rem;
    right: 1rem;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 32px;
    height: 32px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, transform 0.2s;
    font-size: 1.25rem;
    line-height: 1;
}

.modal-close:hover {
    background: var(--border);
    color: var(--text-primary);
}

.modal-close:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* -----------------------------------------------------------------------------
   Modal Content Elements
   ----------------------------------------------------------------------------- */

.modal-content h2 {
    font-size: 1.25rem;
    margin-bottom: 0.75rem;
    padding-right: 2rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.modal-content h2 svg {
    color: var(--accent);
}

.modal-description {
    color: var(--text-secondary);
    font-size: 0.9rem;
    margin-bottom: 1.5rem;
    line-height: 1.5;
}

/* =============================================================================
   Export Modal
   ============================================================================= */

.export-modal {
    max-width: 420px;
}

/* -----------------------------------------------------------------------------
   Export Preview
   ----------------------------------------------------------------------------- */

.export-preview {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 1.25rem;
    text-align: center;
    margin-bottom: 1rem;
}

.export-dimensions {
    margin-bottom: 0.5rem;
}

.export-dim-value {
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--text-primary);
    font-family: 'JetBrains Mono', 'Fira Code', monospace;
}

.export-dim-label {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin-left: 0.25rem;
}

.export-estimate {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    font-size: 0.85rem;
}

.export-estimate-label {
    color: var(--text-muted);
}

.export-estimate-value {
    color: var(--text-secondary);
    font-weight: 500;
}

/* -----------------------------------------------------------------------------
   Export Warning
   ----------------------------------------------------------------------------- */

.export-warning {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    background: rgba(210, 153, 34, 0.15);
    border: 1px solid var(--warning);
    border-radius: 6px;
    padding: 0.75rem;
    margin-bottom: 1rem;
    font-size: 0.85rem;
    color: var(--warning);
}

.export-warning svg {
    flex-shrink: 0;
    margin-top: 2px;
}

/* -----------------------------------------------------------------------------
   Export Options
   ----------------------------------------------------------------------------- */

.export-options {
    margin-bottom: 1.5rem;
}

.export-option {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
}

.export-option span {
    font-size: 0.9rem;
    color: var(--text-primary);
}

.export-slider-group {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.export-slider-group input[type="range"] {
    width: 120px;
    height: 4px;
    -webkit-appearance: none;
    appearance: none;
    background: var(--border);
    border-radius: 2px;
    outline: none;
}

.export-slider-group input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    background: var(--accent);
    border-radius: 50%;
    cursor: pointer;
    transition: transform 0.15s;
}

.export-slider-group input[type="range"]::-webkit-slider-thumb:hover {
    transform: scale(1.1);
}

.export-slider-group input[type="range"]::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background: var(--accent);
    border-radius: 50%;
    cursor: pointer;
    border: none;
}

.export-slider-group input[type="range"]::-moz-range-track {
    height: 4px;
    background: var(--border);
    border-radius: 2px;
    border: none;
}

.export-slider-group input[type="range"]:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

#export-font-value {
    font-size: 0.85rem;
    color: var(--text-secondary);
    font-family: monospace;
    min-width: 35px;
}

.export-option-help {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-top: 0.5rem;
}

/* -----------------------------------------------------------------------------
   Export Checkbox Option
   ----------------------------------------------------------------------------- */

.export-checkbox-option {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1rem;
    cursor: pointer;
}

.export-checkbox-option input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--accent);
    cursor: pointer;
}

.export-checkbox-option input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.export-checkbox-option span {
    font-size: 0.9rem;
    color: var(--text-primary);
}

/* -----------------------------------------------------------------------------
   Export Actions
   ----------------------------------------------------------------------------- */

.export-actions {
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
}

.export-actions .btn {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}


/* ---- styles/components/showcase.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Showcase Component Styles
 *
 * Showcase panel, about banner, and tech info panel.
 * These are prominent display components used in the sidebar.
 */

/* =============================================================================
   Showcase Panel (prominent Rource visualization)
   ============================================================================= */

.showcase-panel {
    background: linear-gradient(135deg, rgba(233, 69, 96, 0.15) 0%, rgba(88, 166, 255, 0.15) 100%);
    border: 2px solid var(--accent);
    border-radius: 10px;
    padding: 1rem;
    text-align: center;
    position: relative;
    overflow: hidden;
    min-width: 0;
    box-sizing: border-box;
}

.showcase-panel::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--accent), var(--accent-blue), var(--accent));
}

.showcase-badge {
    position: absolute;
    top: 8px;
    right: 8px;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    padding: 0.15rem 0.4rem;
    background: var(--accent-surface);
    color: var(--text-on-accent);
    border-radius: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.showcase-icon {
    width: 42px;
    height: 42px;
    margin: 0 auto 0.5rem;
}

.showcase-panel h2,
.showcase-panel h3 {
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 0.5rem;
    color: var(--text-primary);
}

.showcase-panel p {
    font-size: 0.8rem;
    color: var(--text-secondary);
    margin-bottom: 0.75rem;
    line-height: 1.5;
}

/* -----------------------------------------------------------------------------
   Showcase Buttons
   ----------------------------------------------------------------------------- */

.showcase-btn {
    background: var(--accent-surface);
    color: var(--text-on-accent);
    border: none;
    padding: 0.6rem 1rem;
    border-radius: 8px;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.2s, transform 0.2s, opacity 0.2s;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    box-shadow: 0 2px 8px rgba(233, 69, 96, 0.3);
    flex: 1 1 auto;
    justify-content: center;
    min-width: 0;
    white-space: nowrap;
}

.showcase-btn:hover {
    background: var(--accent-hover);
    transform: translateY(-1px);
}

.showcase-btn:disabled {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.showcase-buttons {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
    width: 100%;
}

.showcase-btn-secondary {
    flex: 0 0 auto;
    background: transparent;
    color: var(--text-interactive);
    border: 1px solid var(--border);
    padding: 0.5rem 0.6rem;
    border-radius: 6px;
    cursor: pointer;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s ease, transform 0.2s ease;
    white-space: nowrap;
}

.showcase-btn-secondary:hover {
    background: var(--bg-tertiary);
    border-color: var(--accent-blue);
    color: var(--accent-blue);
}

.showcase-btn-secondary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.showcase-btn-secondary.loading {
    pointer-events: none;
}

.showcase-btn-secondary.loading svg {
    animation: spin 1s linear infinite;
}

/* -----------------------------------------------------------------------------
   Refresh Status
   ----------------------------------------------------------------------------- */

.refresh-status {
    margin-top: 0.5rem;
    font-size: 0.75rem; /* 12px - WCAG minimum (was clamp with sub-12px values) */
    text-align: center;
    padding: 0.35rem 0.5rem;
    border-radius: 4px;
}

.refresh-status.success {
    background: color-mix(in srgb, var(--success) 15%, transparent);
    color: var(--success);
}

.refresh-status.error {
    background: color-mix(in srgb, var(--error) 15%, transparent);
    color: var(--error);
}

.refresh-status.loading {
    background: color-mix(in srgb, var(--accent-blue) 15%, transparent);
    color: var(--accent-blue);
}

/* -----------------------------------------------------------------------------
   Showcase Stats
   ----------------------------------------------------------------------------- */

.showcase-stats {
    display: flex;
    justify-content: space-around;
    gap: 0.5rem;
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.showcase-stat {
    text-align: center;
    flex: 1;
    min-width: 0;
}

/* Stats with tooltips should show help cursor */
.showcase-stat[title] {
    cursor: help;
}

.showcase-stat-value {
    font-size: 1rem;
    font-weight: 700;
    color: var(--accent-blue);
}

.showcase-stat-label {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* =============================================================================
   About Banner
   ============================================================================= */

.about-banner {
    background: linear-gradient(135deg, rgba(233, 69, 96, 0.1) 0%, rgba(88, 166, 255, 0.1) 100%);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.875rem;
    text-align: center;
    min-width: 0;
    box-sizing: border-box;
}

.about-banner h2,
.about-banner h3 {
    font-size: 0.85rem;
    margin-bottom: 0.5rem;
}

.about-banner p {
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-bottom: 0.75rem;
}

.about-links {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.about-links .btn {
    font-size: 0.75rem;
    padding: 0.35rem 0.6rem;
}

/* =============================================================================
   Tech Info Panel
   ============================================================================= */

.tech-info-panel {
    background: linear-gradient(135deg, rgba(88, 166, 255, 0.08) 0%, rgba(233, 69, 96, 0.08) 100%);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.875rem;
    margin-bottom: 0.75rem;
    min-width: 0;
    box-sizing: border-box;
}

.tech-info-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    font-weight: 600;
    font-size: 0.8rem;
    color: var(--text-primary);
}

.tech-info-header svg {
    color: var(--accent-blue);
    flex-shrink: 0;
    width: 16px;
    height: 16px;
}

.tech-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.4rem;
}

.tech-item {
    background: rgba(0, 0, 0, 0.2);
    border-radius: 4px;
    padding: 0.4rem;
    text-align: center;
    min-width: 0;
}

.tech-item-value {
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--accent-blue);
    font-variant-numeric: tabular-nums;
}

.tech-item-label {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.tech-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.5rem;
}

.tech-badge {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    padding: 0.15rem 0.4rem;
    background: var(--bg-tertiary);
    border-radius: 10px;
    color: var(--text-secondary);
    border: 1px solid var(--border);
    white-space: nowrap;
}

.tech-badge.highlight {
    background: rgba(233, 69, 96, 0.15);
    border-color: var(--accent);
    color: var(--accent);
}

/* -----------------------------------------------------------------------------
   Collapsible Tech Info Panel
   ----------------------------------------------------------------------------- */

.tech-info-panel.collapsible .tech-info-header {
    cursor: pointer;
    user-select: none;
    transition: opacity 0.2s;
    margin-bottom: 0;
    width: 100%;
    text-align: left;
    font: inherit;
    border: none;
    background: transparent;
    padding: 0;
    color: inherit;
}

.tech-info-panel.collapsible:not(.collapsed) .tech-info-header {
    margin-bottom: 0.75rem;
}

.tech-info-panel.collapsible .tech-info-header:hover {
    opacity: 0.8;
}

.tech-info-panel.collapsible .tech-info-header:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.tech-info-panel.collapsible .panel-toggle {
    margin-left: auto;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    transition: transform 0.2s;
}

.tech-info-panel.collapsible.collapsed .panel-toggle {
    transform: rotate(-90deg);
}

.tech-info-panel.collapsible.collapsed .tech-grid,
.tech-info-panel.collapsible.collapsed .tech-badges {
    display: none;
}

/* =============================================================================
   Demo Landing Panel
   -----------------------------------------------------------------------------
   Replaces the "Visualize This Project" showcase in the published demo. The
   two things a first-time visitor should be able to act on immediately are the
   bundled histories and the fact that their own repository never leaves the
   browser, so both are given real estate rather than being buried in collapsed
   panels further down the sidebar.
   ============================================================================= */

.demo-welcome-title {
    margin: 0 0 var(--spacing-xs);
    font-size: 1.05rem;
    font-weight: 650;
    color: var(--text-primary);
}

.demo-welcome-subtitle {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    margin: 0 0 var(--spacing-xs);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
}

.demo-welcome-lead {
    margin: 0 0 var(--spacing-sm);
    font-size: 0.8125rem; /* 13px */
    line-height: 1.5;
    color: var(--text-secondary);
}

.demo-repo-chips {
    display: grid;
    /* Two per row at sidebar width, collapsing to one when the sidebar is
       narrow, rather than a ragged wrap. */
    grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: var(--spacing-xs);
}

.demo-repo-chip {
    /* Clears the 44px minimum touch target; the shared .repo-chip is sized for
       a dense secondary list, which is too small for a primary action. */
    min-height: 44px;
    justify-content: flex-start;
    font-size: 0.8125rem;
}

.demo-welcome-divider {
    height: 1px;
    margin: var(--spacing-md) 0;
    background: var(--border);
}

.demo-welcome-cta {
    width: 100%;
    justify-content: center;
    min-height: 44px;
}

/* Brief ring on the drop zone after the landing CTA jumps to it, so the
   destination is obvious rather than the panel just appearing to change. */
.file-drop-zone-highlight {
    animation: drop-zone-attention 1.6s ease-out;
}

@keyframes drop-zone-attention {
    0%, 100% { box-shadow: 0 0 0 0 transparent; }
    20%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 45%, transparent); }
    60%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
    .file-drop-zone-highlight {
        animation: none;
        outline: 2px solid var(--accent);
        outline-offset: 2px;
    }
}


/* ---- styles/components/skeleton.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Skeleton Loading Styles
 *
 * Loading overlay, skeleton placeholders, and loading spinner.
 * Used during initial load and data fetching states.
 */

/* =============================================================================
   Loading Overlay
   ============================================================================= */

#loading {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: var(--bg-primary);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: var(--z-fullscreen);
    /* Contain layout to prevent CLS when hiding */
    contain: layout style paint;
    /* Use composited properties only for better performance */
    transition: opacity 0.3s, visibility 0.3s;
}

#loading.hidden {
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
}

/* =============================================================================
   Loading Skeleton Container
   ============================================================================= */

.loading-skeleton {
    width: 100%;
    max-width: 800px;
    padding: 2rem;
    /* Contain layout to prevent affecting other elements */
    contain: layout style;
}

.skeleton-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 2rem;
}

.skeleton-logo {
    width: 40px;
    height: 40px;
    background: var(--bg-tertiary);
    border-radius: 8px;
    position: relative;
    overflow: hidden;
}

.skeleton-title {
    height: 24px;
    width: 120px;
    background: var(--bg-tertiary);
    border-radius: 4px;
    position: relative;
    overflow: hidden;
}

/* =============================================================================
   Skeleton Canvas Placeholder
   ============================================================================= */

.skeleton-canvas {
    width: 100%;
    height: 350px;
    background: var(--bg-tertiary);
    border-radius: 12px;
    margin-bottom: 1rem;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
}

.skeleton-canvas-text {
    color: var(--text-secondary);
    font-size: 0.9rem;
    z-index: 1;
}

/* =============================================================================
   Skeleton Tree Visualization
   ============================================================================= */

/* Simulated tree structure in loading state */
.skeleton-tree {
    position: relative;
    width: 200px;
    height: 200px;
}

.skeleton-node {
    position: absolute;
    width: 12px;
    height: 12px;
    background: var(--border);
    border-radius: 50%;
    opacity: 0.3;
}

/* Root node in center */
.skeleton-node.root {
    width: 24px;
    height: 24px;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    opacity: 0.5;
}

/* Orbiting file nodes */
.skeleton-node.file-1 { left: 20%; top: 30%; }
.skeleton-node.file-2 { left: 70%; top: 25%; }
.skeleton-node.file-3 { left: 80%; top: 60%; }
.skeleton-node.file-4 { left: 30%; top: 70%; }
.skeleton-node.file-5 { left: 50%; top: 15%; }
.skeleton-node.file-6 { left: 15%; top: 55%; }

/* Connecting beams */
.skeleton-beam {
    position: absolute;
    height: 2px;
    background: var(--accent);
    opacity: 0.1;
    transform-origin: left center;
    animation: beam-pulse 2s ease-in-out infinite;
}

.skeleton-beam-1 {
    width: 60px;
    left: 50%;
    top: 50%;
    transform: rotate(-35deg);
}

.skeleton-beam-2 {
    width: 70px;
    left: 50%;
    top: 50%;
    transform: rotate(25deg);
}

.skeleton-beam-3 {
    width: 55px;
    left: 50%;
    top: 50%;
    transform: rotate(110deg);
}

.skeleton-beam-4 {
    width: 65px;
    left: 50%;
    top: 50%;
    transform: rotate(-120deg);
}

/* Pulsing animation for root */
.skeleton-pulse {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 60px;
    height: 60px;
    border: 2px solid var(--accent);
    border-radius: 50%;
    animation: pulse 2s ease-in-out infinite;
}

/* =============================================================================
   Skeleton Timeline Controls
   ============================================================================= */

.skeleton-controls {
    display: flex;
    gap: 1rem;
    align-items: center;
    justify-content: center;
}

.skeleton-btn {
    height: 32px;
    width: 80px;
    background: var(--bg-tertiary);
    border-radius: 6px;
    position: relative;
    overflow: hidden;
}

.skeleton-slider {
    flex: 1;
    max-width: 300px;
    height: 6px;
    background: var(--bg-tertiary);
    border-radius: 3px;
    position: relative;
    overflow: hidden;
}

/* =============================================================================
   Shimmer Animation Effect
   ============================================================================= */

.skeleton-logo::after,
.skeleton-title::after,
.skeleton-canvas::after,
.skeleton-btn::after,
.skeleton-slider::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(
        90deg,
        transparent,
        rgba(255, 255, 255, 0.08),
        transparent
    );
    animation: shimmer 1.5s infinite;
}

/* =============================================================================
   Loading Spinner
   ============================================================================= */

.loading-spinner {
    width: 48px;
    height: 48px;
    border: 3px solid var(--bg-tertiary);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

/* Smaller spinner variant */
.loading-spinner.small {
    width: 20px;
    height: 20px;
    border-width: 2px;
}

/* Inline spinner for buttons */
.loading-spinner.inline {
    width: 16px;
    height: 16px;
    border-width: 2px;
    margin-right: 0.5rem;
}

/* =============================================================================
   Loading Text
   ============================================================================= */

.loading-text {
    margin-top: 1rem;
    color: var(--text-secondary);
    font-size: 0.9rem;
}

/* =============================================================================
   Responsive Adjustments
   ============================================================================= */

@media (max-width: 768px) {
    .loading-skeleton {
        padding: 1rem;
    }

    .skeleton-canvas {
        height: 250px;
    }

    .skeleton-tree {
        width: 150px;
        height: 150px;
    }

    .skeleton-node.root {
        width: 18px;
        height: 18px;
    }

    .skeleton-pulse {
        width: 45px;
        height: 45px;
    }
}


/* ---- styles/components/docs.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Documentation Panel Styles
 *
 * Documentation sections, shortcut grids, feature lists, and panel guides.
 * Used for help content and feature documentation in the sidebar.
 */

/* =============================================================================
   Documentation Panel
   ============================================================================= */

.docs-panel {
    min-width: 0;
    box-sizing: border-box;
}

.docs-panel .panel-body {
    min-width: 0;
    overflow-x: hidden;
}

.docs-section {
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--border);
    min-width: 0;
}

.docs-section:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.docs-section h3 {
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--text-primary);
}

.docs-section h3 svg {
    color: var(--accent);
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

.docs-section p {
    font-size: 0.75rem;
    color: var(--text-secondary);
    line-height: 1.5;
    margin-bottom: 0.5rem;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.docs-section ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.docs-section li {
    font-size: 0.75rem;
    color: var(--text-secondary);
    padding: 0.25rem 0;
    padding-left: 1rem;
    position: relative;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.docs-section li::before {
    content: "•";
    position: absolute;
    left: 0;
    color: var(--accent);
}

/* =============================================================================
   Documentation Heading (expandable)
   ============================================================================= */

.docs-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: pointer;
    user-select: none;
    transition: opacity 0.2s;
    width: 100%;
    font: inherit;
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    text-align: left;
    color: var(--text-primary);
}

.docs-heading:hover {
    opacity: 0.8;
}

.docs-heading:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.docs-heading .panel-toggle {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    transition: transform 0.2s;
}

.docs-section.collapsed .docs-heading .panel-toggle {
    transform: rotate(-90deg);
}

.docs-section.collapsed > *:not(.docs-heading) {
    display: none;
}

/* =============================================================================
   Shortcut Grid
   ============================================================================= */

.shortcut-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.25rem 0.75rem;
    font-size: 0.75rem;
}

.shortcut-key {
    background: var(--bg-tertiary);
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-secondary);
    border: 1px solid var(--border);
    text-align: center;
    min-width: 1.5em;
    white-space: nowrap;
}

.shortcut-desc {
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    word-wrap: break-word;
    overflow-wrap: break-word;
    min-width: 0;
}

/* =============================================================================
   Feature List
   ============================================================================= */

.feature-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.feature-item {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--text-secondary);
    line-height: 1.4;
}

.feature-item svg {
    color: var(--success);
    flex-shrink: 0;
    margin-top: 2px;
    width: 12px;
    height: 12px;
}

.feature-item span {
    word-wrap: break-word;
    overflow-wrap: break-word;
    min-width: 0;
}

/* =============================================================================
   Panel Guide (instructional text)
   ============================================================================= */

.panel-guide {
    padding: 0.75rem;
    background: var(--bg-tertiary);
    border-radius: 6px;
    margin-bottom: 0.75rem;
}

.panel-guide h3 {
    font-size: 0.8rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
    color: var(--text-primary);
}

.panel-guide .help-text {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    line-height: 1.6;
}

/* =============================================================================
   Responsive Adjustments
   ============================================================================= */

@media (max-width: 1400px) {
    .docs-section h3 {
        font-size: 0.8rem;
    }

    .docs-section p,
    .docs-section li {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    .shortcut-grid {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    .shortcut-key {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }
}


/* ---- styles/components/tooltips.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Tooltip Styles
 *
 * Commit tooltips displayed when hovering over files in the visualization.
 */

/* =============================================================================
   Commit Tooltip
   ============================================================================= */

.commit-tooltip {
    position: fixed;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 0.75rem 1rem;
    max-width: 320px;
    z-index: var(--z-modal);
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.15s, visibility 0.15s;
    box-shadow: 0 4px 12px var(--shadow);
}

.commit-tooltip.visible {
    opacity: 1;
    visibility: visible;
}

/* =============================================================================
   Tooltip Header
   ============================================================================= */

.commit-tooltip-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.commit-tooltip-author-color {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
}

.commit-tooltip-author {
    font-weight: 600;
    color: var(--text-primary);
    flex: 1;
}

.commit-tooltip-date {
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* =============================================================================
   Tooltip Content
   ============================================================================= */

.commit-tooltip-file {
    font-family: 'SF Mono', 'Monaco', monospace;
    font-size: 0.8rem;
    color: var(--accent-blue);
    word-break: break-all;
    margin-bottom: 0.5rem;
}

/* =============================================================================
   Action Badge
   ============================================================================= */

.commit-tooltip-action {
    display: inline-block;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    font-weight: 600;
    text-transform: uppercase;
}

.commit-tooltip-action.add {
    background: rgba(63, 185, 80, 0.2);
    color: var(--success);
}

.commit-tooltip-action.modify {
    background: rgba(210, 153, 34, 0.2);
    color: var(--warning);
}

.commit-tooltip-action.delete {
    background: rgba(248, 81, 73, 0.2);
    color: var(--error);
}

/* =============================================================================
   Sections
   ============================================================================= */

/* ---- styles/sections/header.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Header Styles
 *
 * App header containing logo, controls, and navigation links.
 * Responsive breakpoints included for control dividers and mobile compact mode.
 */

/* =============================================================================
   Header
   ============================================================================= */

header {
    background: var(--bg-secondary);
    /* L5: Respect safe area for notched devices (iPhone X+, Dynamic Island) */
    padding: 0.75rem 1.5rem;
    padding-top: max(0.75rem, env(safe-area-inset-top, 0px));
    padding-left: max(1.5rem, env(safe-area-inset-left, 0px));
    padding-right: max(1.5rem, env(safe-area-inset-right, 0px));
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
    gap: 0.75rem;
    flex-shrink: 0;
    z-index: 100;
}

/* -----------------------------------------------------------------------------
   Brand / Logo
   ----------------------------------------------------------------------------- */

.header-brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.header-brand a {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: var(--text-primary);
}

.header-brand a:hover {
    text-decoration: none;
}

.logo-icon {
    width: 28px;
    height: 28px;
}

header h1 {
    font-size: 1.25rem;
    font-weight: 600;
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-light) 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

/* -----------------------------------------------------------------------------
   Controls
   ----------------------------------------------------------------------------- */

.controls {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    flex-wrap: wrap;
}

.control-group {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.control-divider {
    width: 1px;
    height: 20px;
    background: var(--border);
    margin: 0 0.25rem;
}

/* Hide dividers on small screens when controls wrap */
@media (max-width: 900px) {
    .control-divider {
        display: none;
    }
}

/* -----------------------------------------------------------------------------
   Header Links
   ----------------------------------------------------------------------------- */

.header-links {
    display: flex;
    gap: 1rem;
    align-items: center;
}

.github-link {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-primary);
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.5rem 0.85rem;
    border-radius: 6px;
    border: 1px solid var(--accent-gold);
    /* Fallback for browsers without color-mix() */
    background: rgba(212, 167, 44, 0.1);
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, transform 0.2s;
}

/* Modern browsers: use color-mix for theme-aware backgrounds */
@supports (background: color-mix(in srgb, red 50%, blue)) {
    .github-link {
        background: color-mix(in srgb, var(--accent-gold) 10%, transparent);
    }

    .github-link:hover {
        background: color-mix(in srgb, var(--accent-gold) 25%, transparent);
    }
}

.github-link:hover {
    color: var(--text-on-accent);
    border-color: var(--accent-gold-hover);
    /* Fallback for browsers without color-mix() */
    background: rgba(212, 167, 44, 0.25);
    text-decoration: none;
}

.github-link svg {
    fill: var(--accent-gold-hover);
}

/* -----------------------------------------------------------------------------
   Short Viewport Optimizations (ultrawide monitors, resized windows)
   ----------------------------------------------------------------------------- */

/* Compact header when viewport height is constrained */
@media (max-height: 500px) {
    header {
        padding: 0.4rem 1rem;
        gap: 0.5rem;
    }

    .logo-icon {
        width: 24px;
        height: 24px;
    }

    header h1 {
        font-size: 1rem;
    }

    .github-link {
        padding: 0.35rem 0.6rem;
        font-size: 0.8rem;
    }

    .btn-sm {
        padding: 0.3rem 0.6rem;
        font-size: 0.75rem;
    }
}

/* Very short viewports - minimal header */
@media (max-height: 400px) {
    header {
        padding: 0.25rem 0.75rem;
        gap: 0.4rem;
    }

    .header-brand {
        gap: 0.5rem;
    }

    .logo-icon {
        width: 20px;
        height: 20px;
    }

    header h1 {
        font-size: 0.9rem;
    }

    /* Hide GitHub link on extremely short viewports to save space */
    .github-link {
        display: none;
    }

    .btn-sm {
        padding: 0.25rem 0.5rem;
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    .control-group {
        gap: 0.3rem;
    }
}

/* -----------------------------------------------------------------------------
   Mobile Landscape Optimizations
   ----------------------------------------------------------------------------- */

/* Mobile landscape: Compact header to maximize canvas space */
@media (max-width: 768px) and (orientation: landscape) {
    header {
        padding: 0.35rem 0.75rem;
        gap: 0.4rem;
    }

    .header-brand {
        gap: 0.4rem;
    }

    .logo-icon {
        width: 22px;
        height: 22px;
    }

    header h1 {
        font-size: 0.95rem;
    }

    /* Hide GitHub link in mobile landscape to save horizontal space */
    .github-link {
        display: none;
    }

    .btn-sm {
        padding: 0.3rem 0.5rem;
        font-size: 0.75rem;
    }

    .control-group {
        gap: 0.3rem;
    }

    .control-divider {
        display: none;
    }
}


/* ---- styles/sections/canvas.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Canvas and Layout Styles
 *
 * Main app layout grid, visualization panel, canvas container,
 * empty state, and context lost overlay.
 */

/* =============================================================================
   Main Layout
   ============================================================================= */

/* Full viewport, no scrolling */
.app-container {
    display: grid;
    grid-template-columns: 1fr minmax(320px, min(400px, 30vw));
    gap: 1rem;
    padding: 1rem;
    flex: 1;
    min-height: 0; /* Critical for flex children to shrink properly */
    overflow: hidden;
    contain: layout style; /* Prevent CLS propagation */
}

@media (max-width: 1600px) {
    .app-container {
        grid-template-columns: 1fr minmax(300px, 340px);
    }
}

@media (max-width: 1400px) {
    .app-container {
        grid-template-columns: 1fr minmax(280px, 320px);
        gap: 0.75rem;
        padding: 0.75rem;
    }
}

@media (max-width: 1200px) {
    .app-container {
        grid-template-columns: 1fr;
        grid-template-rows: 1fr auto;
    }
}

@media (max-width: 768px) {
    .app-container {
        padding: 0.5rem;
        gap: 0.5rem;
    }
}

/* =============================================================================
   Visualization Panel
   ============================================================================= */

.viz-panel {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 0; /* Allow shrinking in flex container */
    overflow: hidden;
    contain: layout; /* Prevent CLS propagation */
}

/* Override display:flex when hidden attribute is set by view-manager.js.
   The browser UA [hidden]{display:none} is overridden by author display:flex,
   so we must explicitly enforce it here. */
.viz-panel[hidden] {
    display: none;
}

/* -----------------------------------------------------------------------------
   Canvas Container
   ----------------------------------------------------------------------------- */

#canvas-container {
    flex: 1;
    min-height: 200px; /* Minimum usable size */
    background: var(--bg-canvas);
    border-radius: 8px;
    overflow: hidden;
    position: relative;
    border: 1px solid var(--border);
    contain: strict; /* Full containment for canvas area */
}

/* -----------------------------------------------------------------------------
   Short Viewport Optimizations (ultrawide monitors, resized windows)
   ----------------------------------------------------------------------------- */

/* When viewport height is very constrained on desktop, ensure canvas
   still has a reasonable minimum size for usability */
@media (min-width: 769px) and (max-height: 500px) {
    #canvas-container {
        min-height: 180px;
    }
}

/* Even shorter viewports - prioritize canvas visibility */
@media (min-width: 769px) and (max-height: 400px) {
    #canvas-container {
        min-height: 150px;
        border-radius: 4px;
    }
}

@media (max-width: 768px) {
    #canvas-container {
        min-height: 200px;
    }
}

/* Reduce min-height in landscape to fit more content */
@media (max-width: 768px) and (orientation: landscape) {
    #canvas-container {
        min-height: 120px;
    }
}

#canvas {
    width: 100%;
    height: 100%;
    display: block;
    touch-action: none;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;

    /* Force GPU compositing layer for smoother animation and proper DPI scaling.
       This is critical for Safari to properly handle high-DPI canvases. */
    transform: translateZ(0);
    -webkit-transform: translateZ(0);

    /* Prevent Safari from optimizing away the layer */
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;

    /* Use high-quality image rendering (default for most browsers).
       Safari may need -webkit-optimize-contrast for crisp edges. */
    image-rendering: -webkit-optimize-contrast;
    image-rendering: auto;
}

/* =============================================================================
   Empty State
   ============================================================================= */

.empty-state {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    color: var(--text-secondary);
    pointer-events: none;
    max-width: 400px;
    padding: 2rem;
}

.empty-state.hidden {
    display: none;
}

.empty-state-icon {
    width: 80px;
    height: 80px;
    margin: 0 auto 1rem;
    opacity: 0.4;
}

.empty-state h3 {
    font-size: 1.25rem;
    margin-bottom: 0.5rem;
    color: var(--text-primary);
}

.empty-state p {
    font-size: 0.9rem;
    line-height: 1.6;
}

/* =============================================================================
   Context Lost Overlay
   ============================================================================= */

.context-lost-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(13, 17, 23, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: var(--z-dropdown);
    backdrop-filter: blur(4px);
}

.context-lost-overlay.hidden {
    display: none;
}

.context-lost-content {
    text-align: center;
    max-width: 400px;
    padding: 2rem;
}

.context-lost-icon {
    width: 64px;
    height: 64px;
    color: var(--warning);
    margin-bottom: 1rem;
}

.context-lost-content h3 {
    font-size: 1.25rem;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.context-lost-content p {
    font-size: 0.9rem;
    color: var(--text-secondary);
    line-height: 1.6;
    margin-bottom: 1.5rem;
}

.context-lost-content .btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}


/* ---- styles/sections/sidebar.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Sidebar Styles
 *
 * Sidebar wrapper, scrollable panel, and scroll indicator.
 * Includes the bounce animation for the scroll indicator.
 */

/* =============================================================================
   Sidebar Wrapper
   ============================================================================= */

/* Container for sidebar panel and scroll indicator */
.sidebar-wrapper {
    display: flex;
    flex-direction: column;
    min-height: 0; /* Critical for overflow in flex/grid children */
    position: relative;
    contain: layout; /* Prevent CLS propagation */
}

/* Enforce hidden when view-manager.js sets hidden attribute.
   Without this, display:flex overrides the UA [hidden]{display:none}. */
.sidebar-wrapper[hidden] {
    display: none;
}

/* =============================================================================
   Sidebar Panel
   ============================================================================= */

/* Scrollable independent of main content */
.sidebar-panel {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0; /* Critical for overflow in flex/grid children */
    min-width: 0; /* Prevent content from expanding container */
    width: 100%;
    flex: 1; /* Fill available space in wrapper */
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

/* Ensure all sidebar children respect container width */
.sidebar-panel > * {
    min-width: 0;
    max-width: 100%;
    flex-shrink: 0;
    box-sizing: border-box;
}

/* -----------------------------------------------------------------------------
   Custom Scrollbar (WebKit)
   ----------------------------------------------------------------------------- */

.sidebar-panel::-webkit-scrollbar {
    width: 6px;
}

.sidebar-panel::-webkit-scrollbar-track {
    background: transparent;
}

.sidebar-panel::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: 3px;
}

.sidebar-panel::-webkit-scrollbar-thumb:hover {
    background: var(--border-light);
}

/* =============================================================================
   Scroll Indicator
   ============================================================================= */

/* Shows when more content is below */
.sidebar-scroll-indicator {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    background: linear-gradient(to bottom, transparent 0%, var(--bg-primary) 40%);
    color: var(--text-secondary);
    font-size: 0.75rem;
    pointer-events: none;
    opacity: 1;
    transition: opacity 0.3s ease;
    z-index: 10;
}

.sidebar-scroll-indicator.hidden {
    opacity: 0;
}

.sidebar-scroll-indicator svg {
    animation: bounce 1.5s ease-in-out infinite;
}

@keyframes bounce {
    0%, 100% {
        transform: translateY(0);
    }
    50% {
        transform: translateY(4px);
    }
}

/* =============================================================================
   Responsive
   ============================================================================= */

@media (max-width: 1400px) {
    .sidebar-panel {
        gap: 0.5rem;
    }
}

@media (max-width: 1200px) {
    .sidebar-panel {
        max-height: 40vh;
        flex-shrink: 0;
    }
}

@media (max-width: 768px) {
    .sidebar-panel {
        max-height: 35vh;
    }
}


/* ---- styles/sections/timeline.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Timeline Section Styles
 *
 * Playback timeline controls including slider, date display, play/pause buttons,
 * and speed controls.
 */

/* =============================================================================
   Timeline Container
   ============================================================================= */

.timeline-container {
    background: var(--bg-secondary);
    border-radius: 8px;
    padding: 0.5rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    border: 1px solid var(--border);
    /* Reserve space to prevent CLS during load */
    min-height: 90px;
    /* Contain layout to prevent CLS propagation (not 'content' which clips overflow) */
    contain: layout style;
}

/* Enforce hidden when view-manager.js sets hidden attribute.
   Without this, display:flex overrides the UA [hidden]{display:none}. */
.timeline-container[hidden] {
    display: none;
}

/* =============================================================================
   Date and Commit Info Row
   ============================================================================= */

.timeline-date-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0 0.25rem;
    /* Reserve consistent height to prevent CLS */
    min-height: 1.4em;
}

.timeline-date {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    /* Reserve space for date text */
    min-height: 1.2em;
}

.timeline-commit-info {
    font-size: 0.75rem;
    color: var(--text-secondary);
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    max-width: 50%;
    text-align: right;
    /* Reserve space for commit info */
    min-height: 1.2em;
}

/* =============================================================================
   Slider Row
   ============================================================================= */

.timeline-slider-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    overflow: visible;  /* Allow tick labels/tooltips to show above */
    padding-top: 12px;  /* Space for tick labels above slider */
}

/* Date labels at ends of slider */
.timeline-date-label {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    min-width: 52px;
}

.timeline-date-label:first-of-type {
    text-align: right;
}

.timeline-date-label:last-of-type {
    text-align: left;
}

/* =============================================================================
   Timeline Slider
   ============================================================================= */

.timeline-slider {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    background: var(--bg-tertiary);
    border-radius: 3px;
    outline: none;
}

.timeline-slider:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 4px;
}

.timeline-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    background: var(--accent);
    border-radius: 50%;
    cursor: pointer;
    transition: transform 0.2s;
    /* Hint to browser that transform will change - improves hover animation perf */
    will-change: transform;
}

.timeline-slider::-webkit-slider-thumb:hover {
    transform: scale(1.2);
}

.timeline-slider::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background: var(--accent);
    border-radius: 50%;
    cursor: pointer;
    border: none;
    /* Hint to browser that transform will change - improves hover animation perf */
    will-change: transform;
}

.timeline-slider:disabled {
    opacity: 0.5;
}

/* =============================================================================
   Controls Row
   ============================================================================= */

.timeline-controls-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
}

.playback-controls {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.timeline-controls {
    display: flex;
    gap: 0.25rem;
    align-items: center;
}

/* =============================================================================
   Timeline Buttons
   ============================================================================= */

.timeline-btn {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 32px;
    height: 32px;
    border-radius: var(--radius-md);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity var(--transition-normal), transform var(--transition-normal);
}

.timeline-btn:hover {
    background: var(--border);
    color: var(--text-primary);
}

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

.timeline-btn.active {
    background: var(--accent-surface);
    border-color: var(--accent);
    color: var(--text-on-accent);
}

/* =============================================================================
   Main Play Button
   ============================================================================= */

.play-btn-main {
    background: var(--accent-surface);
    border: none;
    color: var(--text-on-accent);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.2s;
    box-shadow: 0 2px 8px rgba(233, 69, 96, 0.3);
    will-change: transform;
}

.play-btn-main:hover:not(:disabled) {
    background: var(--accent-hover);
    transform: scale(1.05);
    box-shadow: 0 4px 12px rgba(233, 69, 96, 0.4);
}

.play-btn-main:disabled {
    background: var(--bg-tertiary);
    color: var(--text-muted);
    cursor: not-allowed;
    box-shadow: none;
}

.play-btn-main svg {
    width: 20px;
    height: 20px;
}

/* Replay state */
.play-btn-main.replay {
    background: var(--accent-blue-surface);
    box-shadow: 0 2px 8px rgba(88, 166, 255, 0.3);
}

.play-btn-main.replay:hover:not(:disabled) {
    background: var(--accent-blue-surface-hover);
    box-shadow: 0 4px 12px rgba(88, 166, 255, 0.4);
}

/* =============================================================================
   Reset Button
   ============================================================================= */

.reset-btn {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 36px;
    height: 36px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.2s, transform 0.2s;
}

.reset-btn:hover:not(:disabled) {
    background: var(--border);
    color: var(--text-primary);
}

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

.reset-btn svg {
    width: 16px;
    height: 16px;
}

/* =============================================================================
   Timeline Info Display
   ============================================================================= */

.timeline-info {
    font-size: 0.8rem;
    color: var(--text-secondary);
    min-width: 100px;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
}

.timeline-info[title] {
    cursor: help;
}

.timeline-info-label {
    color: var(--text-secondary);
    font-size: 0.75rem; /* 12px - WCAG minimum */
}

.timeline-info-numbers {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}

/* =============================================================================
   Right Controls (Speed)
   ============================================================================= */

.timeline-right-controls {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.speed-control {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.speed-control label {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

.speed-control select {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-primary);
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    position: relative;
    z-index: var(--z-speed-select); /* Above toast to ensure dropdown options are clickable */
    /* Ensure dropdown has enough width for longest option */
    min-width: max-content;
}

/* =============================================================================
   Responsive Adjustments
   ============================================================================= */

@media (max-width: 768px) {
    .timeline-container {
        padding: 0.5rem;
        gap: 0.4rem;
        min-height: 110px; /* Taller on mobile due to stacked layout */
    }

    .timeline-date {
        font-size: 0.85rem;
        /* Ensure date doesn't get crushed */
        flex-shrink: 0;
        min-width: max-content;
    }

    .timeline-commit-info {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        /* Allow more space for author name on mobile */
        max-width: none;
        flex: 1;
        /* Better truncation: show as much as possible */
        min-width: 0;
        /* Truncate with ellipsis */
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Date row needs proper flex layout for truncation */
    .timeline-date-row {
        min-width: 0;
        /* Ensure proper truncation behavior */
        display: flex;
        overflow: hidden;
    }

    /* -------------------------------------------------------------------------
       Mobile Slider Thumb - Larger Touch Target
       -------------------------------------------------------------------------
       WCAG 2.5.5 requires 44x44px minimum touch targets.
       Slider thumb expanded with visible indicator + larger touch area.
    */

    .timeline-slider {
        height: 8px;
        border-radius: 4px;
        /* Increase vertical touch area */
        padding: 12px 0;
        margin: -12px 0;
        background-clip: content-box;
    }

    .timeline-slider::-webkit-slider-thumb {
        width: 24px;
        height: 24px;
        /* Create larger invisible touch area with box-shadow */
        box-shadow: 0 0 0 10px transparent, 0 2px 6px rgba(233, 69, 96, 0.4);
        cursor: pointer;
        /* iOS-style: slightly larger visual indicator */
        border: 2px solid rgba(255, 255, 255, 0.9);
    }

    .timeline-slider::-webkit-slider-thumb:active {
        transform: scale(1.15);
        box-shadow: 0 0 0 10px rgba(233, 69, 96, 0.15), 0 2px 8px rgba(233, 69, 96, 0.5);
    }

    .timeline-slider::-moz-range-thumb {
        width: 24px;
        height: 24px;
        border: 2px solid rgba(255, 255, 255, 0.9);
        cursor: pointer;
    }

    .timeline-slider::-moz-range-thumb:active {
        transform: scale(1.15);
    }

    /* Slider container needs more height for larger thumb */
    .timeline-slider-container {
        height: 32px;
    }

    .play-btn-main {
        width: 44px;
        height: 44px;
    }

    .play-btn-main svg {
        width: 20px;
        height: 20px;
    }

    .timeline-btn {
        width: 36px;
        height: 36px;
    }

    /* A1: hide the "Speed:" label visually, but keep it in the accessibility
     * tree. `display: none` removes a <label for> from the accessible name
     * computation entirely, which left #speed-select with no accessible name
     * on mobile (axe `select-name`, critical). Clipping preserves the
     * for/id association without occupying layout. */
    .speed-control label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    /* Speed select: optimized for mobile to prevent truncation */
    /* A5: Increased touch target for dropdown trigger */
    .speed-control select {
        font-size: 0.8125rem; /* 13px for better readability */
        padding: 0.5rem 0.75rem;
        padding-right: 24px;
        min-height: 44px; /* Apple HIG minimum touch target */
        min-width: 90px;
        max-width: 120px;
        /* Ensure dropdown arrow has space */
        background-position: right 6px center;
        border-radius: 8px;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    /* Timeline controls row: allow wrapping on very narrow screens */
    .timeline-controls-row {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* Timeline info: more compact on mobile */
    .timeline-info {
        min-width: 70px;
        font-size: 0.75rem;
    }

    .timeline-info-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* Mobile thumb is 24px, so marker offset = 24/2 = 12px */
    .timeline-slider-container {
        --thumb-size: 24px;
    }
}

/* Extra small screens: further optimize timeline */
@media (max-width: 375px) {
    .timeline-container {
        padding: 0.4rem;
        gap: 0.35rem;
    }

    .timeline-date {
        font-size: 0.8rem;
    }

    .timeline-commit-info {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        /* Still use flexible width */
        flex: 1;
        min-width: 0;
    }

    /* Stack date row elements more tightly */
    .timeline-date-row {
        gap: 0.4rem;
    }

    /* Slider thumb slightly smaller on tiny screens but still touch-friendly */
    .timeline-slider::-webkit-slider-thumb {
        width: 22px;
        height: 22px;
    }

    .timeline-slider::-moz-range-thumb {
        width: 22px;
        height: 22px;
    }

    /* 375px thumb is 22px, so marker offset = 22/2 = 11px */
    .timeline-slider-container {
        --thumb-size: 22px;
    }

    .play-btn-main {
        width: 40px;
        height: 40px;
    }

    .play-btn-main svg {
        width: 18px;
        height: 18px;
    }

    .timeline-btn {
        width: 32px;
        height: 32px;
    }

    .reset-btn {
        width: 36px;
        height: 36px;
    }

    .timeline-info {
        min-width: 60px;
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* A5: Maintain touch target on smaller screens */
    .speed-control select {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        padding: 0.4rem 0.5rem;
        padding-right: 20px;
        min-height: 44px; /* Maintain touch target */
        min-width: 80px;
        max-width: 100px;
    }

    /* Date labels - maintain readable size even on tiny screens */
    .timeline-date-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        min-width: 45px;
    }
}

/* =============================================================================
   Short Viewport Optimizations (ultrawide monitors, resized windows)
   ============================================================================= */

/* Compact timeline when viewport height is constrained */
@media (max-height: 500px) {
    .timeline-container {
        padding: 0.4rem 0.75rem;
        gap: 0.3rem;
        min-height: auto;
    }

    .timeline-date-row {
        gap: 0.4rem;
    }

    .timeline-date {
        font-size: 0.8rem;
    }

    .timeline-commit-info {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    .play-btn-main {
        width: 32px;
        height: 32px;
    }

    .play-btn-main svg {
        width: 14px;
        height: 14px;
    }

    .timeline-btn {
        width: 24px;
        height: 24px;
    }

    .reset-btn {
        width: 28px;
        height: 28px;
    }

    .timeline-info {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }
}

/* Very short viewports - minimal timeline */
@media (max-height: 400px) {
    .timeline-container {
        padding: 0.25rem 0.5rem;
        gap: 0.2rem;
    }

    /* Hide the date row to save vertical space */
    .timeline-date-row {
        display: none;
    }

    /* Hide slider date labels */
    .timeline-date-label {
        display: none;
    }

    .play-btn-main {
        width: 28px;
        height: 28px;
    }

    .play-btn-main svg {
        width: 12px;
        height: 12px;
    }

    .timeline-btn {
        width: 22px;
        height: 22px;
    }

    .reset-btn {
        width: 24px;
        height: 24px;
    }

    /* A5: Touch target maintained on smallest screens */
    .speed-control select {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        padding: 0.3rem 0.4rem;
        padding-right: 18px;
        min-height: 40px; /* Slightly reduced but still accessible */
    }

    .timeline-info {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        min-width: 50px;
    }
}

/* =============================================================================
   Timeline Slider Container (with markers)
   ============================================================================= */

.timeline-slider-container {
    position: relative;
    flex: 1;
    height: 20px;
    display: flex;
    align-items: center;
    overflow: visible;
    /* Thumb size token: markers offset = thumb-size / 2 so ticks align with thumb center.
       Must match the actual slider thumb width at each breakpoint. */
    --thumb-size: 16px;
}

.timeline-slider-container .timeline-slider {
    position: relative;
    z-index: 2;
    width: 100%;
}

.timeline-slider-container .timeline-markers {
    position: absolute;
    top: 50%;
    /* Derive offset from thumb size so ticks always align with slider positions */
    left: calc(var(--thumb-size) / 2);
    right: calc(var(--thumb-size) / 2);
    height: 24px;
    transform: translateY(-50%);
    pointer-events: none;
    z-index: 3;
    overflow: visible;
}

/* =============================================================================
   Timeline Markers
   ============================================================================= */

.timeline-markers {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
}

.timeline-marker {
    position: absolute;
    width: 2px;
    height: 100%;
    background: var(--accent);
    opacity: 0.6;
    transform: translateX(-50%);
}

.timeline-marker.merge {
    background: var(--accent-blue);
}

.timeline-marker.large {
    background: var(--warning);
}

.timeline-slider-container .timeline-marker {
    position: absolute;
    width: 3px;
    height: 12px;
    border-radius: 1px;
    transform: translateX(-50%);
    opacity: 0.7;
}

.timeline-marker.large-commit {
    background: var(--warning);
    height: 16px;
}

.timeline-marker.first-commit {
    background: var(--success);
    height: 14px;
}

.timeline-marker.recent-commit {
    background: var(--accent-blue);
    height: 14px;
}

/* =============================================================================
   Timeline Date Ticks
   ============================================================================= */

.timeline-tick {
    position: absolute;
    width: 2px;
    transform: translateX(-50%);
    transform-origin: bottom center;
    bottom: 4px;
    opacity: 0;
    /* Use transform instead of height for GPU-accelerated animation */
    transition: opacity 0.3s ease-out, transform 0.2s ease-out;
    pointer-events: auto;
    cursor: pointer;
    border-radius: 1px;
}

.timeline-tick.visible {
    opacity: 1;
}

/* Height variants - using CSS custom properties for transform-based hover */
.timeline-tick.tick-minor {
    --tick-height: 10px;
    --tick-hover-scale: 2;  /* 10px → 20px */
    height: var(--tick-height);
    background: var(--text-muted);
    opacity: 0;
}

.timeline-tick.tick-minor.visible {
    opacity: 0.5;
}

.timeline-tick.tick-medium {
    --tick-height: 14px;
    --tick-hover-scale: 1.43;  /* 14px → 20px */
    height: var(--tick-height);
    background: var(--text-secondary);
    opacity: 0;
    width: 2px;
}

.timeline-tick.tick-medium.visible {
    opacity: 0.7;
}

.timeline-tick.tick-major {
    --tick-height: 18px;
    --tick-hover-scale: 1.11;  /* 18px → 20px */
    height: var(--tick-height);
    background: var(--text-primary);
    width: 2px;
    border-radius: 1px;
    opacity: 0;
}

.timeline-tick.tick-major.visible {
    opacity: 0.85;
}

/* Interval-specific colors */
.timeline-tick.tick-day {
    background: var(--accent-blue);
}

.timeline-tick.tick-week {
    background: var(--accent-purple);
}

.timeline-tick.tick-month {
    background: var(--accent);
}

.timeline-tick.tick-quarter {
    background: var(--success);
}

.timeline-tick.tick-year {
    background: var(--warning);
}

/* Major tick override for all types */
.timeline-tick.tick-major.tick-day,
.timeline-tick.tick-major.tick-week,
.timeline-tick.tick-major.tick-month,
.timeline-tick.tick-major.tick-quarter {
    background: var(--warning);
}

/* Hover effect with tooltip enhancement - uses GPU-accelerated transform */
.timeline-tick:hover {
    opacity: 1;
    transform: translateX(-50%) scaleY(var(--tick-hover-scale, 1.5));
    z-index: 20;
    background: var(--accent);
}

/* Custom tooltip via CSS pseudo-element */
.timeline-tick::after {
    content: attr(data-label);
    position: absolute;
    bottom: calc(100% + 18px);
    left: 50%;
    transform: translateX(-50%) scale(0.9);
    background: var(--bg-tertiary);
    color: var(--text-primary);
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    font-weight: 500;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease-out, transform 0.15s ease-out;
    border: 1px solid var(--border);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
    z-index: 100;
}

.timeline-tick:hover::after {
    opacity: 1;
    transform: translateX(-50%) scale(1);
}

/* Date label above tick for major ticks */
.timeline-tick-label {
    position: absolute;
    bottom: calc(100% + 2px);
    left: 50%;
    transform: translateX(-50%);
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-secondary);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0.9;
    font-weight: 500;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

/* Hide labels on hover so tooltip takes over */
.timeline-tick:hover .timeline-tick-label {
    opacity: 0;
}

/* Label visibility on minor ticks is controlled by JS selectLabeledTicks().
   JS only creates label elements when spacing is sufficient, so no CSS override needed. */


/* ---- styles/sections/overlays.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Overlay Styles
 *
 * Canvas overlays including legend panel, stats overlay,
 * and performance overlay with FPS toggle switch.
 */

/* =============================================================================
   Legend Panel
   ============================================================================= */

.legend-panel {
    position: absolute;
    top: 10px;
    right: 10px;
    background: rgba(22, 27, 34, 0.95);
    border-radius: 8px;
    padding: 0.75rem;
    max-width: 180px;
    max-height: 280px;
    min-height: 32px; /* Reserve minimum height to reduce CLS */
    overflow-y: auto;
    z-index: var(--z-canvas-overlays);
    backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    font-size: 0.75rem;
    /* Contain layout to prevent CLS when toggling collapsed state */
    contain: layout style;
    /* Firefox scrollbar styling */
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

.legend-panel.collapsed {
    /* Must clear the header's 44px target height (see accessibility.css,
       "Target Size"). At the previous 32px the header was clipped. */
    max-height: 44px;
    overflow: hidden;
}

.legend-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    margin-bottom: 0.5rem;
    border-radius: 4px;
}

/* Accessibility: Focus indicator for keyboard navigation */
.legend-header:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.legend-header .legend-title {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.legend-toggle {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    transition: transform 0.2s;
}

.legend-panel.collapsed .legend-toggle {
    transform: rotate(180deg);
}

.legend-items {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.legend-color {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.legend-ext {
    color: var(--text-secondary);
    flex: 1;
    /* Flex items are min-width:auto by default, so an unusually long extension
       would widen the row past the panel instead of truncating. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.legend-count {
    color: var(--text-muted);
    font-size: 0.75rem;
    flex-shrink: 0;
    /* Counts change every frame; tabular figures stop the column shifting
       width as digits change. */
    font-variant-numeric: tabular-nums;
}

.author-commits {
    font-variant-numeric: tabular-nums;
}

/* -----------------------------------------------------------------------------
   Legend Structure Section (directories explanation)
   ----------------------------------------------------------------------------- */

.legend-structure {
    margin-top: 0.5rem;
}

.legend-divider {
    height: 1px;
    background: var(--border);
    margin-bottom: 0.5rem;
    opacity: 0.5;
}

.legend-item-structure {
    cursor: help;
}

.legend-item-structure:hover {
    background: var(--bg-tertiary);
    border-radius: 4px;
    margin: -0.15rem;
    padding: 0.15rem;
}

.legend-structure-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* =============================================================================
   Stats Overlay
   ============================================================================= */

.stats-overlay {
    position: absolute;
    bottom: 10px;
    left: 10px;
    background: rgba(22, 27, 34, 0.9);
    border-radius: 6px;
    padding: 0.5rem 0.75rem;
    backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    display: flex;
    gap: 1rem;
    font-size: 0.75rem;
    z-index: var(--z-canvas-overlays); /* Ensure stats overlay is above canvas for tooltip hover */
}

/* Stats with tooltips should show help cursor */
.stat-item[title] {
    cursor: help;
}

.stat-value {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.stat-label {
    color: var(--text-muted);
    font-size: 0.75rem; /* 12px minimum - WCAG compliance */
    text-transform: uppercase;
}

/* Repository total shown after the live count, e.g. "162 / 5,673".
   Muted and lighter so the on-screen figure stays the one you read first. */
.stat-total {
    color: var(--text-muted);
    font-size: 0.75rem;
    font-weight: 400;
    font-variant-numeric: tabular-nums;
}

/* Grid rather than a column flex: the live value and its total need to share
   one line, with the label centred beneath both. */
.stat-item {
    display: grid;
    grid-template-areas:
        "value total"
        "label label";
    justify-items: center;
    align-items: baseline;
    column-gap: 0.2rem;
}

.stat-value { grid-area: value; }
.stat-total { grid-area: total; }
.stat-label { grid-area: label; }

/* =============================================================================
   Performance Overlay (FPS, metrics)
   ============================================================================= */

.perf-overlay {
    position: absolute;
    top: 10px;
    left: 10px;
    background: rgba(13, 17, 23, 0.92);
    border-radius: 6px;
    padding: 0.5rem 0.75rem;
    backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    min-width: 140px;
    z-index: var(--z-canvas-perf);
}

.perf-overlay.collapsed {
    min-width: auto;
}

.perf-overlay.collapsed .perf-details {
    display: none;
}

.perf-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    margin-bottom: 0.4rem;
    border-radius: 4px;
}

/* Accessibility: Focus indicator for keyboard navigation */
.perf-header:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.perf-overlay.collapsed .perf-header {
    margin-bottom: 0;
}

/* -----------------------------------------------------------------------------
   FPS Display
   ----------------------------------------------------------------------------- */

.perf-fps {
    font-weight: 700;
    font-size: 0.85rem;
}

.perf-fps.good { color: var(--success); }
.perf-fps.ok { color: var(--warning); }
.perf-fps.bad { color: var(--error); }
.perf-fps.paused { color: var(--text-secondary); }
.perf-fps.complete { color: var(--accent-blue); }
.perf-fps.uncapped { color: var(--accent-orange); } /* Orange for uncapped mode */

/* -----------------------------------------------------------------------------
   Peak FPS Badge (visible in header when uncapped mode is active)
   ----------------------------------------------------------------------------- */

.perf-peak-badge {
    display: none; /* Hidden by default */
    align-items: center;
    gap: 4px;
    margin-left: 8px;
    padding: 2px 6px;
    background: rgba(255, 215, 0, 0.15);
    border: 1px solid rgba(255, 215, 0, 0.3);
    border-radius: 8px;
    font-size: 0.75rem; /* 12px - WCAG minimum */
}

.perf-peak-badge:not(.hidden) {
    display: inline-flex;
}

.perf-peak-label {
    color: rgba(255, 255, 255, 0.6);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.perf-peak-value {
    color: #ffd700; /* Gold for peak/high score */
    font-weight: 700;
    text-shadow: 0 0 4px rgba(255, 215, 0, 0.4);
}

/* New record animation */
.perf-peak-badge.new-record .perf-peak-value {
    animation: peak-pulse 0.6s ease-out;
}

@keyframes peak-pulse {
    0% { transform: scale(1); }
    50% { transform: scale(1.2); text-shadow: 0 0 8px rgba(255, 215, 0, 0.8); }
    100% { transform: scale(1); }
}

/* -----------------------------------------------------------------------------
   Toggle Switch (for uncapped FPS)
   ----------------------------------------------------------------------------- */

.perf-toggle-row {
    margin-top: 0.3rem;
    padding-top: 0.3rem;
    border-top: 1px solid var(--border);
}

.perf-switch {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 18px;
}

.perf-switch input {
    position: absolute;
    opacity: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    cursor: pointer;
    z-index: 1;
}

.perf-slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: var(--bg-tertiary);
    border-radius: 18px;
    transition: 0.2s;
}

.perf-slider::before {
    position: absolute;
    content: "";
    height: 12px;
    width: 12px;
    left: 3px;
    bottom: 3px;
    background-color: var(--text-muted);
    border-radius: 50%;
    transition: 0.2s;
}

.perf-switch input:checked + .perf-slider {
    background-color: var(--accent-orange);
}

.perf-switch input:checked + .perf-slider::before {
    transform: translateX(14px);
    background-color: var(--text-on-accent);
}

.perf-switch input:focus-visible + .perf-slider {
    /* Fallback for browsers without color-mix() */
    box-shadow: 0 0 0 2px rgba(255, 107, 53, 0.3);
}

@supports (background: color-mix(in srgb, red 50%, blue)) {
    .perf-switch input:focus-visible + .perf-slider {
        box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-orange) 30%, transparent);
    }
}

.perf-toggle {
    color: var(--text-muted);
    font-size: 0.75rem; /* 12px - WCAG minimum */
    transition: transform 0.2s;
}

.perf-overlay.collapsed .perf-toggle {
    transform: rotate(180deg);
}

/* -----------------------------------------------------------------------------
   Performance Details
   ----------------------------------------------------------------------------- */

.perf-details {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    border-top: 1px solid var(--border);
    padding-top: 0.4rem;
}

.perf-row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
}

.perf-label {
    color: var(--text-muted);
}

.perf-value {
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* Peak/Avg FPS row - shown only in uncapped mode */
.perf-peak-avg-row {
    transition: opacity 0.2s ease, max-height 0.2s ease;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
}

.perf-peak-avg-row:not(.hidden) {
    max-height: 2rem;
    opacity: 1;
}

.perf-peak-avg-value {
    color: var(--accent);
    font-weight: 500;
}

.perf-peak-avg-value span:first-child {
    color: var(--success);
}

/* -----------------------------------------------------------------------------
   Backend Indicator
   ----------------------------------------------------------------------------- */

/* Color coding - deterministic from WASM */
.perf-backend {
    font-weight: 600;
    padding: 0.1rem 0.4rem;
    border-radius: 3px;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

/* GPU-accelerated backends (green) */
.perf-backend[data-gpu-accelerated="true"] {
    background: rgba(63, 185, 80, 0.2);
    color: var(--success);
}

/* CPU/Software backend (amber) */
.perf-backend[data-gpu-accelerated="false"]:not([data-backend="unknown"]) {
    background: rgba(210, 153, 34, 0.2);
    color: var(--warning);
}

/* Unknown state (muted) */
.perf-backend[data-backend="unknown"] {
    background: rgba(132, 141, 151, 0.2);
    color: var(--text-muted);
}

/* =============================================================================
   Authors Panel
   ============================================================================= */

.authors-panel {
    position: absolute;
    bottom: 10px;
    right: 10px;
    background: rgba(22, 27, 34, 0.95);
    border-radius: 8px;
    padding: 0.75rem;
    max-width: 180px;
    max-height: 220px;
    overflow-y: auto;
    z-index: var(--z-canvas-overlays);
    backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    font-size: 0.75rem;
    /* Firefox scrollbar styling */
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

.authors-panel.collapsed {
    /* Must clear the header's 44px target height (see accessibility.css,
       "Target Size"). At the previous 32px the header was clipped. */
    max-height: 44px;
    overflow: hidden;
}

.authors-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    margin-bottom: 0.5rem;
    border-radius: 4px;
}

/* Accessibility: Focus indicator for keyboard navigation */
.authors-header:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.authors-header .authors-title {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.authors-toggle {
    font-size: 0.75rem; /* 12px - WCAG minimum */
    color: var(--text-muted);
    transition: transform 0.2s;
}

.authors-panel.collapsed .authors-toggle {
    transform: rotate(180deg);
}

.authors-items {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    /* Flex items are min-width:auto by default, which resolves to min-content
       and lets a long author name push the column wider than the panel. */
    min-width: 0;
}

/* The rendered markup (main-data-handlers.js) uses `.author-item` as the row
   container; the flex layout below previously targeted a `.author-row` class
   that appeared in no template. Without a flex parent, `.author-name`'s
   `flex: 1` was inert and its ellipsis could never engage on an inline box, so
   long names such as `Sebastian "Sebbie" Silbermann` wrapped and overflowed
   the panel's right edge. */
.author-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.author-color {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.author-name {
    color: var(--text-secondary);
    flex: 1;
    /* Required alongside `flex: 1`: without it the item's automatic minimum
       size keeps the box at min-content width and the ellipsis never applies. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.author-commits {
    color: var(--text-muted);
    font-size: 0.75rem; /* 12px - WCAG minimum */
    flex-shrink: 0;
}

/* =============================================================================
   Live Legend
   -----------------------------------------------------------------------------
   The File Types and Authors panels track the scene frame by frame, so rows
   appear, re-sort and re-count while playback runs. These rules make that
   readable: a brief tint marks a count that just changed, so the eye can follow
   which type or contributor is moving without the list appearing to jitter on
   its own.
   ============================================================================= */

@keyframes legend-row-pulse {
    from { background-color: color-mix(in srgb, var(--accent) 22%, transparent); }
    to   { background-color: transparent; }
}

.legend-row-changed {
    animation: legend-row-pulse 600ms ease-out;
    border-radius: 4px;
}

/* Contributors with a user still present in the scene. The dimming is applied
   to everyone else rather than brightening the active few, so the panel does
   not flash as users fade in and out between commits. */
.author-item:not(.author-item-active) .author-name,
.author-item:not(.author-item-active) .author-commits {
    opacity: 0.62;
}

.author-item-active .author-name {
    color: var(--text-interactive, var(--text-primary));
}

/* Footer noting rows the panel is not showing. Both lists cap their length;
   without this the list simply stopped, giving no hint more existed. */
.legend-summary {
    margin-top: 0.4rem;
    padding-top: 0.35rem;
    border-top: 1px solid var(--border);
    color: var(--text-muted);
    font-size: 0.6875rem; /* 11px - supporting metadata, not body copy */
    text-align: right;
}

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


/* ---- styles/sections/help.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Help Overlay Styles
 *
 * Full-screen help overlay with keyboard shortcuts and feature documentation.
 */

/* =============================================================================
   Help Overlay Container
   ============================================================================= */

.help-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.9);
    z-index: var(--z-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    /* Hidden by default - JS adds 'visible' class to show */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, visibility 0.2s;
    backdrop-filter: blur(4px);
}

.help-overlay.visible {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* =============================================================================
   Help Content Container
   ============================================================================= */

.help-content {
    background: var(--bg-secondary);
    border-radius: 12px;
    padding: 2rem;
    max-width: 600px;
    width: 90%;
    max-height: 85vh;
    max-height: 85dvh; /* Dynamic viewport for mobile */
    overflow-y: auto;
    border: 1px solid var(--border);
    position: relative;
    /* Firefox scrollbar styling */
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

.help-content h2 {
    font-size: 1.5rem;
    margin-bottom: 1.5rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.help-content h2 svg {
    color: var(--accent);
}

/* =============================================================================
   Help Sections
   ============================================================================= */

.help-section {
    margin-bottom: 1.5rem;
}

.help-section:last-child {
    margin-bottom: 0;
}

.help-section h3 {
    font-size: 1rem;
    margin-bottom: 0.75rem;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.help-section h3 svg {
    color: var(--accent-blue);
    width: 16px;
    height: 16px;
}

/* =============================================================================
   Keyboard Shortcuts Grid
   ============================================================================= */

.help-shortcuts {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.5rem 1rem;
}

.help-key {
    background: var(--bg-tertiary);
    padding: 0.25rem 0.6rem;
    border-radius: 4px;
    font-family: 'SF Mono', 'Monaco', monospace;
    font-size: 0.8rem;
    color: var(--text-secondary);
    border: 1px solid var(--border);
    text-align: center;
    min-width: 2em;
}

.help-desc {
    color: var(--text-secondary);
    font-size: 0.85rem;
    display: flex;
    align-items: center;
}

/* =============================================================================
   Help Button
   ============================================================================= */

.help-btn {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 32px;
    height: 32px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, transform 0.2s;
    font-size: 0.9rem;
    font-weight: 600;
}

.help-btn:hover {
    background: var(--border);
    color: var(--text-primary);
}

.help-btn:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* =============================================================================
   Close Help Button
   ============================================================================= */

.help-close {
    position: absolute;
    top: 1rem;
    right: 1rem;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 32px;
    height: 32px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.2s, transform 0.2s;
    font-size: 1.25rem;
    line-height: 1;
}

.help-close:hover {
    background: var(--border);
    color: var(--text-primary);
}

.help-close:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* =============================================================================
   Help "Got it!" Button
   ============================================================================= */

.help-got-it-btn {
    width: 100%;
    margin-top: 1rem;
}

/* =============================================================================
   Help Footer
   ============================================================================= */

.help-footer {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
    text-align: center;
    color: var(--text-muted);
    font-size: 0.8rem;
}

.help-footer kbd {
    background: var(--bg-tertiary);
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    font-family: 'SF Mono', 'Monaco', monospace;
    font-size: 0.75rem;
    border: 1px solid var(--border);
}

/* =============================================================================
   Keyboard Key Styling (used in keyboard shortcuts table)
   ============================================================================= */

.kbd {
    display: inline-block;
    background: var(--bg-tertiary);
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    font-family: 'SF Mono', 'Monaco', 'Cascadia Code', monospace;
    font-size: 0.75rem;
    border: 1px solid var(--border);
    box-shadow: inset 0 -1px 0 var(--border-light);
    color: var(--text-secondary);
    min-width: 1.5em;
    text-align: center;
    vertical-align: middle;
    margin-right: 0.1rem;
}

/* =============================================================================
   Visual Elements Section (Welcome Modal)
   ============================================================================= */

.help-visual {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-top: 0.75rem;
}

.help-item {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.5rem;
    background: var(--bg-tertiary);
    border-radius: 8px;
    border: 1px solid var(--border);
}

.help-item-icon {
    /* CRITICAL: Fixed size for visual element icons */
    width: 48px;
    height: 48px;
    min-width: 48px;
    min-height: 48px;
    flex-shrink: 0;
}

.help-item-text {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.help-item-text strong {
    font-size: 0.9rem;
    color: var(--text-primary);
}

.help-item-text span {
    font-size: 0.8rem;
    color: var(--text-secondary);
}

/* =============================================================================
   Help Section Body Text and Lists
   ============================================================================= */

.help-section-body {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.6;
}

.help-section-note {
    color: var(--text-muted);
    font-size: 0.8rem;
    line-height: 1.5;
    margin-top: 0.5rem;
}

.help-section-list {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.8;
    padding-left: 1.25rem;
}

/* =============================================================================
   Help Shortcuts Grid (Categorized)
   ============================================================================= */

.help-shortcuts-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.5rem 1.5rem;
    color: var(--text-secondary);
    font-size: 0.85rem;
}

.help-shortcuts-category {
    font-weight: 600;
    color: var(--text-primary);
    grid-column: 1 / -1;
    margin-top: 0.5rem;
    border-bottom: 1px solid var(--border);
    padding-bottom: 0.25rem;
}

.help-shortcuts-muted {
    color: var(--text-muted);
    font-size: 0.75rem;
}

/* =============================================================================
   Responsive Adjustments
   ============================================================================= */

@media (max-width: 768px) {
    .help-content {
        padding: 1.5rem;
        max-height: 80vh;
        max-height: 80dvh;
    }

    .help-content h2 {
        font-size: 1.25rem;
    }

    .help-section h3 {
        font-size: 0.9rem;
    }

    .help-shortcuts {
        gap: 0.4rem 0.75rem;
    }

    .help-key {
        padding: 0.2rem 0.4rem;
        font-size: 0.75rem;
    }

    .help-desc {
        font-size: 0.8rem;
    }

    /* Mobile: Slightly smaller visual element icons */
    .help-item {
        gap: 0.75rem;
        padding: 0.4rem;
    }

    .help-item-icon {
        width: 40px;
        height: 40px;
        min-width: 40px;
        min-height: 40px;
    }

    .help-item-text strong {
        font-size: 0.85rem;
    }

    .help-item-text span {
        font-size: 0.75rem;
    }
}


/* ---- styles/sections/footer.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Footer Section Styles
 *
 * Page footer with copyright and links.
 */

/* =============================================================================
   Footer
   ============================================================================= */

footer {
    background: var(--bg-secondary);
    padding: 0.75rem 1rem;
    text-align: center;
    border-top: 1px solid var(--border);
    font-size: 0.75rem;
    color: var(--text-muted);
}

footer a {
    color: var(--accent-blue);
    /* Underlined, not colour-only: --accent-blue against the surrounding
       --text-muted is 1.21:1, far below the 3:1 that WCAG 1.4.1 requires
       when colour is the sole distinction (axe `link-in-text-block`). */
    text-decoration: underline;
    text-underline-offset: 2px;
    transition: color 0.2s;
}

footer a:hover {
    color: var(--accent);
    text-decoration: underline;
}

footer p {
    margin: 0;
    line-height: 1.5;
}

/* Separator between footer items */
footer .separator {
    margin: 0 0.5rem;
    opacity: 0.5;
}

/* =============================================================================
   Responsive Adjustments
   ============================================================================= */

@media (max-width: 768px) {
    footer {
        padding: 0.5rem 0.75rem;
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }
}

/* -----------------------------------------------------------------------------
   Short Viewport Optimizations
   ----------------------------------------------------------------------------- */

/* On very short viewports (ultrawide, resized windows), minimize footer */
@media (max-height: 500px) {
    footer {
        padding: 0.35rem 0.75rem;
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }
}

/* On extremely short viewports, hide footer entirely to prioritize content */
@media (max-height: 400px) {
    footer {
        display: none;
    }
}

/* Mobile landscape: Hide footer to maximize vertical canvas space */
@media (max-width: 768px) and (orientation: landscape) {
    footer {
        display: none;
    }
}

/* Hide footer in fullscreen */
:fullscreen footer,
:-webkit-full-screen footer,
.pseudo-fullscreen footer {
    display: none;
}

/* =============================================================================
   Features
   ============================================================================= */

/* Keyframe animations (after components to ensure correct cascade) */

/* ---- styles/features/animations.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Animation Styles
 *
 * Keyframe animations used across the application.
 * Component-specific animations may be defined in their respective modules:
 * - bounce: sidebar.css (scroll indicator)
 * - modalSlideIn: modals.css (modal entrance)
 *
 * This file contains shared/reusable animations.
 */

/* =============================================================================
   Loading Animations
   ============================================================================= */

/* Spin animation for loading spinners */
@keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* Utility class for spin animation */
.spin {
    animation: spin 1s linear infinite;
}

/* Shimmer effect for skeleton loading */
@keyframes shimmer {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

/* =============================================================================
   Pulse Animations
   ============================================================================= */

/* Generic pulse animation */
@keyframes pulse {
    0%, 100% { opacity: 0.2; transform: translate(-50%, -50%) scale(1); }
    50% { opacity: 0.5; transform: translate(-50%, -50%) scale(1.1); }
}

/* Beam pulse for skeleton visualization */
@keyframes beam-pulse {
    0%, 100% { opacity: 0.1; }
    50% { opacity: 0.4; }
}

/* =============================================================================
   Recording Animations
   ============================================================================= */

/* Recording indicator pulse */
@keyframes recordingPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.6; }
}

/* Recording dot scale animation */
@keyframes recordingDot {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.3); }
}

/* Preparing state pulse (faster) */
@keyframes preparingPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

/* =============================================================================
   Timeline Animations
   ============================================================================= */

/* Stagger animation for tick appearance */
@keyframes tickFadeIn {
    from {
        opacity: 0;
        transform: translateX(-50%) scaleY(0);
    }
    to {
        opacity: 1;
        transform: translateX(-50%) scaleY(1);
    }
}

/* Timeline tick visibility with animation */
.timeline-tick.visible {
    animation: tickFadeIn 0.25s ease-out forwards;
    transform-origin: bottom center;
}

/* =============================================================================
   Touch Feedback Animations (Haptic-like visual feedback)
   ============================================================================= */

/* Spring-based press feedback (iOS-like) */
@keyframes touchPress {
    0% { transform: scale(1); }
    50% { transform: scale(0.95); }
    100% { transform: scale(1); }
}

/* Ripple effect for button taps */
@keyframes ripple {
    0% {
        transform: scale(0);
        opacity: 0.5;
    }
    100% {
        transform: scale(4);
        opacity: 0;
    }
}

/* Bounce feedback after release (spring-like) */
@keyframes touchBounce {
    0% { transform: scale(0.92); }
    40% { transform: scale(1.02); }
    70% { transform: scale(0.98); }
    100% { transform: scale(1); }
}

/* Success feedback pulse */
@keyframes successPulse {
    0% { box-shadow: 0 0 0 0 rgba(63, 185, 80, 0.4); }
    70% { box-shadow: 0 0 0 10px rgba(63, 185, 80, 0); }
    100% { box-shadow: 0 0 0 0 rgba(63, 185, 80, 0); }
}

/* Error shake feedback */
@keyframes errorShake {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-4px); }
    40% { transform: translateX(4px); }
    60% { transform: translateX(-4px); }
    80% { transform: translateX(4px); }
}

/* Utility classes for touch feedback */
.touch-press {
    animation: touchPress 0.15s ease-out;
}

.touch-bounce {
    animation: touchBounce 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.touch-success {
    animation: successPulse 0.6s ease-out;
}

.touch-error {
    animation: errorShake 0.4s ease-out;
}

/* Mobile-specific touch feedback enhancements */
@media (max-width: 768px), (pointer: coarse) {
    /* Enhance active states with spring-like behavior */
    button:active:not(:disabled),
    .btn:active:not(:disabled),
    .bottom-sheet-action-btn:active:not(:disabled),
    .mobile-toolbar-btn:active:not(:disabled) {
        animation: touchPress 0.1s ease-out forwards;
    }

    /* Add subtle glow on touch for important buttons */
    .play-btn-main:active {
        box-shadow: 0 0 0 8px rgba(233, 69, 96, 0.2);
    }

    /* FAB touch feedback */
    .bottom-sheet-fab:active {
        box-shadow: 0 0 0 8px rgba(233, 69, 96, 0.2), 0 4px 12px rgba(233, 69, 96, 0.4);
    }
}

/* Theme support (light theme variables and overrides) */

/* ---- styles/features/themes.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Theme Styles
 *
 * Light theme support and theme toggle component.
 * Dark theme is the default (defined in variables.css).
 *
 * Theme switching:
 * - Automatic via prefers-color-scheme media query
 * - Manual via .light-theme class on :root
 */

/* =============================================================================
   Light Theme Variables
   ============================================================================= */

:root.light-theme {
    /* Background Colors - Slightly warmer/darker for better depth
     * Using off-white and cream tones instead of pure white reduces
     * eye strain and creates better visual hierarchy */
    --bg-primary: #fafbfc;           /* Soft off-white instead of pure white */
    --bg-secondary: #f0f2f5;         /* Warmer light gray */
    --bg-tertiary: #e4e8ec;          /* Slightly darker for depth */
    --bg-canvas: #dce0e5;            /* Darker canvas for visualization contrast */

    /* Text Colors */
    --text-primary: #1f2328;
    --text-secondary: #4d5561; /* WCAG AA: 5.7:1 contrast on white */
    --text-interactive: #32383f; /* ~8.5:1 contrast - for tabs, chips, nav items */
    --text-muted: #656d76; /* WCAG AA: 4.5:1 contrast on white */
    --text-on-accent: #ffffff; /* Same as dark theme - white on accent */

    /* Border Colors - Slightly darker for definition */
    --border: #c5cdd5;
    --border-light: #9da5ae;

    /* Shadows & Overlays - More prominent for visual hierarchy */
    --shadow: rgba(31, 35, 40, 0.18);
    --backdrop: rgba(31, 35, 40, 0.35);
    --backdrop-blur: rgba(31, 35, 40, 0.75);

    /* Accent Colors - adjusted for light backgrounds
     * These maintain WCAG AA contrast on light backgrounds */
    /* On a light theme one value *can* serve both roles: dark enough for white
     * text (5.67:1) and dark enough as text on the light surfaces (4.60:1 on
     * the tertiary surface, the binding case). --accent-surface is defined
     * anyway so component rules can name the role rather than the theme. */
    --accent: #bf2d50;         /* 4.60:1 as text on bg-tertiary */
    --accent-surface: #bf2d50; /* 5.67:1 with white text */
    --accent-hover: #a52645;   /* 7.09:1 with white text */
    --accent-light: #ff9a9e;
    --accent-secondary: #1a7f37; /* Darker green for contrast */
    --accent-secondary-hover: #238636;
    --accent-blue: #0753ab;       /* 4.61:1 as text on --border, the darkest surface it lands on */
    --accent-blue-light: #1867bc; /* 4.60:1 as text on bg-tertiary */
    --accent-purple: #8250df;
    --accent-orange: #ba5a09;     /* 4.61:1 with white text */

    /* Surface variants — see variables.css for why these are separate.
     * The light theme's semantic colours are already dark, so most double as
     * their own surface; white text is readable on all of them here. */
    --accent-blue-surface: #0969da;        /* 5.19:1 with white text */
    --accent-blue-surface-hover: #0753ab;  /* 7.41:1 with white text */
    --error-surface: #cf222e;              /* 5.36:1 with white text */
    --warning-surface: #956300;            /* 5.17:1 with --text-on-warning */
    --accent-orange-surface: #ba5a09;      /* 4.61:1 with --text-on-warning */
    --text-on-warning: #ffffff;            /* light theme ambers are dark enough for white */
    --accent-gold: #9a6700; /* Darker gold for contrast */
    --accent-gold-hover: #bf8700;

    /* Semantic Colors - adjusted for light backgrounds */
    --success: #1a7f37;
    --error: #cf222e;
    --warning: #956300; /* 4.61:1 on bg-secondary */
}

/* =============================================================================
   Light Theme Component Overrides
   ============================================================================= */

/* Canvas overlays - use subtle paper-like backgrounds with soft shadows */
.light-theme .legend-panel,
.light-theme .authors-panel {
    background: rgba(250, 251, 252, 0.97);
    box-shadow: 0 2px 8px rgba(31, 35, 40, 0.1),
                0 0 1px rgba(31, 35, 40, 0.15);
    border: 1px solid var(--border);
}

.light-theme .perf-overlay {
    background: rgba(250, 251, 252, 0.95);
    box-shadow: 0 2px 12px rgba(31, 35, 40, 0.12);
    border: 1px solid var(--border);
}

.light-theme .stats-overlay {
    background: rgba(250, 251, 252, 0.95);
    box-shadow: 0 2px 8px rgba(31, 35, 40, 0.1);
    border: 1px solid var(--border);
}

/* Canvas container - warmer gray for better visualization contrast */
.light-theme #canvas-container {
    background: #d5dae0;
}

/* Header and sidebar enhancements */
.light-theme header {
    background: rgba(250, 251, 252, 0.95);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 1px 3px rgba(31, 35, 40, 0.08);
}

.light-theme .sidebar-panel {
    background: var(--bg-primary);
    box-shadow: -2px 0 8px rgba(31, 35, 40, 0.08);
}

/* Cards and panels - add subtle depth */
.light-theme .showcase-card,
.light-theme .featured-card,
.light-theme .quick-guide-card {
    box-shadow: 0 2px 8px rgba(31, 35, 40, 0.08),
                0 0 1px rgba(31, 35, 40, 0.12);
}

/* Timeline - subtle depth */
.light-theme .timeline-container {
    background: rgba(250, 251, 252, 0.95);
    border-top: 1px solid var(--border);
    box-shadow: 0 -2px 8px rgba(31, 35, 40, 0.06);
}

/* Buttons - enhanced depth */
.light-theme .btn-primary {
    box-shadow: 0 2px 4px rgba(214, 51, 90, 0.25);
}

.light-theme .btn-secondary {
    box-shadow: 0 1px 3px rgba(31, 35, 40, 0.08);
}

/* =============================================================================
   Theme Toggle Button
   ============================================================================= */

.theme-toggle {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 32px;
    height: 32px;
    border-radius: var(--radius-md);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.theme-toggle:hover {
    background: var(--border);
    color: var(--text-primary);
}

.theme-toggle:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* Icon visibility based on theme */
.theme-toggle .sun-icon { display: none; }
.theme-toggle .moon-icon { display: block; }

.light-theme .theme-toggle .sun-icon { display: block; }
.light-theme .theme-toggle .moon-icon { display: none; }

/* =============================================================================
   Light Theme Timeline Tick Adjustments
   ============================================================================= */

[data-theme="light"] .timeline-tick.tick-minor.visible {
    opacity: 0.55;
}

[data-theme="light"] .timeline-tick.tick-medium.visible {
    opacity: 0.7;
}

[data-theme="light"] .timeline-tick.tick-major.visible {
    opacity: 0.9;
}

[data-theme="light"] .timeline-tick::after {
    background: var(--bg-primary);
    border-color: var(--border);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

[data-theme="light"] .timeline-tick-label {
    color: var(--text-muted);
}

/* Fullscreen mode adjustments */

/* ---- styles/features/fullscreen.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Fullscreen Mode Styles
 *
 * Styles for fullscreen visualization including:
 * - Fullscreen button
 * - Native fullscreen mode (Fullscreen API)
 * - Pseudo-fullscreen mode (iOS Safari fallback)
 * - Exit fullscreen button
 * - Viz-panel and canvas-container fullscreen states
 */

/* =============================================================================
   Fullscreen Button
   ============================================================================= */

.fullscreen-btn {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    width: 32px;
    height: 32px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, transform 0.2s;
}

.fullscreen-btn:hover {
    background: var(--accent-surface);
    border-color: var(--accent);
    color: var(--text-on-accent);
}

.fullscreen-btn:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.fullscreen-btn svg {
    width: 16px;
    height: 16px;
}

/* =============================================================================
   Native Fullscreen Mode (Document-level)
   ============================================================================= */

:fullscreen .app-container,
:-webkit-full-screen .app-container {
    height: 100vh;
}

:fullscreen header,
:-webkit-full-screen header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    opacity: 0;
    transition: opacity 0.3s;
}

:fullscreen header:hover,
:-webkit-full-screen header:hover {
    opacity: 1;
}

:fullscreen footer,
:-webkit-full-screen footer {
    display: none;
}

:fullscreen .sidebar-panel,
:-webkit-full-screen .sidebar-panel {
    display: none;
}

:fullscreen .viz-panel,
:-webkit-full-screen .viz-panel {
    grid-column: 1 / -1;
}

/* =============================================================================
   Viz-Panel Fullscreen Mode
   ============================================================================= */

/* Includes both canvas and timeline controls */
.viz-panel:fullscreen,
.viz-panel:-webkit-full-screen {
    width: 100vw;
    height: 100vh;
    background: var(--bg-primary);
    display: flex;
    flex-direction: column;
    padding: 0;
    gap: 0;
}

.viz-panel:fullscreen #canvas-container,
.viz-panel:-webkit-full-screen #canvas-container {
    flex: 1;
    min-height: 0;
    border-radius: 0;
    border: none;
}

.viz-panel:fullscreen #canvas,
.viz-panel:-webkit-full-screen #canvas {
    width: 100% !important;
    height: 100% !important;
}

.viz-panel:fullscreen .timeline-container,
.viz-panel:-webkit-full-screen .timeline-container {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    background: rgba(22, 27, 34, 0.95);
    backdrop-filter: blur(8px);
    z-index: 100;
    opacity: 0.85;
    transition: opacity 0.3s;
}

.viz-panel:fullscreen .timeline-container:hover,
.viz-panel:-webkit-full-screen .timeline-container:hover {
    opacity: 1;
}

/* Keep overlays visible in viz-panel fullscreen */
.viz-panel:fullscreen .stats-overlay,
.viz-panel:-webkit-full-screen .stats-overlay,
.viz-panel:fullscreen .perf-overlay,
.viz-panel:-webkit-full-screen .perf-overlay,
.viz-panel:fullscreen .legend-panel,
.viz-panel:-webkit-full-screen .legend-panel,
.viz-panel:fullscreen .authors-panel,
.viz-panel:-webkit-full-screen .authors-panel {
    position: fixed;
}

/* Hide stats overlay in fullscreen - redundant with timeline info */
.viz-panel:fullscreen .stats-overlay,
.viz-panel:-webkit-full-screen .stats-overlay {
    display: none;
}

/* Authors panel position in fullscreen - clear the timeline */
.viz-panel:fullscreen .authors-panel,
.viz-panel:-webkit-full-screen .authors-panel {
    bottom: 100px;
}

/* Legend panel position in fullscreen - clear the exit button */
.viz-panel:fullscreen .legend-panel,
.viz-panel:-webkit-full-screen .legend-panel {
    top: 50px;
}

/* Exit fullscreen button in viz-panel fullscreen */
.viz-panel:fullscreen .exit-fullscreen-btn,
.viz-panel:-webkit-full-screen .exit-fullscreen-btn {
    display: flex;
    position: fixed;
}

/* =============================================================================
   Canvas-Container Fullscreen (Legacy fallback)
   ============================================================================= */

#canvas-container:fullscreen,
#canvas-container:-webkit-full-screen {
    width: 100vw;
    height: 100vh;
    background: var(--bg-primary);
}

#canvas-container:fullscreen #canvas,
#canvas-container:-webkit-full-screen #canvas {
    width: 100% !important;
    height: 100% !important;
}

/* Keep overlays visible in canvas-container fullscreen */
#canvas-container:fullscreen .stats-overlay,
#canvas-container:-webkit-full-screen .stats-overlay,
#canvas-container:fullscreen .perf-overlay,
#canvas-container:-webkit-full-screen .perf-overlay,
#canvas-container:fullscreen .legend-panel,
#canvas-container:-webkit-full-screen .legend-panel,
#canvas-container:fullscreen .authors-panel,
#canvas-container:-webkit-full-screen .authors-panel {
    position: fixed;
}

/* Also show exit button in native canvas fullscreen */
#canvas-container:fullscreen .exit-fullscreen-btn,
#canvas-container:-webkit-full-screen .exit-fullscreen-btn {
    display: flex;
}

/* =============================================================================
   Pseudo-Fullscreen Mode (iOS Safari fallback)
   ============================================================================= */

/* iOS Safari doesn't support Fullscreen API */
.pseudo-fullscreen {
    overflow: hidden;
}

.pseudo-fullscreen .app-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100vw;
    height: 100vh;
    z-index: var(--z-fullscreen);
}

.pseudo-fullscreen header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    opacity: 0;
    transition: opacity 0.3s;
}

.pseudo-fullscreen header:hover,
.pseudo-fullscreen header:focus-within {
    opacity: 1;
}

.pseudo-fullscreen footer {
    display: none;
}

.pseudo-fullscreen .sidebar-panel {
    display: none;
}

.pseudo-fullscreen .viz-panel {
    grid-column: 1 / -1;
    width: 100vw;
    height: 100vh;
}

.pseudo-fullscreen #canvas-container {
    width: 100vw;
    height: 100vh;
}

.pseudo-fullscreen #canvas {
    width: 100% !important;
    height: 100% !important;
}

/* Keep timeline controls visible in pseudo-fullscreen */
.pseudo-fullscreen .timeline-container {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    background: rgba(22, 27, 34, 0.95);
    backdrop-filter: blur(8px);
    z-index: var(--z-fullscreen-timeline);
    opacity: 0.85;
    transition: opacity 0.3s;
}

.pseudo-fullscreen .timeline-container:hover {
    opacity: 1;
}

/* Hide overlays that shouldn't be visible in fullscreen */
.pseudo-fullscreen .sidebar-overlay {
    display: none;
}

/* Hide stats overlay in pseudo-fullscreen - info is in timeline */
.pseudo-fullscreen .stats-overlay {
    display: none;
}

/* Authors panel position in pseudo-fullscreen - clear the tall mobile timeline */
.pseudo-fullscreen .authors-panel {
    bottom: 180px;
    position: fixed;
}

.pseudo-fullscreen .perf-overlay {
    position: fixed;
}

.pseudo-fullscreen .legend-panel {
    position: fixed;
    top: 50px; /* Clear the exit button */
}

/* =============================================================================
   Exit Fullscreen Button
   ============================================================================= */

/* Hidden by default, visible in pseudo-fullscreen and native fullscreen */
.exit-fullscreen-btn {
    display: none;
    position: fixed;
    top: 0.5rem;
    right: 0.5rem;
    width: 40px;
    height: 40px;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.7);
    color: var(--text-on-accent);
    cursor: pointer;
    z-index: var(--z-fullscreen-exit);
    align-items: center;
    justify-content: center;
    transition: background 0.2s, transform 0.2s;
    -webkit-tap-highlight-color: transparent;
}

.exit-fullscreen-btn:hover,
.exit-fullscreen-btn:focus {
    background: rgba(0, 0, 0, 0.8);
    transform: scale(1.1);
    outline: none;
}

.exit-fullscreen-btn:active {
    transform: scale(0.95);
}

.exit-fullscreen-btn svg {
    width: 24px;
    height: 24px;
}

/* Show exit button only in pseudo-fullscreen mode */
.pseudo-fullscreen .exit-fullscreen-btn {
    display: flex;
}

/* =============================================================================
   Mobile Fullscreen Adjustments
   ============================================================================= */

@media (max-width: 768px) {
    .pseudo-fullscreen .timeline-container {
        padding: 0.5rem 0.75rem;
        padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
    }

    .pseudo-fullscreen .authors-panel {
        bottom: 200px; /* More clearance for taller mobile timeline */
        max-width: 140px;
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    .pseudo-fullscreen .legend-panel {
        max-width: 150px;
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* -----------------------------------------------------------------
       Mobile Fullscreen: Minimize Distractions
       -----------------------------------------------------------------
       In fullscreen on mobile, we want maximum canvas visibility.
       Auto-collapse overlays and ensure exit button is always visible.
    */

    /* Exit button: ALWAYS visible and prominent in mobile fullscreen */
    .pseudo-fullscreen .exit-fullscreen-btn {
        display: flex !important;
        position: fixed !important;
        top: max(12px, env(safe-area-inset-top)) !important;
        right: max(12px, env(safe-area-inset-right)) !important;
        z-index: 10010 !important; /* Above everything */
        width: 44px;
        height: 44px;
        background: rgba(0, 0, 0, 0.8);
        border: 2px solid rgba(255, 255, 255, 0.3);
    }

    /* Hide center play button in fullscreen - timeline has play controls */
    .pseudo-fullscreen .mobile-center-play {
        display: none !important;
    }

    /* Auto-collapse perf overlay in mobile fullscreen for cleaner view */
    .pseudo-fullscreen .perf-overlay {
        /* Move to bottom-right to not conflict with exit button */
        top: auto !important;
        bottom: max(140px, calc(140px + env(safe-area-inset-bottom)));
        right: max(8px, env(safe-area-inset-right));
        left: auto !important;
        /* Compact styling */
        padding: 6px 10px;
        max-width: 120px;
        border-radius: 12px;
        background: rgba(0, 0, 0, 0.7);
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* Force collapsed state in fullscreen - just show FPS */
    .pseudo-fullscreen .perf-overlay .perf-details {
        display: none !important;
    }

    .pseudo-fullscreen .perf-overlay .perf-header {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: none;
    }

    .pseudo-fullscreen .perf-overlay .perf-fps {
        font-size: 0.85rem;
        min-width: auto;
    }

    .pseudo-fullscreen .perf-overlay .perf-toggle {
        display: none;
    }

    /* Hide mobile toolbar in fullscreen - timeline has all controls */
    .pseudo-fullscreen .mobile-toolbar {
        display: none !important;
    }

    /* Hide FAB in fullscreen */
    .pseudo-fullscreen .bottom-sheet-fab {
        display: none !important;
    }

    /* Hide legend and authors in mobile fullscreen */
    .pseudo-fullscreen .legend-panel,
    .pseudo-fullscreen .authors-panel {
        display: none !important;
    }

    /* Adjust timeline for mobile fullscreen */
    .pseudo-fullscreen .timeline-container {
        min-height: auto;
        padding: 0.4rem 0.75rem;
        padding-bottom: max(0.4rem, env(safe-area-inset-bottom));
    }

    /* Compact date row */
    .pseudo-fullscreen .timeline-date-row {
        font-size: 0.8rem;
    }

    /* Ensure timeline is below exit button z-index */
    .pseudo-fullscreen .timeline-container {
        z-index: 1000;
    }
}

/* Native fullscreen mode on mobile (if supported) */
@media (max-width: 768px) {
    .viz-panel:fullscreen .exit-fullscreen-btn,
    .viz-panel:-webkit-full-screen .exit-fullscreen-btn {
        display: flex !important;
        position: fixed !important;
        top: max(12px, env(safe-area-inset-top)) !important;
        right: max(12px, env(safe-area-inset-right)) !important;
        z-index: 10010 !important;
        width: 44px;
        height: 44px;
        background: rgba(0, 0, 0, 0.8);
        border: 2px solid rgba(255, 255, 255, 0.3);
    }

    .viz-panel:fullscreen .mobile-center-play,
    .viz-panel:-webkit-full-screen .mobile-center-play {
        display: none !important;
    }

    .viz-panel:fullscreen .mobile-toolbar,
    .viz-panel:-webkit-full-screen .mobile-toolbar {
        display: none !important;
    }

    .viz-panel:fullscreen .bottom-sheet-fab,
    .viz-panel:-webkit-full-screen .bottom-sheet-fab {
        display: none !important;
    }

    .viz-panel:fullscreen .perf-overlay,
    .viz-panel:-webkit-full-screen .perf-overlay {
        top: auto !important;
        bottom: max(140px, calc(140px + env(safe-area-inset-bottom)));
        right: max(8px, env(safe-area-inset-right));
        left: auto !important;
        padding: 6px 10px;
        max-width: 120px;
        border-radius: 12px;
    }

    .viz-panel:fullscreen .perf-overlay .perf-details,
    .viz-panel:-webkit-full-screen .perf-overlay .perf-details {
        display: none !important;
    }

    .viz-panel:fullscreen .perf-overlay .perf-toggle,
    .viz-panel:-webkit-full-screen .perf-overlay .perf-toggle {
        display: none;
    }

    .viz-panel:fullscreen .legend-panel,
    .viz-panel:-webkit-full-screen .legend-panel,
    .viz-panel:fullscreen .authors-panel,
    .viz-panel:-webkit-full-screen .authors-panel {
        display: none !important;
    }
}

/* =============================================================================
   Light Theme Fullscreen Adjustments
   ============================================================================= */

.light-theme.pseudo-fullscreen .exit-fullscreen-btn {
    background: rgba(250, 251, 252, 0.95);
    border-color: var(--border);
    color: var(--text-primary);
}

.light-theme.pseudo-fullscreen .perf-overlay {
    background: rgba(250, 251, 252, 0.95);
    border: 1px solid var(--border);
}

.light-theme.pseudo-fullscreen .timeline-container {
    background: rgba(250, 251, 252, 0.97);
}

/* Immersive mode (landscape fullscreen with HUD overlay) */

/* ---- styles/features/immersive.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Immersive Fullscreen Mode Styles
 *
 * Cinema/video-game style fullscreen experience for mobile landscape.
 * Features:
 * - Full-bleed canvas with no distractions
 * - Minimal HUD overlay that auto-hides
 * - Edge-positioned controls for thumb reach
 * - Smooth transitions for show/hide
 *
 * Design inspiration:
 * - YouTube fullscreen player
 * - Netflix immersive mode
 * - Video game HUDs (Call of Duty, Fortnite style minimal overlays)
 */

/* =============================================================================
   Fullscreen Prompt Dialog
   ============================================================================= */

.fullscreen-prompt {
    position: fixed;
    bottom: 20%;
    left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: rgba(13, 17, 23, 0.95);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-radius: 16px;
    padding: 20px 24px;
    z-index: var(--z-modal);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
    max-width: 320px;
    width: 90%;
    text-align: center;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

.fullscreen-prompt.visible {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

.fullscreen-prompt-icon {
    width: 48px;
    height: 48px;
    margin: 0 auto 12px;
    color: var(--accent);
}

.fullscreen-prompt-title {
    font-size: 1.125rem;
    font-weight: 600;
    margin-bottom: 8px;
    color: var(--text-primary);
}

.fullscreen-prompt-text {
    font-size: 0.875rem;
    color: var(--text-secondary);
    margin-bottom: 16px;
    line-height: 1.5;
}

.fullscreen-prompt-buttons {
    display: flex;
    gap: 12px;
    justify-content: center;
    margin-bottom: 12px;
}

.fullscreen-prompt-btn {
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    border: none;
    transition: background 0.2s, transform 0.15s;
    -webkit-tap-highlight-color: transparent;
}

.fullscreen-prompt-btn:active {
    transform: scale(0.96);
}

.fullscreen-prompt-btn-primary {
    background: var(--accent-surface);
    color: white;
}

.fullscreen-prompt-btn-primary:hover {
    background: var(--accent-hover);
}

.fullscreen-prompt-btn-secondary {
    background: var(--bg-tertiary);
    color: var(--text-primary);
    border: 1px solid var(--border);
}

.fullscreen-prompt-btn-secondary:hover {
    background: var(--border);
}

.fullscreen-prompt-checkbox {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.fullscreen-prompt-checkbox input {
    width: 16px;
    height: 16px;
    cursor: pointer;
}

/* =============================================================================
   Immersive Mode Base
   ============================================================================= */

/**
 * When immersive mode is active, the canvas takes over the entire viewport.
 * All chrome (header, footer, sidebar, etc.) is hidden.
 */
.immersive-mode {
    /* Hide scrollbars */
    overflow: hidden !important;
}

.immersive-mode header,
.immersive-mode footer,
.immersive-mode .sidebar-wrapper,
.immersive-mode .sidebar-panel,
.immersive-mode .sidebar-toggle,
.immersive-mode .sidebar-overlay,
.immersive-mode .bottom-sheet,
.immersive-mode .bottom-sheet-fab,
.immersive-mode .bottom-sheet-backdrop,
.immersive-mode .mobile-toolbar,
.immersive-mode .mobile-center-play,
.immersive-mode .legend-panel,
.immersive-mode .authors-panel,
.immersive-mode .stats-overlay,
.immersive-mode .perf-overlay,
.immersive-mode .empty-state {
    display: none !important;
}

.immersive-mode .app-container {
    display: block;
    padding: 0;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

.immersive-mode #canvas-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: none;
    z-index: 1;
}

.immersive-mode .viz-panel {
    display: block;
    height: 100%;
}

/* Hide the regular timeline in immersive mode - we use the HUD version */
.immersive-mode .timeline-container {
    display: none !important;
}

/* =============================================================================
   Immersive HUD Overlay
   ============================================================================= */

/**
 * Minimal HUD overlay for immersive mode.
 * Shows:
 * - Top-left: Exit button
 * - Top-right: Stats (optional, tap to show)
 * - Bottom-center: Play/pause + timeline
 *
 * Auto-hides after 3 seconds during playback.
 */

.immersive-hud {
    display: none;
    position: fixed;
    z-index: 1000;
    opacity: 1;
    transition: opacity 0.3s ease;
    pointer-events: none;
}

.immersive-mode .immersive-hud {
    display: flex;
    pointer-events: auto;
}

/* HUD hidden state - fade out */
.immersive-mode.hud-hidden .immersive-hud {
    opacity: 0;
    pointer-events: none;
}

/* -------------------------------------------------------------------------
   Exit Button (Top-left corner)
   ------------------------------------------------------------------------- */

.immersive-exit-btn {
    position: fixed;
    top: max(12px, env(safe-area-inset-top));
    left: max(12px, env(safe-area-inset-left));
    width: 44px;
    height: 44px;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: none;
    border-radius: 50%;
    color: white;
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 1001;
    transition: background 0.2s, opacity 0.3s, transform 0.15s;
    -webkit-tap-highlight-color: transparent;
}

.immersive-mode .immersive-exit-btn {
    display: flex;
}

.immersive-mode.hud-hidden .immersive-exit-btn {
    opacity: 0;
    pointer-events: none;
}

.immersive-exit-btn:hover {
    background: rgba(0, 0, 0, 0.8);
}

.immersive-exit-btn:active {
    transform: scale(0.9);
}

.immersive-exit-btn svg {
    width: 20px;
    height: 20px;
}

/* -------------------------------------------------------------------------
   Bottom HUD Bar (Play + Timeline)
   ------------------------------------------------------------------------- */

.immersive-bottom-hud {
    position: fixed;
    bottom: max(16px, env(safe-area-inset-bottom));
    left: 50%;
    transform: translateX(-50%);
    display: none;
    align-items: center;
    gap: 16px;
    padding: 12px 20px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: 28px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
    z-index: 1001;
    transition: opacity 0.3s ease, transform 0.3s ease;
    max-width: calc(100vw - 32px);
}

.immersive-mode .immersive-bottom-hud {
    display: flex;
}

.immersive-mode.hud-hidden .immersive-bottom-hud {
    opacity: 0;
    transform: translateX(-50%) translateY(20px);
    pointer-events: none;
}

/* Play/Pause Button */
.immersive-play-btn {
    width: 48px;
    height: 48px;
    background: var(--accent-surface);
    border: none;
    border-radius: 50%;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.2s, transform 0.15s;
    -webkit-tap-highlight-color: transparent;
}

.immersive-play-btn:hover {
    background: var(--accent-hover);
}

.immersive-play-btn:active {
    transform: scale(0.92);
}

.immersive-play-btn svg {
    width: 24px;
    height: 24px;
}

/* Timeline Slider in HUD */
.immersive-timeline {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    min-width: 200px;
    max-width: 400px;
}

.immersive-timeline-slider {
    flex: 1;
    height: 6px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
}

.immersive-timeline-slider::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    width: 16px;
    height: 16px;
    background: var(--accent);
    border-radius: 50%;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    transition: transform 0.15s;
}

.immersive-timeline-slider::-webkit-slider-thumb:hover {
    transform: scale(1.15);
}

.immersive-timeline-slider::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background: var(--accent);
    border-radius: 50%;
    border: none;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.immersive-timeline-slider::-webkit-slider-runnable-track {
    height: 6px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
}

.immersive-timeline-slider::-moz-range-track {
    height: 6px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
}

/* Time/Date Display */
.immersive-time-display {
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.8);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    min-width: 80px;
    text-align: right;
}

/* -------------------------------------------------------------------------
   Optional: Mini Stats Badge (tap to show, hidden by default)
   ------------------------------------------------------------------------- */

.immersive-stats-badge {
    position: fixed;
    top: max(12px, env(safe-area-inset-top));
    right: max(12px, env(safe-area-inset-right));
    display: none;
    padding: 6px 12px;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 16px;
    color: white;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    z-index: 1001;
    transition: opacity 0.3s ease;
}

.immersive-mode .immersive-stats-badge {
    display: flex;
    gap: 12px;
}

.immersive-mode.hud-hidden .immersive-stats-badge {
    opacity: 0;
}

.immersive-stats-badge span {
    display: flex;
    align-items: center;
    gap: 4px;
}

.immersive-stats-badge .stat-value {
    font-weight: 600;
}

.immersive-stats-badge .stat-label {
    opacity: 0.7;
    font-size: 0.75rem; /* 12px - WCAG minimum */
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

/* =============================================================================
   Light Theme Adjustments
   ============================================================================= */

.light-theme .fullscreen-prompt {
    background: rgba(250, 251, 252, 0.97);
    border-color: var(--border);
}

.light-theme .immersive-exit-btn,
.light-theme .immersive-bottom-hud,
.light-theme .immersive-stats-badge {
    background: rgba(250, 251, 252, 0.92);
    border-color: var(--border);
}

.light-theme .immersive-exit-btn {
    color: var(--text-primary);
}

.light-theme .immersive-time-display {
    color: var(--text-secondary);
}

.light-theme .immersive-timeline-slider {
    background: rgba(0, 0, 0, 0.15);
}

.light-theme .immersive-timeline-slider::-webkit-slider-runnable-track {
    background: rgba(0, 0, 0, 0.15);
}

.light-theme .immersive-timeline-slider::-moz-range-track {
    background: rgba(0, 0, 0, 0.15);
}

.light-theme .immersive-stats-badge {
    color: var(--text-primary);
}

/* =============================================================================
   Landscape Adjustments
   ============================================================================= */

@media (orientation: landscape) {
    .immersive-bottom-hud {
        /* Safe area for notched devices in landscape */
        left: max(50%, calc(50% + env(safe-area-inset-left) / 2));
        padding-left: max(20px, env(safe-area-inset-left));
        padding-right: max(20px, env(safe-area-inset-right));
    }

    .immersive-timeline {
        min-width: 250px;
        max-width: 500px;
    }
}

/* =============================================================================
   Reduced Motion
   ============================================================================= */

@media (prefers-reduced-motion: reduce) {
    .fullscreen-prompt,
    .immersive-hud,
    .immersive-exit-btn,
    .immersive-bottom-hud,
    .immersive-stats-badge {
        transition: none;
    }
}

/* Video recording and controls */

/* ---- styles/features/recording.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Recording and Controls Styles
 *
 * Video recording indicator, record button, share button, and font size controls.
 */

/* =============================================================================
   Recording Indicator
   ============================================================================= */

.recording-indicator {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: rgba(248, 81, 73, 0.15);
    border: 1px solid var(--error);
    border-radius: 6px;
    color: var(--error);
    font-size: 0.85rem;
    animation: recordingPulse 1.5s ease-in-out infinite;
}

.recording-indicator .recording-dot {
    width: 8px;
    height: 8px;
    background: var(--error);
    border-radius: 50%;
    animation: recordingDot 1s ease-in-out infinite;
}

/* =============================================================================
   Record Button
   ============================================================================= */

.btn-record {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.btn-record.preparing {
    background: var(--warning-surface);
    border-color: var(--warning-surface);
    color: var(--text-on-warning);
    animation: preparingPulse 0.5s ease-in-out infinite;
}

.btn-record.recording {
    background: var(--error-surface);
    border-color: var(--error-surface);
    color: var(--text-on-accent);
}

.btn-record.recording:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

/* =============================================================================
   Share Button
   ============================================================================= */

.share-btn {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    /* Touch target: 44px minimum (Apple HIG / WCAG 2.5.5) */
    width: 44px;
    height: 44px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Use composited properties only for better performance */
    transition: opacity 0.2s, transform 0.2s;
}

.share-btn:hover {
    background: var(--accent-blue-surface);
    border-color: var(--accent-blue-surface);
    color: var(--text-on-accent);
}

.share-btn:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.share-btn svg {
    width: 16px;
    height: 16px;
}

/* =============================================================================
   Font Size Control
   ============================================================================= */

.font-size-control {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.font-size-control label {
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.font-size-control .font-size-btns {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.font-size-control .font-size-btn {
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    /* Touch target: 44px minimum (Apple HIG / WCAG 2.5.5) */
    width: 44px;
    height: 44px;
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    font-weight: 600;
    /* Use composited properties only for better performance */
    transition: opacity 0.15s, transform 0.15s;
}

.font-size-control .font-size-btn:hover:not(:disabled) {
    background: var(--border);
    color: var(--text-primary);
}

.font-size-control .font-size-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.font-size-control .font-size-value {
    font-size: 0.8rem;
    color: var(--text-secondary);
    min-width: 44px; /* Consistent with touch target minimum */
    text-align: center;
    font-family: monospace;
}

/* Accessibility (contrast, reduced motion, auto color scheme) */

/* ---- styles/features/accessibility.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Accessibility Styles
 *
 * WCAG compliance improvements, reduced motion support, and auto color scheme.
 */

/* =============================================================================
   Screen Reader Only (Hidden Visually but Accessible)
   ============================================================================= */

/**
 * Hide content visually but keep it accessible to screen readers.
 * Used for status announcements and additional context.
 */
.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;
}

/* =============================================================================
   Contrast Improvements (WCAG AA)
   ============================================================================= */

/**
 * Improve contrast ratios to meet WCAG AA requirements (4.5:1 for normal text).
 * Dark theme: #8b949e on #21262d = 3.86:1 (fails), #a8b2bd on #21262d = 4.7:1 (passes)
 */

/* Disabled buttons need higher contrast text */
.showcase-btn:disabled,
.btn:disabled,
.btn-secondary:disabled {
    color: #a8b2bd; /* WCAG AA: 4.7:1 contrast on #21262d */
}

/* Links should be distinguishable without relying solely on color */
.docs-panel a,
.panel-body a,
.help-text a,
.about-banner a:not(.btn) {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

.docs-panel a:hover,
.panel-body a:hover,
.help-text a:hover,
.about-banner a:not(.btn):hover {
    text-decoration-thickness: 2px;
}

/* Improve muted text contrast for informational content */
.panel-guide .help-text,
.docs-section p {
    color: #9ca3af; /* WCAG AA: 4.5:1 on dark backgrounds */
}

/* Maintain h3 visual styling when using h2 for proper heading hierarchy */
h2.h3-style {
    font-size: 1.1rem;
    font-weight: 600;
    margin: 0 0 0.5rem 0;
}

/* =============================================================================
   Focus States (A6: Visible Focus Indicators)
   ============================================================================= */

/**
 * Visible focus indicators for keyboard navigation.
 * Uses :focus-visible to show focus rings only for keyboard users,
 * not for mouse/touch interactions.
 *
 * WCAG 2.1 Success Criterion 2.4.7: Focus Visible (Level AA)
 */

/* Base focus ring for all focusable elements */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Remove default focus ring (replaced by :focus-visible) */
:focus:not(:focus-visible) {
    outline: none;
}

/* Button focus states */
.btn:focus-visible,
.control-btn:focus-visible,
.mobile-toolbar-btn:focus-visible,
.bottom-sheet-fab:focus-visible,
.theme-toggle:focus-visible,
.sidebar-toggle:focus-visible,
.showcase-btn:focus-visible {
    outline: 2px solid var(--text-primary, #f0f6fc);
    outline-offset: 2px;
    border-radius: inherit;
}

/* Timeline scrubber focus */
.timeline-slider:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 4px;
}

/* Timeline thumb focus (for custom range inputs) */
.timeline-slider:focus-visible::-webkit-slider-thumb {
    box-shadow: 0 0 0 3px var(--accent);
}

.timeline-slider:focus-visible::-moz-range-thumb {
    box-shadow: 0 0 0 3px var(--accent);
}

/* Input field focus */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.input-group input:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
    border-color: var(--accent);
}

/* Link focus */
a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

/* Tab focus */
.tab-btn:focus-visible,
.quick-action:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-md, 8px);
}

/* Panel/card focus (for keyboard-navigable panels) */
.author-item:focus-visible,
.legend-item:focus-visible,
.collapsible-header:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Speed dropdown focus */
.speed-select:focus-visible {
    outline: 2px solid var(--text-primary, #f0f6fc);
    outline-offset: 2px;
}

/* Close button focus */
.modal-close:focus-visible,
.help-close:focus-visible,
.toast-close:focus-visible {
    outline: 2px solid var(--text-primary, #f0f6fc);
    outline-offset: 2px;
    border-radius: 50%;
}

/* Skip link for keyboard users */
.skip-link {
    position: absolute;
    top: -40px;
    left: 0;
    background: var(--accent-surface);
    color: white;
    padding: 8px 16px;
    z-index: 10000;
    transition: top 0.2s;
}

.skip-link:focus {
    top: 0;
}

/* Light theme focus adjustments */
.light-theme :focus-visible,
:root:not(.theme-manual) :focus-visible {
    outline-color: var(--accent, #d6335a);
}

@media (prefers-color-scheme: light) {
    :root:not(.theme-manual) :focus-visible {
        outline-color: var(--accent, #d6335a);
    }
}

/* =============================================================================
   Composited Animations (GPU Acceleration)
   ============================================================================= */

/**
 * Ensure animations use compositor-friendly properties (transform, opacity)
 * and add will-change hint for GPU acceleration.
 */

.sidebar-scroll-indicator svg {
    will-change: transform;
}

.loading-spinner {
    will-change: transform;
}

.btn-record.recording .record-indicator {
    will-change: transform, opacity;
}

/* =============================================================================
   Reduced Motion Support
   ============================================================================= */

/**
 * Disable animations and transitions for users who prefer reduced motion.
 * This respects the prefers-reduced-motion media query for accessibility.
 */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    /* Allow subtle hover effects but remove transitions */
    .control-btn,
    .collapsible-header,
    .timeline-slider,
    .theme-toggle,
    .sidebar-toggle,
    .btn,
    .input-group input {
        transition: none !important;
    }

    /* Disable parallax or sliding effects */
    .sidebar-panel {
        scroll-behavior: auto !important;
    }
}

/**
 * Manual reduced motion override class.
 * Applied via JavaScript when user explicitly chooses 'always' reduce motion.
 * This complements the @media query for user preference override.
 */
:root.reduce-motion *,
:root.reduce-motion *::before,
:root.reduce-motion *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
}

:root.reduce-motion .control-btn,
:root.reduce-motion .collapsible-header,
:root.reduce-motion .timeline-slider,
:root.reduce-motion .theme-toggle,
:root.reduce-motion .sidebar-toggle,
:root.reduce-motion .btn,
:root.reduce-motion .input-group input {
    transition: none !important;
}

:root.reduce-motion .sidebar-panel {
    scroll-behavior: auto !important;
}

/* Loading skeleton animations disabled in reduced motion mode */
:root.reduce-motion .skeleton-bar::after,
:root.reduce-motion .loading-spinner,
:root.reduce-motion .skeleton-node,
:root.reduce-motion .skeleton-beam,
:root.reduce-motion .skeleton-pulse {
    animation: none !important;
}

/* =============================================================================
   Auto Color Scheme (System Preference)
   ============================================================================= */

/**
 * Automatically apply light theme for users with light system preference.
 * This can be overridden by the manual theme toggle (JS adds/removes .light-theme class).
 * The :not(.theme-manual) check prevents auto-switching when user has manually toggled.
 */

/* =============================================================================
   Backdrop Filter Fallbacks
   ============================================================================= */

/**
 * Progressive enhancement for backdrop-filter.
 * Older browsers (e.g., Firefox <103, older Safari) don't support backdrop-filter.
 * We use @supports to provide fallback with more opaque backgrounds.
 *
 * Strategy: Set solid fallback backgrounds by default, then apply blur
 * with transparent backgrounds when supported.
 */

/* Fallback: more opaque backgrounds when backdrop-filter is not supported */
@supports not (backdrop-filter: blur(1px)) {
    .legend-panel,
    .authors-panel,
    .stats-overlay {
        background: rgba(22, 27, 34, 0.98);
    }

    .perf-overlay {
        background: rgba(13, 17, 23, 0.98);
    }

    .modal-overlay,
    .help-overlay {
        background: rgba(0, 0, 0, 0.85);
    }

    .viz-panel:fullscreen .timeline-container,
    .pseudo-fullscreen .timeline-container {
        background: rgba(22, 27, 34, 0.98);
    }
}

/* Light theme fallbacks */
@supports not (backdrop-filter: blur(1px)) {
    .light-theme .legend-panel,
    .light-theme .authors-panel,
    .light-theme .perf-overlay,
    .light-theme .stats-overlay {
        background: rgba(246, 248, 250, 0.98);
    }
}

/* =============================================================================
   High Contrast Mode (prefers-contrast: more)
   ============================================================================= */

/**
 * Enhanced contrast for users who prefer higher contrast.
 * Increases border visibility and text contrast.
 */

@media (prefers-contrast: more) {
    :root {
        /* High contrast: increase all contrast values above defaults */
        --border: #848d97;          /* ~4.6:1 vs bg-primary (was #6e7681 ~3.8:1) */
        --border-light: #9ca3ab;    /* ~5.7:1 vs bg-primary */
        --text-secondary: #c9d1d9;  /* ~11.6:1 vs bg-primary */
        --text-muted: #b1b8c0;     /* ~8.2:1 vs bg-primary (was #8b949e ~4.86:1, same as default) */
    }

    :root.light-theme {
        --border: #57606a;
        --border-light: #424a53;
        --text-secondary: #24292f;
        --text-muted: #424a53;
    }

    /* Increase border width for better visibility */
    .panel,
    .modal-content,
    .bottom-sheet,
    .legend-panel,
    .stats-overlay,
    .perf-overlay,
    .authors-panel,
    #canvas-container {
        border-width: 2px;
    }

    /* Ensure focus indicators are more visible */
    :focus-visible {
        outline-width: 3px;
        outline-offset: 3px;
    }

    /* Increase button contrast */
    .btn {
        border: 2px solid currentColor;
    }

    .btn:disabled {
        border-color: var(--border);
    }
}

/* =============================================================================
   Windows High Contrast Mode (forced-colors)
   ============================================================================= */

/**
 * Support for Windows High Contrast mode.
 * Uses system colors and removes custom styling that might interfere.
 */

@media (forced-colors: active) {
    /* Reset backgrounds to system colors */
    body,
    header,
    .panel,
    .modal-content,
    .bottom-sheet,
    .sidebar-panel {
        background: Canvas;
        color: CanvasText;
    }

    /* Ensure links are visible */
    a {
        color: LinkText;
    }

    /* Buttons use system button styling */
    .btn,
    .theme-toggle,
    .sidebar-toggle,
    .bottom-sheet-fab,
    .mobile-toolbar-btn {
        background: ButtonFace;
        color: ButtonText;
        border: 2px solid ButtonText;
        forced-color-adjust: none;
    }

    .btn:hover,
    .theme-toggle:hover,
    .sidebar-toggle:hover {
        background: Highlight;
        color: HighlightText;
        border-color: Highlight;
    }

    /* Focus indicators use system highlight */
    :focus-visible {
        outline: 3px solid Highlight;
        outline-offset: 2px;
    }

    /* Ensure form controls are visible */
    input,
    select,
    textarea {
        background: Field;
        color: FieldText;
        border: 2px solid ButtonText;
    }

    /* Checkboxes and switches */
    input[type="checkbox"],
    input[type="radio"],
    .perf-switch input {
        forced-color-adjust: none;
    }

    /* Disabled states */
    .btn:disabled,
    input:disabled {
        color: GrayText;
        border-color: GrayText;
    }

    /* Remove decorative shadows and gradients */
    * {
        box-shadow: none !important;
        text-shadow: none !important;
    }

    /* Ensure SVG icons use current color */
    svg {
        fill: currentColor;
        stroke: currentColor;
    }

    /* Timeline slider track */
    .timeline-slider::-webkit-slider-runnable-track {
        background: ButtonFace;
        border: 1px solid ButtonText;
    }

    .timeline-slider::-moz-range-track {
        background: ButtonFace;
        border: 1px solid ButtonText;
    }

    /* Progress indicators */
    .timeline-progress {
        background: Highlight;
    }
}

/* =============================================================================
   Utility Classes
   ============================================================================= */

/* Visually hidden but accessible to screen readers */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Hidden from everyone including screen readers */
.hidden {
    display: none !important;
}

/* =============================================================================
   Author Filter (Interactive)
   ============================================================================= */

.author-item {
    cursor: pointer;
    padding: 0.25rem;
    margin: -0.25rem;
    border-radius: 4px;
    /* Use composited properties only for better performance */
    transition: opacity 0.15s, transform 0.15s;
}

.author-item:hover {
    background: var(--bg-tertiary);
}

.author-item.filtered {
    opacity: 0.4;
}

.author-item.active {
    background: rgba(233, 69, 96, 0.15);
    border: 1px solid var(--accent);
    margin: calc(-0.25rem - 1px);
    padding: calc(0.25rem - 1px);
}

.author-filter-clear {
    font-size: 0.75rem;
    color: var(--accent);
    cursor: pointer;
    margin-left: auto;
    padding: 0.2rem 0.4rem;
    background: rgba(233, 69, 96, 0.1);
    border-radius: 4px;
    display: none;
}

.author-filter-clear.visible {
    display: block;
}

/* =============================================================================
   Target Size (A3)
   =============================================================================

   CLAUDE.md requires every interactive control to be at least 44x44 CSS px
   (Apple HIG; WCAG 2.5.5 Target Size). Enforced here in one place rather than
   scattered across component files, so the rule is auditable and a new
   component cannot quietly opt out.

   The controls below were measured under 44x44 by
   tests/visual/audit/a11y-audit.js. Sizes are set with min-height / min-width
   so a component may still be larger, never smaller.

   NOT covered, deliberately: links inside running prose ("built on <Gource>"),
   which WCAG 2.5.8 exempts precisely because enlarging a word inside a
   sentence breaks the line box. a11y-audit.js encodes that exception so the
   report stays honest about what it is and is not checking.
   ============================================================================= */

/* Icon-only buttons: header chrome, transport controls, panel affordances. */
#btn-theme,
#btn-fullscreen,
#btn-help,
#btn-prev,
#btn-next,
#btn-reset-bar,
.timeline-btn {
    min-width: 44px;
    min-height: 44px;
}

/* Text buttons, tabs and small button-styled links. */
.btn,
.btn-sm,
.tab-btn,
.showcase-btn,
.showcase-btn-secondary,
#btn-labels,
#btn-screenshot,
#btn-full-map,
#btn-record,
#btn-copy-command,
#btn-fetch-github,
#btn-visualize-rource,
#btn-refresh-rource {
    min-height: 44px;
}

/* Form controls. */
#speed-select,
#github-url,
.analytics-input {
    min-height: 44px;
}

/* Header brand link and the GitHub call to action. */
.header-brand > a,
.github-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
}

/* Collapsible panel headers act as buttons, so they answer to the same rule. */
#legend-toggle,
#authors-toggle,
#perf-toggle,
#tech-info-toggle {
    min-height: 44px;
    display: flex;
    align-items: center;
}

/* The skip link is only visible on focus, but it is still a control. */
.skip-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
}

/* Keyboard-focusable scroll region (see A6). */
.command-box {
    min-height: 44px;
}

/* The uncapped-FPS checkbox is a genuine 44x44 target; the visual box stays
   small, the hit area does not. */
#perf-uncapped {
    min-width: 44px;
    min-height: 44px;
}

/* Toast dismiss button. Only present while a toast is showing, which is why
   it does not appear in every sweep — a control that exists intermittently
   still has to meet the size rule. */
.toast-close {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Bottom sheet: links and the "+N more" expander. */
.bottom-sheet-link,
.bottom-sheet-legend-toggle {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
}

/* -----------------------------------------------------------------------------
   Range inputs
   -----------------------------------------------------------------------------
   The timeline scrubber is the single most important control in the app and
   measured 890x6 on desktop, 244x24 on mobile. A range input's height is its
   hit area, so the input is given the full 44px while the visible track keeps
   its slim look via a styled runnable-track. Padding would not work: it is
   excluded from the input's own box for hit-testing purposes.
   ----------------------------------------------------------------------------- */
.timeline-slider,
.immersive-timeline-slider {
    height: 44px;
    background: transparent;
}

.timeline-slider::-webkit-slider-runnable-track,
.immersive-timeline-slider::-webkit-slider-runnable-track {
    height: 6px;
    border-radius: 3px;
    background: var(--bg-tertiary);
}

.timeline-slider::-moz-range-track,
.immersive-timeline-slider::-moz-range-track {
    height: 6px;
    border-radius: 3px;
    background: var(--bg-tertiary);
}

/* Re-centre the thumb now that the input is 44px tall rather than 6px. */
.timeline-slider::-webkit-slider-thumb,
.immersive-timeline-slider::-webkit-slider-thumb {
    margin-top: -5px;
}

/* iOS-style bottom sheet for mobile */

/* ---- styles/features/bottom-sheet-core.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Bottom Sheet Core Styles
 *
 * Core structural styles for the iOS-style bottom sheet:
 * - Desktop hidden states and [hidden] overrides
 * - Backdrop (dimmed background)
 * - Sheet container and positioning
 * - Drag handle header
 * - Close button
 * - Scrollable content area
 * - Floating Action Button (FAB)
 */

/* =============================================================================
   Bottom Sheet - Desktop Hidden
   ============================================================================= */

.bottom-sheet-backdrop {
    display: none;
}

.bottom-sheet {
    display: none;
}

.bottom-sheet-fab {
    display: none;
}

/* Enforce hidden when view-manager.js sets hidden attribute.
   Without this, the mobile media query display:flex/block overrides
   the UA [hidden]{display:none} at <=768px viewports. */
.bottom-sheet-backdrop[hidden] {
    display: none;
}

.bottom-sheet[hidden] {
    display: none;
}

.bottom-sheet-fab[hidden] {
    display: none;
}

/* =============================================================================
   Bottom Sheet - Mobile Core
   ============================================================================= */

@media (max-width: 768px) {
    /* Hide old sidebar when bottom sheet is active */
    .has-bottom-sheet .sidebar-toggle {
        display: none !important;
    }

    .has-bottom-sheet .sidebar-panel {
        display: none !important;
    }

    .has-bottom-sheet .sidebar-wrapper {
        display: none !important;
    }

    /* -------------------------------------------------------------------------
       Backdrop (dimmed background)
       ------------------------------------------------------------------------- */

    .bottom-sheet-backdrop {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: var(--backdrop);
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        z-index: var(--z-modal-backdrop);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.3s ease, visibility 0.3s ease;
        pointer-events: none;
    }

    .bottom-sheet-backdrop.visible {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }

    /* -------------------------------------------------------------------------
       Sheet Container
       ------------------------------------------------------------------------- */

    .bottom-sheet {
        display: flex;
        flex-direction: column;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        /* Dynamic viewport height for mobile browser address bar changes */
        height: 92vh;
        height: 92dvh; /* Modern browsers - accounts for collapsing address bar */
        max-height: calc(100vh - env(safe-area-inset-top) - 20px);
        max-height: calc(100dvh - env(safe-area-inset-top) - 20px);
        background: var(--bg-primary);
        border-radius: 16px 16px 0 0;
        box-shadow: 0 -4px 20px var(--shadow);
        z-index: var(--z-modal);
        transform: translateY(100%);
        transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
        overflow: hidden;
        padding-bottom: env(safe-area-inset-bottom);
    }

    /* NOTE: .bottom-sheet.open class removed - JS uses inline transform directly */

    /* -------------------------------------------------------------------------
       Drag Handle Header
       ------------------------------------------------------------------------- */

    .bottom-sheet-header {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 12px 16px 8px;
        cursor: grab;
        user-select: none;
        -webkit-user-select: none;
        touch-action: none;
    }

    .bottom-sheet-header:active {
        cursor: grabbing;
    }

    .bottom-sheet-handle {
        width: 40px;
        height: 5px;
        /* More visible: lighter color with slight transparency */
        background: rgba(255, 255, 255, 0.35);
        border-radius: 2.5px;
        margin-bottom: 12px;
        transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
        /* Subtle glow to indicate interactivity */
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }

    /* Pulsing animation to indicate draggability on first view */
    @keyframes handle-pulse {
        0%, 100% { opacity: 0.6; transform: scaleX(1); }
        50% { opacity: 1; transform: scaleX(1.1); }
    }

    .bottom-sheet-handle.hint {
        animation: handle-pulse 1.5s ease-in-out 2;
    }

    .bottom-sheet-header:hover .bottom-sheet-handle {
        background: rgba(255, 255, 255, 0.5);
        transform: scaleX(1.05);
    }

    .bottom-sheet-header:active .bottom-sheet-handle {
        background: rgba(255, 255, 255, 0.65);
        transform: scaleX(1.15);
        box-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
    }

    /* Light theme adjustments */
    .light-theme .bottom-sheet-handle {
        background: rgba(0, 0, 0, 0.25);
    }

    .light-theme .bottom-sheet-header:hover .bottom-sheet-handle {
        background: rgba(0, 0, 0, 0.35);
    }

    .light-theme .bottom-sheet-header:active .bottom-sheet-handle {
        background: rgba(0, 0, 0, 0.45);
    }

    .bottom-sheet-header-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        padding: 0 4px;
    }

    .bottom-sheet-title {
        font-size: 1.1rem;
        font-weight: 600;
        color: var(--text-primary);
        margin: 0;
        flex: 1;
        text-align: center;
        padding-left: 36px;
    }

    /* -------------------------------------------------------------------------
       Close Button
       ------------------------------------------------------------------------- */

    .bottom-sheet-close {
        display: flex;
        align-items: center;
        justify-content: center;
        /* Touch target: 44px minimum (Apple HIG / WCAG 2.5.5) */
        width: 44px;
        height: 44px;
        background: var(--bg-tertiary);
        border: none;
        border-radius: 50%;
        color: var(--text-secondary);
        cursor: pointer;
        transition: background 0.2s ease, color 0.2s ease;
    }

    .bottom-sheet-close:hover {
        background: var(--border);
        color: var(--text-primary);
    }

    .bottom-sheet-close:focus-visible {
        outline: 2px solid var(--accent-blue);
        outline-offset: 2px;
    }

    .bottom-sheet-close:active {
        background: var(--border-light);
        /* --border-light is a mid-tone in both themes; the inherited
           --text-secondary drops to 3.0-3.3:1 against it. */
        color: var(--text-primary);
        transform: scale(0.95);
    }

    .bottom-sheet-close svg {
        width: 18px;
        height: 18px;
    }

    /* -------------------------------------------------------------------------
       Scrollable Content
       ------------------------------------------------------------------------- */

    .bottom-sheet-content {
        flex: 1;
        /* Enable vertical scrolling with proper min-height for flex item */
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
        padding: 0 16px 16px;
        /* Allow touch scrolling on the content area */
        touch-action: pan-y;
        /* Add padding at bottom for safe area and better UX */
        padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
        /* Scroll snap for section-based navigation (proximity = gentle snapping) */
        scroll-snap-type: y proximity;
        scroll-padding-top: 8px;
        /* Firefox scrollbar styling */
        scrollbar-width: thin;
        scrollbar-color: var(--border) transparent;
    }

    .bottom-sheet-content::-webkit-scrollbar {
        width: 4px;
    }

    .bottom-sheet-content::-webkit-scrollbar-track {
        background: transparent;
    }

    .bottom-sheet-content::-webkit-scrollbar-thumb {
        background: var(--border);
        border-radius: 2px;
    }

    /* -------------------------------------------------------------------------
       Floating Action Button (FAB)
       ------------------------------------------------------------------------- */

    .bottom-sheet-fab {
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        bottom: max(140px, calc(140px + env(safe-area-inset-bottom)));
        right: 16px;
        width: 56px;
        height: 56px;
        background: var(--accent-surface);
        color: var(--text-on-accent);
        border: none;
        border-radius: 50%;
        /* Fallback for browsers without color-mix() */
        box-shadow: 0 4px 12px rgba(233, 69, 96, 0.4),
                    0 2px 4px var(--shadow);
        cursor: pointer;
        z-index: var(--z-fab);
        transition: transform 0.2s ease;
    }

    @supports (background: color-mix(in srgb, red 50%, blue)) {
        .bottom-sheet-fab {
            box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent),
                        0 2px 4px var(--shadow);
        }
    }

    .bottom-sheet-fab:hover {
        transform: scale(1.05);
    }

    .bottom-sheet-fab:active {
        transform: scale(0.95);
    }

    /* Accessibility: Focus indicator for keyboard navigation */
    .bottom-sheet-fab:focus-visible {
        outline: 2px solid var(--text-on-accent);
        outline-offset: 3px;
    }

    .bottom-sheet-fab svg {
        width: 24px;
        height: 24px;
    }
}


/* ---- styles/features/bottom-sheet-controls.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Bottom Sheet Controls & Input Styles
 *
 * Interactive controls within the bottom sheet:
 * - Segmented tabs (Material Design 3 pattern)
 * - Quick action buttons
 * - Section headers and labels
 * - Input group (URL input + fetch button)
 * - Collapsible details sections
 * - Tech grid and badges
 */

@media (max-width: 768px) {
    /* -------------------------------------------------------------------------
       Segmented Tabs (Progressive Disclosure Pattern)
       -------------------------------------------------------------------------
       Tabs allow users to navigate between sections without scrolling.
       Follows Material Design 3 "Segmented buttons" pattern.
    */

    .bottom-sheet-tabs {
        display: flex;
        gap: 4px;
        padding: 0 16px 12px;
        background: var(--bg-primary);
        position: sticky;
        top: 0;
        z-index: 10;
    }

    .bottom-sheet-tab {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        padding: 10px 12px;
        background: var(--bg-tertiary);
        border: 1px solid var(--border);
        border-radius: 8px;
        color: var(--text-interactive);
        font-size: 0.8125rem;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.15s ease;
        -webkit-tap-highlight-color: transparent;
    }

    .bottom-sheet-tab:active {
        transform: scale(0.98);
    }

    .bottom-sheet-tab.active {
        background: var(--accent-surface);
        border-color: var(--accent);
        color: var(--text-on-accent);
    }

    .bottom-sheet-tab svg {
        width: 16px;
        height: 16px;
    }

    .bottom-sheet-tab-content {
        display: none;
    }

    .bottom-sheet-tab-content.active {
        display: block;
    }

    /* -------------------------------------------------------------------------
       Quick Actions
       ------------------------------------------------------------------------- */

    .bottom-sheet-quick-actions {
        display: flex;
        gap: 12px;
        padding: 0 16px 16px;
        border-bottom: 1px solid var(--border);
        margin-bottom: 16px;
    }

    .bottom-sheet-action-btn {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 8px;
        /* FIXED: Increase touch target to 48px minimum */
        min-height: 72px;
        padding: 14px 12px;
        background: var(--bg-tertiary);
        border: 1px solid var(--border);
        border-radius: 12px;
        color: var(--text-primary);
        font-size: 0.8125rem;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.2s ease;
        -webkit-tap-highlight-color: transparent;
    }

    .bottom-sheet-action-btn:active {
        transform: scale(0.97);
        background: var(--border);
    }

    .bottom-sheet-action-btn.primary {
        background: var(--accent-surface);
        border-color: var(--accent);
        color: var(--text-on-accent);
    }

    .bottom-sheet-action-btn.primary:active {
        background: var(--accent-hover);
    }

    .bottom-sheet-action-btn:disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }

    .bottom-sheet-action-btn svg {
        width: 24px;
        height: 24px;
    }

    /* Better focus states for accessibility */
    .bottom-sheet-action-btn:focus-visible {
        outline: 2px solid var(--accent-blue);
        outline-offset: 2px;
    }

    /* -------------------------------------------------------------------------
       Sections and Labels
       ------------------------------------------------------------------------- */

    .bottom-sheet-section {
        padding: 0 16px;
        margin-bottom: 16px;
        /* Scroll snap alignment for smooth section navigation */
        scroll-snap-align: start;
        scroll-margin-top: 8px;
    }

    /* Remove extra padding when section is inside quick-actions */
    .bottom-sheet-section:has(.bottom-sheet-quick-actions) {
        padding: 0;
    }

    .bottom-sheet-label {
        display: block;
        font-size: 0.75rem; /* 12px - WCAG minimum */
        font-weight: 700;
        color: var(--text-secondary);
        text-transform: uppercase;
        letter-spacing: 0.75px;
        margin-bottom: 10px;
    }

    .bottom-sheet-section-header {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem 0;
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--text-secondary);
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }

    .bottom-sheet-section-header svg {
        width: 14px;
        height: 14px;
    }

    /* -------------------------------------------------------------------------
       Input Group - Enhanced for Mobile
       ------------------------------------------------------------------------- */

    .bottom-sheet-input-group {
        display: flex;
        gap: 10px;
    }

    .bottom-sheet-input {
        flex: 1;
        padding: 14px 16px;
        background: var(--bg-tertiary);
        border: 1px solid var(--border);
        border-radius: 12px;
        color: var(--text-primary);
        font-size: 1rem;
        -webkit-appearance: none;
        /* Prevent iOS zoom on focus */
        font-size: 16px;
    }

    .bottom-sheet-input:focus {
        outline: none;
        border-color: var(--accent);
        box-shadow: 0 0 0 3px rgba(233, 69, 96, 0.15);
    }

    .bottom-sheet-input:focus-visible {
        outline: 2px solid var(--accent-blue);
        outline-offset: 2px;
    }

    .bottom-sheet-input::placeholder {
        color: var(--text-muted);
        font-size: 0.9375rem;
    }

    .bottom-sheet-fetch-btn {
        width: 52px;
        height: 52px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: var(--accent-surface);
        border: none;
        border-radius: 12px;
        color: var(--text-on-accent);
        cursor: pointer;
        flex-shrink: 0;
        transition: background 0.2s ease, transform 0.15s ease;
        -webkit-tap-highlight-color: transparent;
    }

    .bottom-sheet-fetch-btn:active {
        background: var(--accent-hover);
        transform: scale(0.95);
    }

    .bottom-sheet-fetch-btn:disabled {
        background: var(--bg-tertiary);
        border: 1px solid var(--border);
        color: var(--text-muted);
        cursor: not-allowed;
    }

    .bottom-sheet-fetch-btn:focus-visible {
        outline: 2px solid var(--accent-blue);
        outline-offset: 2px;
    }

    .bottom-sheet-fetch-btn svg {
        width: 18px;
        height: 18px;
    }

    .bottom-sheet-hint {
        font-size: 0.75rem;
        color: var(--text-muted);
        margin-top: 10px;
        padding-left: 2px;
    }

    /* -------------------------------------------------------------------------
       Collapsible Details - Mobile Optimized
       ------------------------------------------------------------------------- */

    .bottom-sheet-details {
        margin: 0 16px 10px;
        background: var(--bg-secondary);
        border: 1px solid var(--border);
        border-radius: 12px;
        overflow: hidden;
    }

    .bottom-sheet-summary {
        display: flex;
        align-items: center;
        gap: 12px;
        /* Min 48px touch target */
        min-height: 52px;
        padding: 14px 16px;
        font-size: 0.9375rem;
        font-weight: 600;
        color: var(--text-primary);
        cursor: pointer;
        list-style: none;
        -webkit-tap-highlight-color: transparent;
        transition: background 0.15s ease;
    }

    .bottom-sheet-summary:active {
        background: var(--bg-tertiary);
    }

    .bottom-sheet-summary::-webkit-details-marker {
        display: none;
    }

    .bottom-sheet-summary::after {
        content: '';
        margin-left: auto;
        width: 0;
        height: 0;
        border-left: 6px solid transparent;
        border-right: 6px solid transparent;
        border-top: 6px solid var(--text-muted);
        transition: transform 0.2s ease;
    }

    .bottom-sheet-details[open] .bottom-sheet-summary::after {
        transform: rotate(180deg);
    }

    .bottom-sheet-details[open] .bottom-sheet-summary {
        border-bottom: 1px solid var(--border);
    }

    .bottom-sheet-summary svg {
        width: 18px;
        height: 18px;
        color: var(--accent);
        flex-shrink: 0;
    }

    .bottom-sheet-details-content {
        padding: 14px 16px 16px;
        font-size: 0.875rem;
        color: var(--text-secondary);
        line-height: 1.6;
    }

    .bottom-sheet-details-content p {
        margin: 0 0 10px;
    }

    .bottom-sheet-details-content ul {
        margin: 10px 0;
        padding-left: 20px;
    }

    .bottom-sheet-details-content li {
        margin-bottom: 6px;
    }

    .bottom-sheet-details-content strong {
        color: var(--text-primary);
    }

    /* Tech Grid in Details */
    .bottom-sheet-tech-grid {
        display: flex;
        justify-content: space-around;
        gap: 12px;
        padding: 10px 0;
        margin-bottom: 12px;
    }

    .bottom-sheet-tech-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 4px;
    }

    .bottom-sheet-tech-value {
        font-size: 1rem;
        font-weight: 700;
        color: var(--text-primary);
    }

    .bottom-sheet-tech-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        font-weight: 600;
        color: var(--text-secondary);
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }

    /* Tech Badges */
    .bottom-sheet-badges {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        justify-content: center;
    }

    .bottom-sheet-badge {
        display: inline-block;
        padding: 4px 10px;
        background: var(--bg-tertiary);
        border-radius: 12px;
        font-size: 0.75rem; /* 12px - WCAG minimum */
        font-weight: 600;
        color: var(--text-interactive);
    }
}


/* ---- styles/features/bottom-sheet-legends.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Bottom Sheet Legends & Content Styles
 *
 * Content sections within the bottom sheet:
 * - File type legend with color dots and counts
 * - Author items with commit counts
 * - Footer links
 * - Compact panel overrides for embedded panels
 * - Extra small screen (375px) adjustments
 *
 * NOTE: Landscape-specific bottom sheet rules are consolidated in
 * mobile-landscape.css for consistency with other mobile landscape
 * optimizations.
 */

@media (max-width: 768px) {
    /* -------------------------------------------------------------------------
       Legend Section - Improved Visual Hierarchy
       ------------------------------------------------------------------------- */

    .bottom-sheet-legends {
        display: flex;
        flex-direction: column;
        gap: 12px;
        margin-bottom: 16px;
        padding: 0 16px;
    }

    /* Show legends section when visible (JS removes hidden class) */
    .bottom-sheet-legends:not(.hidden) {
        display: flex;
    }

    .bottom-sheet-legend-section {
        background: var(--bg-tertiary);
        border-radius: 12px;
        padding: 12px 14px;
        border: 1px solid var(--border);
    }

    .bottom-sheet-legend-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 10px;
        padding-bottom: 6px;
        border-bottom: 1px solid var(--border);
    }

    .bottom-sheet-legend-title {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        font-weight: 700;
        color: var(--text-secondary);
        text-transform: uppercase;
        letter-spacing: 0.75px;
    }

    .bottom-sheet-legend-items {
        display: flex;
        flex-wrap: wrap;
        gap: 6px 8px;
    }

    .bottom-sheet-legend-item {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        /* A4: Increase touch target to 44px minimum (Apple HIG) */
        padding: 10px 14px;
        min-height: 44px;
        background: var(--bg-secondary);
        border-radius: 22px;
        font-size: 0.8125rem; /* 13px for better readability */
        white-space: nowrap;
        transition: background 0.15s ease;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    /* Subtle hover feedback */
    .bottom-sheet-legend-item:active {
        background: var(--border);
    }

    .bottom-sheet-legend-color {
        /* A4: Slightly larger color dot for better visibility */
        width: 12px;
        height: 12px;
        border-radius: 50%;
        flex-shrink: 0;
        /* Add subtle shadow for depth */
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }

    .bottom-sheet-legend-name {
        color: var(--text-primary);
        font-weight: 500;
    }

    .bottom-sheet-legend-count {
        color: var(--text-muted);
        font-size: 0.75rem; /* 12px - WCAG minimum (was 0.6875rem/11px) */
        font-weight: 500;
        font-variant-numeric: tabular-nums;
    }

    /* "More" indicator for overflow - now a clickable button */
    .bottom-sheet-legend-more {
        display: inline-flex;
        align-items: center;
        padding: 5px 10px;
        color: var(--text-muted);
        font-size: 0.75rem;
        font-weight: 500;
    }

    /* Expand/Collapse toggle button for legends */
    .bottom-sheet-legend-toggle {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 6px 12px;
        margin-top: 6px;
        background: var(--bg-secondary);
        border: 1px solid var(--border);
        border-radius: 16px;
        color: var(--accent-blue);
        font-size: 0.75rem;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.15s ease;
        -webkit-tap-highlight-color: transparent;
        /* Full width to make it easier to tap */
        width: 100%;
        justify-content: center;
    }

    .bottom-sheet-legend-toggle:hover {
        background: var(--bg-tertiary);
        border-color: var(--accent-blue);
    }

    .bottom-sheet-legend-toggle:active {
        transform: scale(0.98);
        background: var(--border);
    }

    .bottom-sheet-legend-toggle:focus-visible {
        outline: 2px solid var(--accent-blue);
        outline-offset: 2px;
    }

    .bottom-sheet-legend-toggle svg {
        flex-shrink: 0;
    }

    /* Light theme toggle button */
    .light-theme .bottom-sheet-legend-toggle {
        background: var(--bg-primary);
    }

    .light-theme .bottom-sheet-legend-toggle:hover {
        background: var(--bg-secondary);
    }

    /* -------------------------------------------------------------------------
       Author Items - Enhanced for Mobile
       ------------------------------------------------------------------------- */

    .bottom-sheet-author-item {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        padding: 6px 12px;
        background: var(--bg-secondary);
        border-radius: 16px;
        transition: background 0.15s ease;
    }

    .bottom-sheet-author-item:active {
        background: var(--border);
    }

    .bottom-sheet-author-color {
        width: 12px;
        height: 12px;
        border-radius: 50%;
        flex-shrink: 0;
        border: 1px solid rgba(255, 255, 255, 0.2);
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }

    .bottom-sheet-author-name {
        font-size: 0.8125rem;
        font-weight: 500;
        color: var(--text-primary);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 120px;
    }

    .bottom-sheet-author-commits {
        font-size: 0.75rem;
        font-weight: 500;
        color: var(--text-muted);
        font-variant-numeric: tabular-nums;
    }

    /* -------------------------------------------------------------------------
       Footer Links
       ------------------------------------------------------------------------- */

    .bottom-sheet-footer {
        display: flex;
        justify-content: center;
        gap: 16px;
        padding: 16px;
        margin-top: auto;
        border-top: 1px solid var(--border);
    }

    .bottom-sheet-link {
        display: flex;
        align-items: center;
        gap: 6px;
        font-size: 0.8125rem;
        color: var(--accent-blue);
        text-decoration: none;
    }

    .bottom-sheet-link svg {
        width: 14px;
        height: 14px;
    }

    /* -------------------------------------------------------------------------
       Compact Panels in Bottom Sheet
       ------------------------------------------------------------------------- */

    .bottom-sheet .showcase-panel {
        padding: 1rem;
        margin-bottom: 0.75rem;
    }

    .bottom-sheet .showcase-panel h2 {
        font-size: 1rem;
    }

    .bottom-sheet .showcase-panel p {
        font-size: 0.85rem;
    }

    .bottom-sheet .showcase-stats {
        gap: 0.5rem;
    }

    .bottom-sheet .showcase-stat-value {
        font-size: 1.25rem;
    }

    .bottom-sheet .panel {
        margin-bottom: 0.75rem;
    }

    .bottom-sheet .panel-header h2 {
        font-size: 0.95rem;
    }

    .bottom-sheet .panel.collapsible .panel-body {
        padding: 0.75rem;
    }

    .bottom-sheet .docs-section {
        padding: 0.5rem 0;
    }

    .bottom-sheet .docs-section h3 {
        font-size: 0.9rem;
    }

    .bottom-sheet .docs-section p,
    .bottom-sheet .docs-section li {
        font-size: 0.85rem;
    }

    .bottom-sheet .tab-nav {
        gap: 0.25rem;
    }

    .bottom-sheet .tab-btn {
        padding: 0.4rem 0.75rem;
        font-size: 0.8rem;
    }

    .bottom-sheet .about-banner {
        padding: 1rem;
        margin-top: 0.5rem;
    }

    .bottom-sheet .about-banner h2 {
        font-size: 1rem;
    }
}

/* =============================================================================
   Extra Small Screens (iPhone SE)
   ============================================================================= */

@media (max-width: 375px) {
    .bottom-sheet-fab {
        width: 52px;
        height: 52px;
        right: 12px;
    }

    .bottom-sheet-content {
        padding: 0 12px 12px;
    }

    .bottom-sheet-quick-actions {
        padding: 0 12px 10px;
    }
}

/* Mobile responsive overrides (should be last to override other styles) */

/* ---- styles/features/mobile-sidebar.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Mobile Sidebar Styles
 *
 * Sidebar toggle button, slide-out drawer, close button, and overlay.
 * At 1200px the sidebar becomes a fixed-position drawer.
 * At 480px the drawer expands to full width with safe-area insets.
 *
 * Breakpoints:
 * - 1200px: Sidebar becomes slide-out drawer
 * - 480px: Full-width drawer with safe areas
 */

/* =============================================================================
   Mobile Sidebar Toggle
   ============================================================================= */

.sidebar-toggle {
    display: none;
    position: fixed;
    bottom: 20px;
    right: 20px;
    background: var(--accent-surface);
    color: var(--text-on-accent);
    border: none;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    cursor: pointer;
    z-index: var(--z-sticky);
    /* Fallback for browsers without color-mix() */
    box-shadow: 0 4px 12px rgba(233, 69, 96, 0.4);
    /* Use composited properties only for better performance */
    transition: opacity 0.3s, transform 0.3s;
}

@supports (background: color-mix(in srgb, red 50%, blue)) {
    .sidebar-toggle {
        box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent);
    }
}

.sidebar-toggle:hover {
    transform: scale(1.1);
    background: var(--accent-hover);
}

.sidebar-toggle:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

.sidebar-toggle svg {
    width: 24px;
    height: 24px;
}

/* Enforce hidden when view-manager.js sets hidden attribute.
   Without this, the 1200px media query display:flex overrides
   the UA [hidden]{display:none}. */
.sidebar-toggle[hidden] {
    display: none;
}

/* =============================================================================
   Tablet Breakpoint (1200px) - Sidebar Drawer
   ============================================================================= */

@media (max-width: 1200px) {
    .sidebar-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .sidebar-panel {
        position: fixed;
        top: 0;
        right: 0;
        width: min(100%, 400px);
        height: 100%;
        max-height: 100%;
        background: var(--bg-primary);
        z-index: var(--z-sidebar-drawer);
        transform: translateX(100%);
        transition: transform 0.3s ease;
        padding: 1rem;
        padding-top: 60px;
        box-shadow: -4px 0 20px var(--shadow);
        overflow-y: auto;
        overflow-x: hidden;
    }

    .sidebar-panel.open {
        transform: translateX(0);
    }

    .sidebar-close {
        position: absolute;
        top: 10px;
        right: 10px;
        background: var(--bg-tertiary);
        border: 1px solid var(--border);
        color: var(--text-secondary);
        /* Touch target: 44px minimum (Apple HIG / WCAG 2.5.5) */
        width: 44px;
        height: 44px;
        border-radius: 6px;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: var(--z-base);
    }

    .sidebar-close:hover {
        background: var(--border);
        color: var(--text-primary);
    }

    .sidebar-close:focus-visible {
        outline: 2px solid var(--accent-blue);
        outline-offset: 2px;
    }

    .sidebar-overlay {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: var(--backdrop);
        z-index: var(--z-sidebar-overlay);
        opacity: 0;
        visibility: hidden;
        /* Use composited properties only for better performance */
        transition: opacity 0.3s, visibility 0.3s;
    }

    .sidebar-overlay.visible {
        opacity: 1;
        visibility: visible;
    }

    /* Sidebar scroll indicator - position inside fixed sidebar */
    .sidebar-scroll-indicator {
        position: fixed;
        bottom: 0;
        right: 0;
        width: min(100%, 400px);
        z-index: var(--z-sidebar-scroll);
        opacity: 0;
        visibility: hidden;
    }

    .sidebar-panel.open + .sidebar-scroll-indicator {
        opacity: 1;
        visibility: visible;
    }

    .sidebar-panel.open + .sidebar-scroll-indicator.hidden {
        opacity: 0;
    }

    /* Main content takes full width when sidebar is closed */
    .app-container {
        grid-template-columns: 1fr;
        grid-template-rows: 1fr;
    }
}

/* =============================================================================
   Extra Small Screens (480px) - Full Width Sidebar
   ============================================================================= */

@media (max-width: 480px) {
    .sidebar-panel {
        width: 100%;
        padding: 0.75rem;
        padding-top: 50px;
        /* Support for notched devices (iPhone X+, etc.) */
        padding-left: max(0.75rem, env(safe-area-inset-left));
        padding-right: max(0.75rem, env(safe-area-inset-right));
        padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
    }
}


/* ---- styles/features/mobile-toolbar.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Mobile Toolbar Styles
 *
 * Floating quick-action toolbar positioned in the thumb zone.
 * Includes toolbar buttons with labels, uncapped FPS toggle,
 * and auto-hide behavior during playback.
 *
 * THUMB ZONE DESIGN:
 * - Positioned at BOTTOM of screen for easy one-handed reach
 * - Industry standard: bottom third is "easy to reach" zone
 * - Touch targets: minimum 44px (Apple HIG) / ideally 48-60px for games
 *
 * References:
 * - NN/g: https://www.nngroup.com/articles/touch-target-size/
 * - Material Design 3: 48dp minimum touch target
 * - Apple HIG: 44pt minimum
 */

.mobile-toolbar {
    display: none; /* Hidden on desktop */
}

@media (max-width: 768px) {
    .has-bottom-sheet .mobile-toolbar {
        display: flex;
        position: absolute;
        /* CENTER the toolbar at the bottom for balanced layout */
        bottom: 8px;
        left: 50%;
        transform: translateX(-50%);
        z-index: var(--z-canvas-overlays);
        background: rgba(22, 27, 34, 0.92);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        border-radius: 24px;
        padding: 6px 12px;
        gap: 4px;
        border: 1px solid var(--border);
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
        /* Auto-hide support */
        transition: opacity 0.3s ease, transform 0.3s ease;
        /* Center buttons within toolbar */
        align-items: center;
        justify-content: center;
    }

    /* Auto-hide when playing - more visible and animated like FAB */
    .has-bottom-sheet.controls-hidden .mobile-toolbar {
        opacity: 0.3;
        /* Maintain center position while animating down */
        transform: translateX(-50%) translateY(8px);
        /* Keep pointer-events: auto so user can tap to show controls */
        pointer-events: auto;
        /* Match FAB pulse animation for consistency */
        animation: toolbar-pulse 3s ease-in-out infinite;
    }

    @keyframes toolbar-pulse {
        0%, 100% { opacity: 0.25; }
        50% { opacity: 0.4; }
    }

    .has-bottom-sheet.controls-hidden .mobile-toolbar:active {
        opacity: 0.6;
        animation: none;
        transform: translateX(-50%) translateY(8px);
    }

    /* While the toolbar is dormant its labels are not rendered.
     *
     * Fading the toolbar to 0.3 during playback is the right instinct — the
     * chrome gets out of the way of the visualization — but it drags the label
     * text down to 1.41:1, which is text that is present and unreadable rather
     * than absent. `visibility: hidden` removes it from rendering (so it is
     * neither read nor measured) while holding the layout, so nothing shifts
     * when the toolbar comes back on tap. The icons remain as the affordance.
     *
     * This was invisible to earlier sweeps because the first-run help modal
     * covered the toolbar; the audit only found it once the modal was
     * dismissed the way a visitor dismisses it. */
    .has-bottom-sheet.controls-hidden .mobile-toolbar .btn-label {
        visibility: hidden;
    }

    /* Also hide stats overlay when controls are hidden for cleaner view */
    .has-bottom-sheet.controls-hidden .stats-overlay {
        opacity: 0.2;
        transition: opacity 0.3s ease;
    }

    /* -------------------------------------------------------------------------
       Toolbar Buttons
       ------------------------------------------------------------------------- */

    .mobile-toolbar-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        /* FIXED: Increase to 44px minimum touch target */
        width: 44px;
        height: 44px;
        background: transparent;
        border: none;
        border-radius: 12px;
        color: var(--text-secondary);
        cursor: pointer;
        transition: background 0.15s ease, transform 0.15s ease, color 0.15s ease;
        -webkit-tap-highlight-color: transparent;
        /* Ensure buttons are clickable */
        pointer-events: auto;
        position: relative;
        z-index: 1;
    }

    .mobile-toolbar-btn:hover {
        background: var(--bg-tertiary);
        color: var(--text-primary);
    }

    .mobile-toolbar-btn:active {
        background: var(--bg-tertiary);
        transform: scale(0.92);
    }

    /* Labels toggle active state - clearer visual distinction */
    .mobile-toolbar-btn.active {
        /* --accent on its own 18% tint measures 3.8:1. The tint and the inset
           ring already carry the active state, so the label uses the brightest
           text token instead of the accent. */
        color: var(--text-primary);
        background: color-mix(in srgb, var(--accent) 18%, transparent);
        /* Add subtle border for better visibility */
        box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--accent) 30%, transparent);
    }

    .mobile-toolbar-btn.active:active {
        background: color-mix(in srgb, var(--accent) 25%, transparent);
        transform: scale(0.92);
    }

    .mobile-toolbar-btn:disabled {
        opacity: 0.4;
        cursor: not-allowed;
        pointer-events: none;
    }

    .mobile-toolbar-btn svg {
        width: 20px;
        height: 20px;
        /* Ensure SVG doesn't capture pointer events */
        pointer-events: none;
    }

    /* -------------------------------------------------------------------------
       Toolbar Button Labels (A1: No mystery meat navigation)
       -------------------------------------------------------------------------
       Shows text labels below icons for accessibility and discoverability.
       Labels are always visible to comply with WCAG and avoid "mystery meat"
       navigation where users must guess what icons mean.
    */
    .mobile-toolbar-btn {
        flex-direction: column;
        gap: 2px;
        padding: 4px 8px;
        /* FIXED: Use auto width with min-width to prevent text truncation */
        min-width: 48px;
        width: auto;
    }

    .mobile-toolbar-btn .btn-label {
        display: block;
        font-size: 0.75rem; /* 12px - WCAG minimum readable size */
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.2px;
        white-space: nowrap;
        opacity: 0.9;
        line-height: 1;
        /* Ensure text doesn't overflow */
        overflow: visible;
    }

    .mobile-toolbar-btn.active .btn-label {
        opacity: 1;
    }

    /* Theme button icon visibility */
    .mobile-toolbar-btn .sun-icon {
        display: none;
    }

    .mobile-toolbar-btn .moon-icon {
        display: block;
    }

    .light-theme .mobile-toolbar-btn .sun-icon {
        display: block;
    }

    .light-theme .mobile-toolbar-btn .moon-icon {
        display: none;
    }

    .mobile-toolbar-divider {
        width: 1px;
        height: 28px;
        background: var(--border);
        margin: 0 4px;
        align-self: center;
    }

    /* -------------------------------------------------------------------------
       Quick-Access Uncapped FPS Toggle (Mobile Toolbar)
       -------------------------------------------------------------------------

       Prominently placed in mobile toolbar for easy discoverability.
       Uses flame icon and orange accent when active (like "turbo" mode).
       Follows video game "boost" UI patterns.
    */

    .mobile-toolbar-btn.uncapped-toggle {
        position: relative;
    }

    /* Active state - orange glow like "turbo/boost" in games */
    .mobile-toolbar-btn.uncapped-toggle.active {
        color: var(--accent-orange);
        /* Fallback for browsers without color-mix() */
        background: rgba(255, 107, 53, 0.2);
    }

    .mobile-toolbar-btn.uncapped-toggle.active::before {
        content: '';
        position: absolute;
        inset: -2px;
        border-radius: 14px;
        /* Fallback for browsers without color-mix() */
        background: rgba(255, 107, 53, 0.15);
        animation: uncapped-pulse 2s ease-in-out infinite;
        z-index: -1;
    }

    @supports (background: color-mix(in srgb, red 50%, blue)) {
        .mobile-toolbar-btn.uncapped-toggle.active {
            background: color-mix(in srgb, var(--accent-orange) 20%, transparent);
        }

        .mobile-toolbar-btn.uncapped-toggle.active::before {
            background: color-mix(in srgb, var(--accent-orange) 15%, transparent);
        }
    }

    @keyframes uncapped-pulse {
        0%, 100% { opacity: 0.5; transform: scale(1); }
        50% { opacity: 1; transform: scale(1.05); }
    }

    /* Uncapped indicator badge on FPS display */
    .has-bottom-sheet .perf-overlay .perf-fps.uncapped::after {
        content: 'MAX';
        display: inline-block;
        margin-left: 4px;
        font-size: 0.75rem; /* 12px - WCAG minimum */
        font-weight: 700;
        background: var(--accent-orange-surface);
        color: var(--text-on-warning);
        padding: 2px 4px;
        border-radius: 4px;
        vertical-align: middle;
        letter-spacing: 0.5px;
    }
}


/* ---- styles/features/mobile-hud.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Mobile HUD Styles
 *
 * Video game-inspired heads-up display for mobile:
 * - Header adjustments and FAB positioning
 * - Stats overlay (commits/files/dirs/authors) in top-left
 * - Performance overlay (FPS/frame time) in top-right
 * - Collapsible stats panel (L1)
 * - High-score style metrics display
 * - Auto-hide timeline controls (YouTube/Netflix pattern)
 * - Minimal HUD (I6: date/progress when controls hidden)
 * - Center play button (tap-to-show overlay)
 *
 * References:
 * - FPS games: minimal HUDs prioritizing essential info
 * - High score displays: prominent primary metric + secondary stats
 * - Steam FPS counter: small corner pill with bold number
 */

/* =============================================================================
   Mobile Center Play Button - Base Styles (Hidden on Desktop)
   ============================================================================= */

/*
 * CRITICAL: The mobile-center-play button must be hidden by default on ALL
 * screen sizes. The @media query below provides mobile-specific styling,
 * but we need base hidden state to prevent flash of unstyled content on
 * page load (especially in Firefox where CSS parsing timing can vary).
 */
.mobile-center-play {
    display: none;
}

/* =============================================================================
   Mobile Header & HUD Adjustments (768px)
   ============================================================================= */

@media (max-width: 768px) {
    header {
        /* L5/L6: Safe area support + better mobile padding */
        padding: 10px 12px;
        padding-top: max(10px, env(safe-area-inset-top, 0px));
        padding-left: max(12px, env(safe-area-inset-left, 0px));
        padding-right: max(12px, env(safe-area-inset-right, 0px));
        justify-content: space-between;
        flex-wrap: nowrap;
        gap: 8px;
    }

    .header-brand {
        flex-shrink: 0;
        /* L6: Prevent brand from being too cramped */
        min-width: 0;
    }

    .header-brand h1 {
        font-size: 1.125rem;
        /* L6: Allow text to truncate gracefully if needed */
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .logo-icon {
        width: 24px;
        height: 24px;
        flex-shrink: 0;
    }

    /* Hide controls in header on mobile with bottom sheet */
    .has-bottom-sheet header .controls {
        display: none !important;
    }

    .has-bottom-sheet .header-links {
        display: none !important;
    }

    /* FAB repositioned for mobile - right corner, above timeline
       FIXED: Move higher to avoid overlapping author info in timeline date row
       Timeline is ~110-130px, but author info appears at top of timeline (~160px from bottom) */
    .has-bottom-sheet .bottom-sheet-fab {
        bottom: max(175px, calc(175px + env(safe-area-inset-bottom)));
        right: 12px;
        /* 56px is Material Design 3 standard FAB size */
        width: 56px;
        height: 56px;
        z-index: var(--z-fab);
        /* Auto-hide support */
        transition: opacity 0.3s ease, transform 0.3s ease;
    }

    /* Auto-hide FAB when playing - more visible and animated to hint tappability */
    .has-bottom-sheet.controls-hidden .bottom-sheet-fab {
        opacity: 0.4;
        transform: scale(0.85);
        /* Keep pointer-events: auto so user can tap to show controls */
        pointer-events: auto;
        /* Subtle pulse animation to hint that FAB can be tapped */
        animation: fab-pulse 3s ease-in-out infinite;
    }

    @keyframes fab-pulse {
        0%, 100% { opacity: 0.35; transform: scale(0.85); }
        50% { opacity: 0.5; transform: scale(0.88); }
    }

    /* Visual feedback when tapping hidden FAB */
    .has-bottom-sheet.controls-hidden .bottom-sheet-fab:active {
        opacity: 0.7;
        transform: scale(0.8);
        animation: none;
    }

    /* App container full width on mobile */
    .has-bottom-sheet .app-container {
        padding: 0;
        gap: 0;
    }

    /* CRITICAL: Hide legend and authors panels on mobile - they're in bottom sheet */
    .has-bottom-sheet .legend-panel {
        display: none !important;
    }

    .has-bottom-sheet .authors-panel {
        display: none !important;
    }

    /* -------------------------------------------------------------------------
       Stats Overlay - Mobile HUD Layout
       -------------------------------------------------------------------------
       Shows commits/files/dirs/authors as a compact HUD in TOP-LEFT corner.
       This keeps it out of the way and doesn't cramp the canvas area.

       Layout:
       - Top-left: Stats overlay (secondary info)
       - Top-right: Perf overlay (FPS/frame time)
       - Bottom-center: Mobile toolbar (actions)
       - Bottom-right: FAB (menu)
    */

    .has-bottom-sheet .stats-overlay {
        /* Top-left HUD positioning */
        top: max(8px, env(safe-area-inset-top));
        left: max(8px, env(safe-area-inset-left));
        bottom: auto;
        right: auto;
        transform: none;
        padding: 6px 12px;
        border-radius: 16px;
        background: rgba(0, 0, 0, 0.75);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        border: 1px solid rgba(255, 255, 255, 0.08);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
        gap: 12px;
        font-size: 0.75rem; /* 12px - WCAG minimum */
        /* Compact width */
        max-width: 200px;
    }

    .has-bottom-sheet .stats-overlay .stat-item {
        flex-direction: row;
        gap: 3px;
        white-space: nowrap;
    }

    .has-bottom-sheet .stats-overlay .stat-value {
        font-size: 0.75rem;
        font-weight: 700;
    }

    .has-bottom-sheet .stats-overlay .stat-label {
        font-size: 0.75rem; /* 12px - WCAG minimum readable size */
        text-transform: uppercase;
        letter-spacing: 0.3px;
        opacity: 0.8;
    }

    /* -------------------------------------------------------------------------
       L1: Collapsible Stats Panel
       -------------------------------------------------------------------------
       Stats panel collapses to a minimal indicator during playback.
       Tap to expand, auto-collapse when playing resumes.
       Maximizes visualization area (target: 85%+ during playback).
    */
    .has-bottom-sheet .stats-overlay {
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* Collapsed state - minimal indicator */
    .has-bottom-sheet .stats-overlay.collapsed {
        padding: 4px 10px;
        gap: 6px;
    }

    .has-bottom-sheet .stats-overlay.collapsed .stat-item {
        display: none;
    }

    /* Show only first stat (commits) when collapsed */
    .has-bottom-sheet .stats-overlay.collapsed .stat-item:first-child {
        display: flex;
    }

    /* Add expand indicator when collapsed */
    .has-bottom-sheet .stats-overlay.collapsed::after {
        content: '\203A';
        font-size: 0.75rem;
        color: var(--text-muted);
        margin-left: 4px;
        transition: transform 0.2s ease;
    }

    .has-bottom-sheet .stats-overlay:not(.collapsed)::after {
        content: '';
    }

    /* Tap feedback */
    .has-bottom-sheet .stats-overlay:active {
        transform: scale(0.97);
    }

    /* -------------------------------------------------------------------------
       Performance Overlay - HUD Style
       -------------------------------------------------------------------------
       Compact pill in top-right corner with FPS as primary metric.
    */

    /* HUD-style container - compact pill in top-right */
    .has-bottom-sheet .perf-overlay {
        top: 8px;
        right: 8px;
        left: auto;
        min-width: auto;
        padding: 8px 12px;
        border-radius: 16px;
        background: rgba(0, 0, 0, 0.8);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        border: 1px solid rgba(255, 255, 255, 0.15);
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
        /* Touch-friendly tap area */
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    /* Tap hint indicator */
    .has-bottom-sheet .perf-overlay::after {
        content: '';
        position: absolute;
        top: 4px;
        right: 4px;
        width: 6px;
        height: 6px;
        background: var(--text-muted);
        border-radius: 50%;
        opacity: 0.5;
        transition: opacity 0.2s ease;
    }

    .has-bottom-sheet .perf-overlay:not(.collapsed)::after {
        opacity: 0;
    }

    .has-bottom-sheet .perf-overlay:active {
        transform: scale(0.98);
    }

    /* HUD header - horizontal layout with FPS prominent */
    .has-bottom-sheet .perf-overlay .perf-header {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-bottom: 0;
    }

    /* FPS as primary metric - video game style */
    .has-bottom-sheet .perf-overlay .perf-fps {
        font-size: 1rem;
        font-weight: 700;
        min-width: 70px;
        text-align: center;
        letter-spacing: -0.5px;
    }

    /* Hide default toggle arrow on mobile */
    .has-bottom-sheet .perf-overlay .perf-toggle {
        display: none;
    }

    /* Compact details row - inline layout */
    .has-bottom-sheet .perf-overlay .perf-details {
        display: flex;
        flex-wrap: wrap;
        gap: 6px 12px;
        margin-top: 6px;
        padding-top: 6px;
        border-top: 1px solid rgba(255, 255, 255, 0.1);
    }

    /* Individual metric rows - horizontal compact style */
    .has-bottom-sheet .perf-overlay .perf-row {
        flex: none;
        gap: 4px;
        font-size: 0.75rem; /* 12px - WCAG minimum readable size */
    }

    .has-bottom-sheet .perf-overlay .perf-label {
        font-weight: 500;
        text-transform: uppercase;
        letter-spacing: 0.3px;
        /* No opacity here: 0.7 on --text-muted measured 3.69:1 against the
           canvas. Opacity is invisible to token-level contrast checks, so
           dim a label by choosing a dimmer token, never by fading it. */
    }

    /* Uncapped toggle - PROMINENT button style for discoverability */
    .has-bottom-sheet .perf-overlay .perf-toggle-row {
        margin-top: 0;
        padding-top: 0;
        border-top: none;
        flex-basis: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        margin-top: 6px;
        padding-top: 8px;
        border-top: 1px solid rgba(255, 255, 255, 0.1);
    }

    /* Uncapped label - more prominent */
    .has-bottom-sheet .perf-overlay #perf-uncapped-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        color: var(--text-secondary);
    }

    /* Larger toggle switch for touch - 44px tap zone */
    .has-bottom-sheet .perf-overlay .perf-switch {
        width: 44px;
        height: 24px;
        position: relative;
    }

    .has-bottom-sheet .perf-overlay .perf-slider {
        border-radius: 24px;
    }

    .has-bottom-sheet .perf-overlay .perf-slider::before {
        height: 18px;
        width: 18px;
        bottom: 3px;
        left: 3px;
    }

    .has-bottom-sheet .perf-overlay .perf-switch input:checked + .perf-slider::before {
        transform: translateX(20px);
    }

    /* Peak/Avg row - high-score style display */
    .has-bottom-sheet .perf-overlay .perf-peak-avg-row:not(.hidden) {
        display: flex;
        justify-content: center;
        gap: 12px;
        max-height: 2rem;
        opacity: 1;
    }

    .has-bottom-sheet .perf-overlay .perf-peak-avg-value {
        font-size: 0.75rem;
        font-weight: 600;
        display: flex;
        gap: 4px;
    }

    /* Backend indicator - compact badge */
    .has-bottom-sheet .perf-overlay .perf-backend {
        font-size: 0.75rem; /* 12px - WCAG minimum */
        padding: 2px 6px;
        border-radius: 8px;
    }

    /* Collapsed state - ultra-compact FPS badge only */
    .has-bottom-sheet .perf-overlay.collapsed {
        padding: 4px 10px;
        border-radius: 16px;
    }

    .has-bottom-sheet .perf-overlay.collapsed .perf-fps {
        min-width: auto;
        font-size: 0.85rem;
    }

    /* -------------------------------------------------------------------------
       High-Score Style Metrics Display
       -------------------------------------------------------------------------

       Inspired by video game leaderboards and achievement displays:
       - Peak FPS highlighted as "personal best"
       - Color-coded frame time (green < 16.7ms, yellow < 33ms, red > 33ms)
       - Compact "score" badges for key metrics
    */

    /* Frame time color coding (video game style) */
    .has-bottom-sheet .perf-overlay .perf-value[data-metric="frame"] {
        font-weight: 600;
    }

    /* Peak FPS - "high score" gold badge styling */
    .has-bottom-sheet .perf-overlay .perf-peak-avg-value span:first-child {
        color: #ffd700;
        font-weight: 700;
        text-shadow: 0 0 6px rgba(255, 215, 0, 0.4);
    }

    /* Avg FPS - silver styling */
    .has-bottom-sheet .perf-overlay .perf-peak-avg-value span:last-child {
        color: #c0c0c0;
    }

    /* Expanded state - show all metrics with high-score layout */
    .has-bottom-sheet .perf-overlay:not(.collapsed) .perf-header {
        padding-bottom: 6px;
        margin-bottom: 6px;
        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    }

    /* FPS number glow effect when hitting high values */
    .has-bottom-sheet .perf-overlay .perf-fps.good {
        text-shadow: 0 0 8px rgba(63, 185, 80, 0.5);
    }

    .has-bottom-sheet .perf-overlay .perf-fps.uncapped {
        text-shadow: 0 0 8px rgba(255, 107, 53, 0.5);
    }

    /* Achievement-style backend badge */
    .has-bottom-sheet .perf-overlay .perf-backend[data-gpu-accelerated="true"] {
        background: linear-gradient(135deg, rgba(63, 185, 80, 0.3), rgba(63, 185, 80, 0.1));
        border: 1px solid rgba(63, 185, 80, 0.3);
    }

    /* "New Record" animation for peak FPS updates */
    @keyframes peak-flash {
        0% { transform: scale(1); }
        50% { transform: scale(1.1); color: #ffd700; }
        100% { transform: scale(1); }
    }

    .has-bottom-sheet .perf-overlay .perf-peak-avg-value.new-record span:first-child {
        animation: peak-flash 0.5s ease-out;
    }

    /* -------------------------------------------------------------------------
       Auto-Hide Timeline Controls (YouTube/Netflix Pattern)
       -------------------------------------------------------------------------
       Controls fade out after 3-5 seconds of playback.
       Tap canvas to show controls, auto-hide resumes.
    */

    .has-bottom-sheet .timeline-container {
        transition: opacity 0.3s ease, transform 0.3s ease;
    }

    .has-bottom-sheet.controls-hidden .timeline-container {
        opacity: 0;
        transform: translateY(100%);
        pointer-events: none;
    }

    /* Canvas overlays also auto-hide during playback */
    .has-bottom-sheet.controls-hidden .stats-overlay,
    .has-bottom-sheet.controls-hidden .perf-overlay,
    .has-bottom-sheet.controls-hidden .legend-panel,
    .has-bottom-sheet.controls-hidden .authors-panel {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease;
    }

    /* -------------------------------------------------------------------------
       I6: Minimal HUD - Context When Controls Hidden
       -------------------------------------------------------------------------
       Shows date and progress (commit count) when stats/timeline are hidden.
       Provides essential context without cluttering the visualization.
       Positioned at bottom-left to avoid stats panel area at top-left.
    */

    .minimal-hud {
        position: absolute;
        bottom: max(140px, calc(140px + env(safe-area-inset-bottom)));
        left: max(12px, env(safe-area-inset-left));
        display: flex;
        gap: 12px;
        align-items: center;
        font-size: 0.875rem;
        font-weight: 500;
        color: var(--text-primary);
        text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8), 0 0 8px rgba(0, 0, 0, 0.5);
        pointer-events: none;
        z-index: var(--z-canvas-overlays);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.3s ease, visibility 0.3s ease;
    }

    .minimal-hud-date {
        color: var(--text-primary);
        font-weight: 600;
        letter-spacing: 0.3px;
    }

    .minimal-hud-progress {
        color: var(--text-secondary);
        font-size: 0.8125rem;
        font-variant-numeric: tabular-nums;
    }

    /* Show minimal HUD only when controls are hidden during playback */
    .has-bottom-sheet.controls-hidden .minimal-hud {
        opacity: 1;
        visibility: visible;
    }

    /* Hide minimal HUD when controls are visible (avoid redundancy) */
    .has-bottom-sheet:not(.controls-hidden) .minimal-hud {
        opacity: 0;
        visibility: hidden;
    }

    /* -------------------------------------------------------------------------
       Tap-to-Show Overlay (Video Player Pattern)
       -------------------------------------------------------------------------
       Large center play button appears on tap when paused.
       Follows YouTube's "cleaner and more immersive" player pattern.
    */

    .mobile-center-play {
        /* Override base display: none for mobile */
        display: flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) scale(0.9);
        width: 80px;
        height: 80px;
        background: rgba(0, 0, 0, 0.6);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        border: none;
        border-radius: 50%;
        color: var(--text-on-accent);
        cursor: pointer;
        z-index: var(--z-canvas-overlays);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
        -webkit-tap-highlight-color: transparent;
    }

    .mobile-center-play.visible {
        opacity: 1;
        visibility: visible;
        transform: translate(-50%, -50%) scale(1);
    }

    .mobile-center-play:active {
        transform: translate(-50%, -50%) scale(0.9);
    }

    .mobile-center-play:focus-visible {
        outline: 2px solid var(--text-on-accent);
        outline-offset: 4px;
    }

    .mobile-center-play svg {
        width: 40px;
        height: 40px;
    }
}


/* ---- styles/features/mobile-landscape.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Mobile Landscape Styles
 *
 * Landscape orientation adjustments for mobile devices.
 * Uses both media query AND .landscape-mobile class for reliability.
 * The class is added by JS when it detects landscape mobile orientation,
 * catching phones with width > 768px in landscape.
 *
 * Includes:
 * - Bottom sheet landscape sizing
 * - FAB and toolbar repositioning
 * - Compact performance/stats overlays
 * - Backdrop and center play adjustments
 * - Sidebar/legend hiding for landscape mobile
 */

/* =============================================================================
   Landscape Mode - Media Query
   ============================================================================= */

@media (max-width: 768px) and (orientation: landscape) {
    .bottom-sheet {
        /* Dynamic viewport height for mobile browser address bar */
        height: 75vh;
        height: 75dvh;
        max-height: calc(100vh - 20px);
        max-height: calc(100dvh - 20px);
    }

    .bottom-sheet-header {
        padding: 6px 16px 4px;
    }

    .bottom-sheet-handle {
        margin-bottom: 6px;
    }

    .bottom-sheet-fab {
        /* Position above timeline (min-height 85px) with some padding */
        bottom: max(95px, calc(95px + env(safe-area-inset-bottom)));
        right: max(12px, env(safe-area-inset-right));
        width: 48px;
        height: 48px;
    }

    /* Landscape: Move toolbar to left edge for left thumb */
    .has-bottom-sheet .mobile-toolbar {
        bottom: 6px;
        left: max(6px, env(safe-area-inset-left));
    }

    /* Timeline more compact in landscape */
    .has-bottom-sheet .timeline-container {
        padding: 0.35rem 0.75rem;
        min-height: 85px;
    }

    /* Center play button smaller in landscape */
    .mobile-center-play {
        width: 64px;
        height: 64px;
    }

    .mobile-center-play svg {
        width: 32px;
        height: 32px;
    }

    /* Landscape toolbar: Maintain 44px touch targets (WCAG 2.5.5) */
    .has-bottom-sheet .mobile-toolbar-btn {
        min-width: 44px;
        min-height: 44px;
        width: auto;
        padding: 4px 6px;
    }

    .has-bottom-sheet .mobile-toolbar-btn svg {
        width: 16px;
        height: 16px;
    }

    /* Labels in landscape maintain WCAG minimum */
    .has-bottom-sheet .mobile-toolbar-btn .btn-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* Tighter toolbar spacing in landscape */
    .has-bottom-sheet .mobile-toolbar {
        gap: 2px;
    }
}

/* =============================================================================
   Landscape Mode - JS-Added Class
   =============================================================================
   Catches phones with width > 768px in landscape where media query
   doesn't apply. The .landscape-mobile class is added by JS.
   ============================================================================= */

/* CRITICAL: Hide sidebar on landscape mobile - content is in bottom sheet instead */
.landscape-mobile.has-bottom-sheet .sidebar-toggle,
.landscape-mobile.has-bottom-sheet .sidebar-panel,
.landscape-mobile.has-bottom-sheet .sidebar-wrapper {
    display: none !important;
}

/* Also hide legend and authors panels on landscape mobile */
.landscape-mobile.has-bottom-sheet .legend-panel,
.landscape-mobile.has-bottom-sheet .authors-panel {
    display: none !important;
}

/* CRITICAL: Enable bottom sheet display for landscape mobile
   The base bottom-sheet-core.css only enables it for max-width: 768px,
   but landscape phones can exceed that width. This ensures the
   bottom sheet works in landscape mode. */
.landscape-mobile .bottom-sheet {
    display: flex;
    flex-direction: column;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: 75vh;
    height: 75dvh;
    max-height: calc(100vh - 20px);
    max-height: calc(100dvh - 20px);
    background: var(--bg-primary);
    border-radius: 20px 20px 0 0;
    transform: translateY(100%);
    transition: transform 0.4s cubic-bezier(0.32, 0.72, 0, 1);
    z-index: var(--z-modal);
    will-change: transform;
    overflow: hidden;
}

.landscape-mobile .bottom-sheet.open {
    transform: translateY(0);
}

.landscape-mobile .bottom-sheet.half {
    transform: translateY(50%);
}

/* Enable backdrop for landscape mobile */
.landscape-mobile .bottom-sheet-backdrop {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--backdrop);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: var(--z-modal-backdrop);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
    pointer-events: none;
}

.landscape-mobile .bottom-sheet-backdrop.visible {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* Enable FAB for landscape mobile */
.landscape-mobile .bottom-sheet-fab {
    display: flex;
}

.landscape-mobile .bottom-sheet-header {
    padding: 6px 16px 4px;
}

.landscape-mobile .bottom-sheet-handle {
    margin-bottom: 6px;
}

.landscape-mobile .bottom-sheet-fab {
    /* Position above timeline (min-height 85px) with some padding */
    bottom: max(95px, calc(95px + env(safe-area-inset-bottom)));
    right: max(12px, env(safe-area-inset-right));
    width: 48px;
    height: 48px;
}

.landscape-mobile.has-bottom-sheet .mobile-toolbar {
    bottom: 6px;
    /* Center toolbar in landscape for consistent layout */
    left: 50%;
    transform: translateX(-50%);
    gap: 2px;
}

.landscape-mobile.has-bottom-sheet .timeline-container {
    padding: 0.35rem 0.75rem;
    min-height: 85px;
}

.landscape-mobile .mobile-center-play {
    width: 64px;
    height: 64px;
}

.landscape-mobile .mobile-center-play svg {
    width: 32px;
    height: 32px;
}

.landscape-mobile.has-bottom-sheet .mobile-toolbar-btn {
    min-width: 44px;
    min-height: 44px;
    width: auto;
    padding: 4px 6px;
}

.landscape-mobile.has-bottom-sheet .mobile-toolbar-btn svg {
    width: 16px;
    height: 16px;
}

.landscape-mobile.has-bottom-sheet .mobile-toolbar-btn .btn-label {
    font-size: 0.75rem; /* 12px - WCAG minimum */
}

/* =============================================================================
   Landscape Performance & Stats Overlays
   ============================================================================= */

.landscape-mobile.has-bottom-sheet .perf-overlay {
    top: 6px;
    right: max(6px, env(safe-area-inset-right));
    left: auto;
    padding: 4px 8px;
    border-radius: 16px;
    font-size: 0.75rem; /* 12px - WCAG minimum */
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-fps {
    font-size: 0.85rem;
    min-width: 60px;
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-details {
    flex-direction: row;
    flex-wrap: nowrap;
    gap: 8px;
    padding-top: 4px;
    margin-top: 4px;
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-row {
    font-size: 0.75rem; /* 12px - WCAG minimum */
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-row:nth-child(n+3):not(.perf-toggle-row):not(.perf-peak-avg-row) {
    display: none;
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-toggle-row {
    flex-basis: auto;
    margin-top: 0;
    padding-top: 0;
    border-top: none;
    padding-left: 8px;
    border-left: 1px solid rgba(255, 255, 255, 0.1);
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-switch {
    width: 36px;
    height: 20px;
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-slider::before {
    height: 14px;
    width: 14px;
}

.landscape-mobile.has-bottom-sheet .perf-overlay .perf-switch input:checked + .perf-slider::before {
    transform: translateX(16px);
}

/* Landscape stats overlay - also top-left for consistency */
.landscape-mobile.has-bottom-sheet .stats-overlay {
    top: max(6px, env(safe-area-inset-top));
    left: max(6px, env(safe-area-inset-left));
    bottom: auto;
    right: auto;
    transform: none;
    padding: 4px 10px;
    gap: 8px;
    max-width: 180px;
}

.landscape-mobile.has-bottom-sheet .stats-overlay .stat-value {
    font-size: 0.75rem; /* 12px - WCAG minimum */
}

.landscape-mobile.has-bottom-sheet .stats-overlay .stat-label {
    font-size: 0.75rem; /* 12px - WCAG minimum */
}


/* ---- styles/features/mobile-accessibility.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Mobile Accessibility & Interaction Styles
 *
 * Touch target accessibility (WCAG 2.5.5), first-run onboarding hints,
 * and gesture feedback indicators.
 *
 * Touch Targets:
 * - Minimum 44x44px (Apple HIG) / 48x48px (Material Design 3)
 * - Applied via media query for touch devices AND small screens
 *
 * References:
 * - WCAG 2.5.5: https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
 * - Apple HIG: https://developer.apple.com/design/human-interface-guidelines/
 * - Material Design: https://m3.material.io/foundations/accessible-design
 */

/* =============================================================================
   Touch Target Accessibility (WCAG 2.5.5 Target Size)
   ============================================================================= */

@media (max-width: 768px), (pointer: coarse) {
    /* Theme toggle - increase touch target with padding */
    .theme-toggle {
        min-width: 44px;
        min-height: 44px;
    }

    /* Modal close button */
    .modal-close {
        min-width: 44px;
        min-height: 44px;
    }

    /* Help button and close button */
    .help-btn,
    .help-close {
        min-width: 44px;
        min-height: 44px;
    }

    /* Fullscreen exit button */
    .fullscreen-exit-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Bottom sheet close button */
    .bottom-sheet-close {
        min-width: 44px;
        min-height: 44px;
    }

    /* Sidebar close button */
    .sidebar-close {
        min-width: 44px;
        min-height: 44px;
    }

    /* Timeline control buttons */
    .timeline-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Main play button */
    .play-btn-main {
        min-width: 44px;
        min-height: 44px;
    }

    /* Reset button */
    .reset-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Reset view button */
    .reset-view-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Collapsible panel headers - expand touch target */
    .collapsible-header {
        min-height: 48px;
    }

    /* Legend and overlay toggle areas */
    .legend-header,
    .authors-header,
    .perf-header {
        min-height: 44px;
        padding: 8px 0;
    }

    /* Tab buttons */
    .tab-btn {
        min-height: 44px;
    }

    /* Bottom sheet tabs */
    .bottom-sheet-tab {
        min-height: 44px;
    }

    /* Icon buttons - base class */
    .btn-icon {
        min-width: 44px;
        min-height: 44px;
    }

    /* Fullscreen toggle button */
    .fullscreen-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Share/export button */
    .share-btn,
    .export-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Font size adjustment buttons */
    .font-size-btn,
    .text-size-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Recording controls */
    .record-btn,
    .recording-control-btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Mobile toolbar buttons - ensure proper size */
    .mobile-toolbar-btn {
        min-width: 44px;
        min-height: 44px;
    }
}

/* =============================================================================
   First-Run Onboarding Hints
   =============================================================================

   Contextual tips for first-time users. Hidden after first interaction.
   Based on Material Design coach marks and YouTube's gesture education.
*/

.mobile-onboarding-hint {
    position: fixed;
    bottom: 200px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: var(--text-on-accent);
    padding: 12px 20px;
    border-radius: 12px;
    font-size: 0.875rem;
    text-align: center;
    z-index: 600;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
    pointer-events: none;
    max-width: 280px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
}

.mobile-onboarding-hint.visible {
    opacity: 1;
    visibility: visible;
}

.mobile-onboarding-hint-icon {
    display: block;
    margin: 0 auto 8px;
    width: 32px;
    height: 32px;
    opacity: 0.8;
}

.mobile-onboarding-hint-text {
    line-height: 1.4;
}

.mobile-onboarding-hint-dismiss {
    display: inline-block;
    margin-top: 10px;
    padding: 6px 16px;
    background: rgba(255, 255, 255, 0.15);
    border: none;
    border-radius: 6px;
    color: var(--text-on-accent);
    font-size: 0.8125rem;
    cursor: pointer;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
}

.mobile-onboarding-hint-dismiss:active {
    background: rgba(255, 255, 255, 0.25);
}

/* Swipe hint animation */
@keyframes swipe-hint {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
}

.mobile-onboarding-hint.swipe-hint .mobile-onboarding-hint-icon {
    animation: swipe-hint 1.5s ease-in-out infinite;
}

/* Tap hint pulse */
@keyframes tap-hint {
    0%, 100% { transform: scale(1); opacity: 0.8; }
    50% { transform: scale(1.1); opacity: 1; }
}

.mobile-onboarding-hint.tap-hint .mobile-onboarding-hint-icon {
    animation: tap-hint 1.2s ease-in-out infinite;
}

/* =============================================================================
   Gesture Feedback Indicators
   =============================================================================

   Visual feedback for gestures (pinch zoom, pan, etc.)
   Provides immediate feedback for touch interactions.
*/

.gesture-indicator {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0, 0, 0, 0.7);
    color: var(--text-on-accent);
    padding: 12px 20px;
    border-radius: 8px;
    font-size: 0.875rem;
    font-weight: 500;
    z-index: 550;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.15s ease;
    pointer-events: none;
}

.gesture-indicator.visible {
    opacity: 1;
    visibility: visible;
}

.gesture-indicator-zoom {
    display: flex;
    align-items: center;
    gap: 8px;
}

.gesture-indicator-zoom svg {
    width: 20px;
    height: 20px;
}


/* ---- styles/features/mobile-responsive.css ---- */
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2026 Tom F <https://github.com/tomtom215> */

/**
 * Rource - Mobile Responsive Breakpoints & Theme Overrides
 *
 * Extra-small screen adjustments, light theme mobile overrides,
 * and analytics dashboard mobile overrides.
 *
 * Breakpoints:
 * - 375px: Smallest screens (iPhone SE)
 * - 480px: Analytics dashboard compact mode
 */

/* =============================================================================
   Extra Small Screens (375px)
   ============================================================================= */

@media (max-width: 375px) {
    .bottom-sheet-fab {
        width: 52px;
        height: 52px;
        right: 12px;
    }

    .bottom-sheet-content {
        padding: 0 12px 12px;
    }

    .bottom-sheet-quick-actions {
        padding: 0 12px 10px;
    }

    /* Extra small stats overlay - even more compact */
    .has-bottom-sheet .stats-overlay {
        bottom: max(112px, calc(112px + env(safe-area-inset-bottom)));
        padding: 5px 10px;
        gap: 10px;
        max-width: calc(100vw - 120px);
    }

    .has-bottom-sheet .stats-overlay .stat-value {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    .has-bottom-sheet .stats-overlay .stat-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* -------------------------------------------------------------------------
       Extra Small Performance Overlay - Minimal Footprint
       -------------------------------------------------------------------------

       On smallest screens (iPhone SE, etc.), use absolute minimum size
       while maintaining readability. FPS + uncapped badge only in collapsed.
    */

    .has-bottom-sheet .perf-overlay {
        padding: 4px 8px;
        border-radius: 14px;
        max-width: 140px;
    }

    .has-bottom-sheet .perf-overlay .perf-fps {
        font-size: 0.8rem;
        min-width: 55px;
    }

    /* Collapsed: FPS only, ultra-compact badge */
    .has-bottom-sheet .perf-overlay.collapsed {
        padding: 3px 8px;
    }

    .has-bottom-sheet .perf-overlay.collapsed .perf-fps {
        font-size: 0.75rem;
    }

    /* Smaller switch on tiny screens */
    .has-bottom-sheet .perf-overlay .perf-switch {
        width: 38px;
        height: 20px;
    }

    .has-bottom-sheet .perf-overlay .perf-slider::before {
        height: 14px;
        width: 14px;
    }

    .has-bottom-sheet .perf-overlay .perf-switch input:checked + .perf-slider::before {
        transform: translateX(18px);
    }

    /* Details even more compact */
    .has-bottom-sheet .perf-overlay .perf-details {
        gap: 4px 8px;
    }

    .has-bottom-sheet .perf-overlay .perf-row {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }

    /* Uncapped toggle inline with label on tiny screens */
    .has-bottom-sheet .perf-overlay .perf-toggle-row {
        flex-wrap: nowrap;
        gap: 6px;
        padding-top: 6px;
        margin-top: 6px;
    }

    .has-bottom-sheet .perf-overlay #perf-uncapped-label {
        font-size: 0.75rem; /* 12px - WCAG minimum */
    }
}

/* =============================================================================
   Light Theme Mobile Adjustments
   ============================================================================= */

.light-theme.has-bottom-sheet .mobile-toolbar {
    background: rgba(250, 251, 252, 0.97);
    border: 1px solid var(--border);
    box-shadow: 0 2px 12px rgba(31, 35, 40, 0.12);
}

.light-theme.has-bottom-sheet .stats-overlay {
    background: rgba(250, 251, 252, 0.97);
    border: 1px solid var(--border);
    box-shadow: 0 2px 8px rgba(31, 35, 40, 0.1);
}

.light-theme.has-bottom-sheet .perf-overlay {
    background: rgba(250, 251, 252, 0.97);
    border: 1px solid var(--border);
    box-shadow: 0 2px 12px rgba(31, 35, 40, 0.12);
}

/* Light theme HUD adjustments */
.light-theme.has-bottom-sheet .perf-overlay .perf-details {
    border-top-color: rgba(0, 0, 0, 0.1);
}

.light-theme.has-bottom-sheet .perf-overlay .perf-toggle-row {
    border-top-color: rgba(0, 0, 0, 0.1);
}

/* Uncapped mode active indicator - light theme */
.light-theme .mobile-toolbar-btn.uncapped-toggle.active {
    background: rgba(255, 107, 53, 0.15);
}

.light-theme.has-bottom-sheet .timeline-container {
    background: var(--bg-secondary);
}


@media (max-width: 768px) {
}

@media (max-width: 480px) {
}
