/* Fitness Dashboard — Design System
   Single source of truth for colors, typography, cards, animations.
   All colors use CSS custom properties for future dark mode support. */

:root {
    /* Backgrounds */
    --bg-primary: #faf8f5;
    --bg-card: #ffffff;
    --bg-card-hover: #ffffff;
    --bg-card-border: #e8e2d8;
    --bg-input: #f3f0ea;
    --bg-overlay: rgba(0, 0, 0, 0.4);

    /* Text */
    --text-primary: #2d2d2d;
    --text-secondary: #666;
    --text-muted: #999;
    --text-faint: #bbb;

    /* Accent Colors */
    --accent-orange: #e8734a;
    --accent-green: #3d9970;
    --accent-blue: #4a90d9;
    --accent-red: #d9534f;
    --accent-purple: #8e6bb5;
    --accent-gold: #d4a017;

    /* Sport Colors */
    --sport-bike-bg: #e8f4fd;
    --sport-bike-text: #2a7ab5;
    --sport-run-bg: #fef3e8;
    --sport-run-text: #c75e2a;
    --sport-swim-bg: #e8eef8;
    --sport-swim-text: #5568a8;
    --sport-strength-bg: #f3e8f8;
    --sport-strength-text: #7b4fa0;
    --sport-rest-bg: #e8f8ed;
    --sport-rest-text: #2d8a54;
    --sport-row-bg: #e6f2f2;
    --sport-row-text: #2e7f7f;

    /* Readiness */
    --readiness-high: #3d9970;
    --readiness-mid: #e8734a;
    --readiness-low: #d9834a;
    --readiness-critical: #d9534f;

    /* Shadows */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.1);
    --shadow-glow-orange: 0 0 20px rgba(232, 115, 74, 0.15);
    --shadow-glow-green: 0 0 20px rgba(61, 153, 112, 0.15);

    /* Sizing */
    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --radius-xl: 24px;

    /* Transitions */
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
    --duration-fast: 150ms;
    --duration-normal: 250ms;
    --duration-slow: 400ms;
}

/* Dark */
[data-theme="dark"] {
    --bg-primary: #141414;
    --bg-card: #1e1e1e;
    --bg-card-hover: #252525;
    --bg-card-border: #333;
    --bg-input: #2a2a2a;
    --bg-overlay: rgba(0, 0, 0, 0.6);
    --text-primary: #e8e2d8;
    --text-secondary: #aaa;
    --text-muted: #888;
    --text-faint: #6a6a6a;
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4);
}

/* Power — Stryd PowerCenter inspired (near-black, orange accent) */
[data-theme="power"] {
    --bg-primary: #0a0b0d;
    --bg-card: #131416;
    --bg-card-hover: #1a1b1e;
    --bg-card-border: #222326;
    --bg-input: #1a1b1e;
    --bg-overlay: rgba(0, 0, 0, 0.75);
    --text-primary: #e8e4dc;
    --text-secondary: #9a9590;
    --text-muted: #7d7873;
    --text-faint: #5e5954;
    --accent-orange: #e89830;
    --accent-green: #3dbba0;
    --accent-blue: #3da8c4;
    --accent-red: #e85050;
    --accent-purple: #a07be0;
    --accent-gold: #e8c040;
    --sport-bike-bg: #162028;
    --sport-bike-text: #3da8c4;
    --sport-run-bg: #28201a;
    --sport-run-text: #e89830;
    --sport-swim-bg: #1a1e30;
    --sport-swim-text: #7090d0;
    --sport-strength-bg: #221a30;
    --sport-strength-text: #a07be0;
    --sport-rest-bg: #162820;
    --sport-rest-text: #3dbba0;
    --sport-row-bg: #14262a;
    --sport-row-text: #45b8c8;
    --shadow-sm: none;
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 4px 20px rgba(0, 0, 0, 0.6);
    --shadow-glow-orange: 0 0 20px rgba(232, 152, 48, 0.12);
    --shadow-glow-green: 0 0 20px rgba(61, 187, 160, 0.12);
}

/* Midnight — deep indigo/purple (Garmin-inspired) */
[data-theme="midnight"] {
    --bg-primary: #13111c;
    --bg-card: #1c1a2e;
    --bg-card-hover: #24213a;
    --bg-card-border: #2e2b45;
    --bg-input: #24213a;
    --bg-overlay: rgba(0, 0, 0, 0.65);
    --text-primary: #e4e0f0;
    --text-secondary: #9e96b8;
    --text-muted: #7d74a0;
    --text-faint: #5e5680;
    --accent-orange: #ff8c42;
    --accent-green: #66d9a0;
    --accent-blue: #6c8cff;
    --accent-red: #ff5c7a;
    --accent-purple: #c084fc;
    --accent-gold: #fcd34d;
    --sport-bike-bg: #1e2248;
    --sport-bike-text: #6c8cff;
    --sport-run-bg: #2e1e1a;
    --sport-run-text: #ff8c42;
    --sport-swim-bg: #1a1e40;
    --sport-swim-text: #8b9eff;
    --sport-strength-bg: #2a1a3e;
    --sport-strength-text: #c084fc;
    --sport-rest-bg: #1a2e24;
    --sport-rest-text: #66d9a0;
    --sport-row-bg: #16303a;
    --sport-row-text: #58c8dc;
    --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.5);
    --shadow-glow-orange: 0 0 24px rgba(255, 140, 66, 0.15);
    --shadow-glow-green: 0 0 24px rgba(102, 217, 160, 0.15);
}

/* Nature — earth tones, forest green */
[data-theme="nature"] {
    --bg-primary: #f5f2eb;
    --bg-card: #faf8f2;
    --bg-card-hover: #fffdf7;
    --bg-card-border: #d6cdb8;
    --bg-input: #ece7da;
    --bg-overlay: rgba(40, 35, 20, 0.4);
    --text-primary: #33301e;
    --text-secondary: #5c5840;
    --text-muted: #8a8468;
    --text-faint: #b3ad94;
    --accent-orange: #c77c3a;
    --accent-green: #4a7c59;
    --accent-blue: #5a7fa0;
    --accent-red: #b5543a;
    --accent-purple: #7a6b8a;
    --accent-gold: #b8952e;
    --sport-bike-bg: #e4ede6;
    --sport-bike-text: #3a6b50;
    --sport-run-bg: #f0e8dd;
    --sport-run-text: #a06830;
    --sport-swim-bg: #e0e8f0;
    --sport-swim-text: #4a6a85;
    --sport-strength-bg: #ece4f0;
    --sport-strength-text: #6a5a7a;
    --sport-rest-bg: #e8f0e4;
    --sport-rest-text: #4a7040;
    --sport-row-bg: #e0ecea;
    --sport-row-text: #3a7570;
    --shadow-sm: 0 1px 3px rgba(40, 35, 20, 0.06);
    --shadow-md: 0 4px 12px rgba(40, 35, 20, 0.08);
    --shadow-lg: 0 8px 24px rgba(40, 35, 20, 0.12);
    --shadow-glow-orange: 0 0 20px rgba(199, 124, 58, 0.15);
    --shadow-glow-green: 0 0 20px rgba(74, 124, 89, 0.15);
}

/* Base */
body {
    background: var(--bg-primary);
    color: var(--text-primary);
    font-family: 'DM Sans', system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
}

/* Card System */
.card {
    background: var(--bg-card);
    border: 1px solid var(--bg-card-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--duration-normal) var(--ease-out),
                transform var(--duration-normal) var(--ease-out);
}

.card-interactive {
    cursor: pointer;
}

.card-interactive:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

.card-interactive:active {
    transform: scale(0.99);
    box-shadow: var(--shadow-sm);
}

.card-glass {
    background: rgba(255, 255, 255, 0.7);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.3);
}

[data-theme="dark"] .card-glass {
    background: rgba(30, 30, 30, 0.7);
    border: 1px solid rgba(255, 255, 255, 0.08);
}

/* Typography */
.stat-value {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--text-primary);
}

.stat-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    font-weight: 500;
}

.stat-sm {
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--text-primary);
}

.stat-delta {
    font-size: 0.75rem;
    font-weight: 600;
}

.stat-delta.positive { color: var(--accent-green); }
.stat-delta.negative { color: var(--accent-red); }
.stat-delta.neutral { color: var(--text-muted); }

/* Sport Badges */
.sport-badge {
    padding: 3px 10px;
    border-radius: var(--radius-sm);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    display: inline-block;
}

.sport-bike { background: var(--sport-bike-bg); color: var(--sport-bike-text); }
.sport-run { background: var(--sport-run-bg); color: var(--sport-run-text); }
.sport-swim { background: var(--sport-swim-bg); color: var(--sport-swim-text); }
.sport-strength { background: var(--sport-strength-bg); color: var(--sport-strength-text); }
.sport-rest { background: var(--sport-rest-bg); color: var(--sport-rest-text); }
.sport-row { background: var(--sport-row-bg); color: var(--sport-row-text); }
.sport-other { background: var(--bg-input); color: var(--text-muted); }

/* Insight Borders */
.insight-warning { border-left: 3px solid var(--accent-orange); }
.insight-positive { border-left: 3px solid var(--accent-green); }
.insight-info { border-left: 3px solid var(--accent-blue); }

/* Tabs */
.tab {
    padding-bottom: 10px;
    font-size: 0.875rem;
    white-space: nowrap;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    color: var(--text-muted);
    transition: color var(--duration-fast), border-color var(--duration-fast);
}

.tab:hover { color: var(--text-secondary); }
.tab.active { border-bottom-color: var(--accent-orange); color: var(--accent-orange); font-weight: 600; }

/* Slide Panel (Workout Detail) */
.slide-panel-backdrop {
    position: fixed;
    inset: 0;
    background: var(--bg-overlay);
    z-index: 50;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-slow) var(--ease-out);
}

.slide-panel-backdrop.open {
    opacity: 1;
    pointer-events: auto;
}

.slide-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 55%;
    max-width: 700px;
    background: var(--bg-primary);
    z-index: 51;
    transform: translateX(100%);
    transition: transform var(--duration-slow) var(--ease-out);
    overflow-y: auto;
    box-shadow: -4px 0 24px rgba(0, 0, 0, 0.12);
}

.slide-panel.open {
    transform: translateX(0);
}

/* Pulse animation for low readiness */
@keyframes pulse-warn {
    0%, 100% { box-shadow: var(--shadow-sm); }
    50% { box-shadow: var(--shadow-glow-orange); }
}

.pulse-warn {
    animation: pulse-warn 2s ease-in-out infinite;
}

/* Stagger entrance animation */
@keyframes fadeSlideUp {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: translateY(0); }
}

.animate-in {
    animation: fadeSlideUp var(--duration-slow) var(--ease-out) forwards;
    opacity: 0;
}

/* Skeleton loading */
.skeleton {
    background: linear-gradient(90deg, var(--bg-input) 25%, var(--bg-card-border) 50%, var(--bg-input) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.5s infinite;
    border-radius: var(--radius-sm);
}

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

/* State: Loading */
.state-loading {
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* State: Error */
.state-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 32px 16px;
    text-align: center;
    gap: 12px;
    min-height: 120px;
}

.state-error-icon {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--accent-red) 12%, transparent);
    color: var(--accent-red);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 1.2rem;
}

.state-error-text {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin: 0;
    max-width: 280px;
}

.state-retry-btn {
    padding: 6px 16px;
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    border: 1px solid var(--bg-card-border);
    color: var(--text-secondary);
    font-size: 0.8rem;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--duration-fast) var(--ease-out);
}

.state-retry-btn:hover {
    background: var(--bg-card-hover);
    color: var(--text-primary);
    border-color: var(--accent-orange);
}

/* State: Empty */
.state-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 32px 16px;
    text-align: center;
    gap: 8px;
    min-height: 120px;
}

.state-empty-icon {
    font-size: 1.8rem;
    color: var(--text-faint);
    font-weight: 300;
}

.state-empty-text {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin: 0;
}

/* Button Micro-interactions */
button, .btn, [role="button"] {
    transition: all var(--duration-fast) var(--ease-out);
}

button:active:not(:disabled), .btn:active:not(:disabled) {
    transform: scale(0.97);
}

/* Filter/Tab Active State */
.filter-btn {
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    font-size: 0.8rem;
    font-weight: 500;
    border: 1px solid var(--bg-card-border);
    background: var(--bg-card);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all var(--duration-fast) var(--ease-out);
}

.filter-btn:hover {
    border-color: var(--accent-orange);
    color: var(--text-primary);
}

.filter-btn.active {
    background: var(--accent-orange);
    border-color: var(--accent-orange);
    color: #fff;
    font-weight: 600;
}

/* Smooth page transitions */
.page-content {
    animation: fadeSlideUp var(--duration-slow) var(--ease-out);
}

/* Celebration burst */
@keyframes celebratePop {
    0% { transform: scale(0); opacity: 0; }
    50% { transform: scale(1.2); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

@keyframes confettiFall {
    0% { transform: translateY(-10px) rotate(0deg); opacity: 1; }
    100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }
}

.celebrate-pop {
    animation: celebratePop 0.5s var(--ease-bounce) forwards;
}

/* Readiness ring animation */
@keyframes ringFill {
    from { stroke-dashoffset: var(--ring-circumference); }
    to { stroke-dashoffset: var(--ring-target); }
}

.readiness-ring-animated {
    animation: ringFill 1.2s var(--ease-out) forwards;
}

/* Scrollbar */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bg-card-border); border-radius: 3px; }

/* Mobile */
@media (max-width: 640px) {
    .stat-value { font-size: 1.5rem; }
    .card { border-radius: var(--radius-md); }
    body { font-size: 14px; }

    .slide-panel {
        width: 100%;
        max-width: none;
    }
}

/* ============================================================
 * ApexCharts tooltip — readable on every theme.
 * Without these overrides, the default light tooltip renders
 * grey-on-grey on dark/midnight/power surfaces.
 * Originally lived in activity.html — promoted here so trends,
 * engine, today, etc. inherit it.
 * ============================================================ */
.apexcharts-tooltip,
.apexcharts-tooltip.apexcharts-theme-light,
.apexcharts-tooltip.apexcharts-theme-dark {
    background: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border: 1px solid var(--bg-card-border) !important;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35) !important;
}
.apexcharts-tooltip-title {
    background: var(--bg-card-hover) !important;
    color: var(--text-primary) !important;
    border-bottom: 1px solid var(--bg-card-border) !important;
    font-weight: 600;
}
.apexcharts-tooltip-text,
.apexcharts-tooltip-text-y-label,
.apexcharts-tooltip-text-y-value,
.apexcharts-tooltip-text-z-label,
.apexcharts-tooltip-text-z-value,
.apexcharts-tooltip-y-group,
.apexcharts-tooltip-series-group {
    color: var(--text-primary) !important;
}
.apexcharts-xaxistooltip,
.apexcharts-yaxistooltip {
    background: var(--bg-card) !important;
    color: var(--text-primary) !important;
    border-color: var(--bg-card-border) !important;
}

/* ============================================================
 * Glossar-Tooltips — small "?" badge next to a metric label.
 * Originally lived only in engine.html; promoted here so any
 * page can use the same pattern: wrap any label in
 *   <span class="tt-wrap">CTL <span class="tt-icon">?</span>
 *     <div class="tt-bubble"><div class="tt-title">…</div>…</div>
 *   </span>
 * — or use renderGlossary() from utils.js to auto-attach.
 * ============================================================ */
.tt-wrap { position: relative; display: inline-flex; align-items: center; }
.tt-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 15px; height: 15px; border-radius: 50%;
    font-size: 9px; font-weight: 700; line-height: 1;
    color: var(--text-muted); border: 1px solid var(--bg-card-border);
    cursor: help; margin-left: 5px; flex-shrink: 0; opacity: 0.55;
    transition: opacity 150ms, color 150ms, border-color 150ms;
    user-select: none; background: transparent;
}
.tt-icon:hover, .tt-icon:focus-visible {
    opacity: 1; color: var(--accent-orange); border-color: var(--accent-orange);
    outline: none;
}
.tt-bubble {
    display: none; position: absolute; bottom: calc(100% + 8px); left: 50%;
    transform: translateX(-50%); width: 280px;
    padding: 0.65rem 0.8rem;
    background: var(--bg-card); border: 1px solid var(--accent-orange);
    border-radius: 8px;
    font-size: 0.72rem; line-height: 1.5;
    color: var(--text-primary);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
    z-index: 1000; pointer-events: none;
}
.tt-bubble::after {
    content: ''; position: absolute; top: 100%; left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-top-color: var(--accent-orange);
}
.tt-icon:hover + .tt-bubble,
.tt-icon:focus-visible + .tt-bubble,
.tt-bubble:hover { display: block; }
.tt-bubble .tt-title {
    font-weight: 700; font-size: 0.78rem;
    margin-bottom: 4px; color: var(--accent-orange);
}
.tt-bubble .tt-meta {
    margin-top: 6px; padding-top: 6px;
    border-top: 1px solid var(--bg-card-border);
    font-size: 0.66rem; color: var(--text-muted);
}

/* ============================================================
 * Toast notifications — premium feedback after Save/Update actions.
 * Use showToast(message, type='success'|'info'|'warning'|'error')
 * ============================================================ */
.coach-toast {
    position: fixed; bottom: 24px; left: 50%;
    transform: translateX(-50%) translateY(120%);
    background: var(--bg-card);
    border: 1px solid var(--bg-card-border);
    border-left: 4px solid var(--accent-green);
    border-radius: 10px;
    padding: 12px 18px;
    font-size: 0.85rem; font-weight: 500;
    color: var(--text-primary);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
    z-index: 9999; opacity: 0;
    transition: transform 280ms var(--ease-out), opacity 200ms;
    pointer-events: none;
    max-width: 90vw;
}
.coach-toast.visible {
    transform: translateX(-50%) translateY(0);
    opacity: 1;
}
.coach-toast.toast-success { border-left-color: var(--accent-green); }
.coach-toast.toast-info { border-left-color: var(--accent-blue); }
.coach-toast.toast-warning { border-left-color: var(--accent-orange); }
.coach-toast.toast-error { border-left-color: var(--accent-red); }
.coach-toast .toast-icon { display: inline-block; margin-right: 8px; font-size: 1rem; }

/* ============================================================
 * Empty + error state polish — friendlier than blank/red text.
 * ============================================================ */
.empty-state {
    text-align: center; padding: 32px 20px;
    color: var(--text-muted);
}
.empty-state .empty-icon {
    font-size: 1.8rem; opacity: 0.4; margin-bottom: 8px;
}
.empty-state .empty-title {
    font-weight: 600; font-size: 0.9rem; color: var(--text-secondary);
    margin-bottom: 4px;
}
.empty-state .empty-sub {
    font-size: 0.8rem; line-height: 1.5;
}
.empty-state .empty-cta {
    display: inline-block; margin-top: 12px;
    padding: 6px 14px; border-radius: 6px;
    background: rgba(232, 115, 74, 0.12); color: var(--accent-orange);
    font-size: 0.8rem; font-weight: 600;
    text-decoration: none; transition: background 120ms;
}
.empty-state .empty-cta:hover { background: rgba(232, 115, 74, 0.2); }

/* ============================================================
 * KPI shimmer / number animation
 * Subtle entrance for stat-values.
 * ============================================================ */
@keyframes kpiFadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: translateY(0); }
}
.kpi-fade { animation: kpiFadeIn 320ms var(--ease-out) both; }

/* ============================================================
 * Hover-text tooltip (CSS only). Originally lived in dashboard.html;
 * promoted globally so trends/activity/today/race etc. can use the
 * same pattern: <span data-tooltip="…">label</span>
 * Empty data-tooltip="" → no bubble.
 * data-tooltip-pos="top|right|left" → reposition.
 * ============================================================ */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    top: calc(100% + 8px); left: 50%;
    transform: translateX(-50%) translateY(-4px);
    padding: 8px 11px;
    background: var(--bg-card);
    border: 1px solid var(--bg-card-border);
    border-radius: var(--radius-sm);
    font-size: 0.7rem; font-weight: 400; line-height: 1.5;
    color: var(--text-secondary);
    text-transform: none; letter-spacing: normal;
    white-space: normal; width: max-content; max-width: 260px;
    box-shadow: var(--shadow-lg); z-index: 100;
    text-align: left;
    opacity: 0; pointer-events: none;
    transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out);
}
[data-tooltip]:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
[data-tooltip=""]::after { display: none; }
[data-tooltip-pos="top"]::after {
    top: auto; bottom: calc(100% + 8px);
    transform: translateX(-50%) translateY(4px);
}
[data-tooltip-pos="top"]:hover::after { transform: translateX(-50%) translateY(0); }
[data-tooltip-pos="right"]::after {
    left: auto; right: 0;
    transform: translateX(0) translateY(-4px);
}
[data-tooltip-pos="right"]:hover::after { transform: translateX(0) translateY(0); }
[data-tooltip-pos="left"]::after {
    left: 0;
    transform: translateX(0) translateY(-4px);
}
[data-tooltip-pos="left"]:hover::after { transform: translateX(0) translateY(0); }

/* Touch-Geräte: kein Hover → Tooltips sind totes Gewicht, und ihre
 * opacity-0-Boxen (bis 260px) verbreiterten das Dokument horizontal
 * über den Viewport hinaus (UI-Audit U9). Gilt global. */
@media (hover: none) {
    [data-tooltip]::after { display: none; }
}

/* ============================================================
 * Foto-Hintergrund pro Theme (optional, utils.js applyThemeBackground):
 * /static/backgrounds/{theme}.jpg → fixer Layer (scrollt NICHT mit),
 * Overlay in Theme-Grundfarbe sichert Lesbarkeit, Content-Spalte
 * streckt sich auf volle Browserbreite.
 * ============================================================ */
#fd-bg-photo {
    position: fixed; inset: 0; z-index: -2;
    background-size: cover; background-position: center; background-repeat: no-repeat;
}
#fd-bg-photo::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--bg-primary) 22%, transparent),
        color-mix(in srgb, var(--bg-primary) 58%, transparent));
}
html[data-bg-photo] body { background: transparent; }
html[data-bg-photo] .bg-decor { display: none; }

/* Content-Spine: Die Seiten behalten ihr normales Format (Foto sichtbar
 * links + rechts). Damit sich der Inhalt klar vom Bild abhebt, liegt die
 * Content-Spalte auf einem getönten Frosted-Glass-Panel. */
html[data-bg-photo] body > div[class*="max-w-"],
html[data-bg-photo] body > main[class*="max-w-"],
html[data-bg-photo] body > div.mx-auto {
    background: color-mix(in srgb,
        color-mix(in srgb, var(--bg-primary) 72%, var(--text-primary) 28%) 42%,
        transparent);
    -webkit-backdrop-filter: blur(18px) saturate(1.05);
    backdrop-filter: blur(18px) saturate(1.05);
    border-radius: 16px;
    margin-top: 10px;
    margin-bottom: 28px;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg-card-border) 60%, transparent),
                0 24px 60px rgba(0, 0, 0, 0.35);
}
/* Helle Themes (Sand + Nature): VOLL deckendes Panel, einen Hauch dunkler
 * als die Karten (warme Border-Farbe statt Grau) — transluzent ließ zu
 * viel Bild durch. Das Foto lebt links und rechts der Content-Spalte. */
html[data-bg-photo="light"] body > div[class*="max-w-"],
html[data-bg-photo="light"] body > main[class*="max-w-"],
html[data-bg-photo="light"] body > div.mx-auto,
html[data-bg-photo="nature"] body > div[class*="max-w-"],
html[data-bg-photo="nature"] body > main[class*="max-w-"],
html[data-bg-photo="nature"] body > div.mx-auto {
    background: color-mix(in srgb, var(--bg-primary) 60%, var(--bg-card-border) 40%);
}

/* Kalender: Sticky-Header hat inline bg-primary — auf Foto-Seiten
 * stattdessen frosted, damit er nicht als Vollbreite-Balken wirkt. */
html[data-bg-photo] #cal-header {
    background: color-mix(in srgb,
        color-mix(in srgb, var(--bg-primary) 72%, var(--text-primary) 28%) 54%,
        transparent) !important;
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
}
html[data-bg-photo="light"] #cal-header,
html[data-bg-photo="nature"] #cal-header {
    background: color-mix(in srgb, var(--bg-primary) 60%, var(--bg-card-border) 40%) !important;
}

/* Kontrast Module ↔ Glas: NICHT die Karten anfassen — das Glas-Panel
 * selbst wird Richtung Textfarbe getönt (dunkle Themes → helleres Glas,
 * helle Themes → dunkleres Glas). Die unveränderten Karten stehen dann
 * als dunkle bzw. helle Flächen klar auf dem Panel. */

/* JS-Tooltip-Overlay (utils.js): rendert die Bubble fix am body, damit sie
 * aus overflow-hidden-Containern (fd-hero, Cards) herausragen kann und auch
 * auf SVG-Elementen (Ring-Segmente) funktioniert. Bei aktivem Overlay wird
 * die reine CSS-Bubble abgeschaltet — sie bleibt No-JS-Fallback. */
html.tt-overlay [data-tooltip]::after { display: none !important; }
.tt-overlay-bubble {
    display: none; position: fixed;
    padding: 8px 11px;
    background: var(--bg-card);
    border: 1px solid var(--bg-card-border);
    border-radius: var(--radius-sm);
    font-size: 0.7rem; font-weight: 400; line-height: 1.5;
    color: var(--text-secondary);
    text-transform: none; letter-spacing: normal;
    white-space: normal; width: max-content; max-width: 280px;
    box-shadow: var(--shadow-lg); z-index: 1200;
    text-align: left; pointer-events: none;
}
