/**
 * mio.land - Composants UX partagés
 * Source de vérité pour tous les éléments d'interface utilisateur
 * 
 * Usage: <link rel="stylesheet" href="/ux/ux-components.css?<?= filemtime($_SERVER['DOCUMENT_ROOT'] . '/ux/ux-components.css') ?>">
 * 
 * Ce fichier est conçu pour être embeddable dans des exports HTML standalone.
 * Toutes les icônes sont en SVG inline, jamais d'emojis ou caractères graphiques.
 * 
 * PERSONNALISATION PAR APP:
 * Les apps peuvent définir --accent dans leur CSS pour personnaliser:
 * - La couleur du toast undo (bouton + barre de progression)
 * Exemple: :root { --accent: #7C4DFF; }
 */

/* ============================
   VARIABLES UX (à ne pas surcharger)
   ============================ */

:root {
    /* Couleurs de boutons standard */
    --ux-btn-default: #2ECC71;
    --ux-btn-default-hover: #27AE60;
    --ux-btn-primary: #3498DB;
    --ux-btn-primary-hover: #2980B9;
    --ux-btn-secondary: rgba(255, 255, 255, 0.08);
    --ux-btn-secondary-hover: rgba(255, 255, 255, 0.15);
    --ux-btn-danger: #E74C3C;
    --ux-btn-danger-hover: #C0392B;
    --ux-btn-purple: #8b5cf6;
    --ux-btn-purple-hover: #7c3aed;
    --ux-btn-pink: #ec4899;
    --ux-btn-pink-hover: #db2777;
    --ux-btn-orange: #F39C12;
    --ux-btn-orange-hover: #E67E22;
    --ux-btn-cyan: #00BCD4;
    --ux-btn-cyan-hover: #00ACC1;
    
    /* Couleurs de feedback */
    --ux-success: #2ECC71;
    --ux-error: #E74C3C;
    --ux-warning: #F39C12;
    --ux-info: #3498DB;
    
    /* Transitions */
    --ux-transition-fast: 0.15s ease;
    --ux-transition-normal: 0.25s ease;
}

/* ============================
   MARQUE PRODUCTIVIA
   ============================
   Style officiel du logotype "Productiv<span class="brand-ia">IA</span>".
   Source de verite : productivia.ca (_css/main.css).
   Usage obligatoire dans toute interface visible mentionnant la marque.
   - .brand-ia : applique le style officiel des lettres "IA" (taille reduite + decalage subtil vers le haut)
   - .brand-lock : empeche un retour a la ligne entre "Productiv" et "IA"
   Pattern HTML : <span class="brand-lock">Productiv<span class="brand-ia">IA</span></span>
   ============================ */

.brand-ia {
    display: inline-block;
    font-size: 0.85em;
    transform: translate(0px, -0.20em);
    pointer-events: none;
}

.brand-lock {
    white-space: nowrap;        /* empeche le retour a la ligne */
    display: inline-block;      /* evite certaines cesures bizarres */
    word-break: normal;         /* annule break-all sur des parents */
    overflow-wrap: normal;      /* annule anywhere / break-word */
    hyphens: none;              /* pas de cesure automatique */
}

/* ============================
   INPUTS GLOBAUX
   ============================ */

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
}

/* ============================
   ICONES DECLARATIVES (data-icon)
   ----------------------------
   Conteneur d'icone hydrate par UX.hydrateIcons (voir ux-components.js).
   Usage : <i data-icon="alert-circle"></i>
   La couleur suit currentColor, la taille suit la police (1em) sauf
   data-icon-size. Source unique : app Icones.
   ============================ */
[data-icon] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
    vertical-align: middle;
    flex-shrink: 0;
}

/* Listes déroulantes natives : harmoniser avec les champs (thème système + couleurs) */
select:not([multiple]) {
    color-scheme: dark;
}

select option {
    background-color: var(--bg-tertiary, #1a1a25);
    color: var(--text-primary, #f0f0f5);
}

select option:checked,
select option:hover {
    background-color: var(--bg-hover, rgba(255, 255, 255, 0.08));
    color: var(--text-primary, #f0f0f5);
}

/* Sélecteur stylé (liste HTML = même look que le champ) — activer avec data-ux-custom-select sur <select> */
.ux-select-wrap {
    position: relative;
    width: 100%;
    max-width: 100%;
}

select.ux-select-native-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

.ux-select-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 12px 40px 12px 16px;
    box-sizing: border-box;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-radius: 10px;
    color: var(--text-primary, #f0f0f5);
    font-family: inherit;
    font-size: 14px;
    font-weight: 400;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--transition-fast, 0.15s ease), background var(--transition-fast, 0.15s ease);
    user-select: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%238888a0' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 16px;
}

.ux-select-trigger:hover {
    border-color: var(--border-hover, rgba(255, 255, 255, 0.12));
}

.ux-select-trigger:focus {
    outline: none;
    border-color: var(--border-focus, var(--accent-purple, #8b5cf6));
    background-color: rgba(139, 92, 246, 0.05);
}

.ux-select-trigger[aria-expanded="true"] {
    border-color: var(--border-focus, var(--accent-purple, #8b5cf6));
}

.ux-select-trigger-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ux-select-dropdown {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    z-index: 4000;
    margin-top: 4px;
    padding: 0;
    background: var(--bg-secondary, #12121a);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-radius: 10px;
    box-shadow: var(--shadow-lg, 0 10px 40px rgba(0, 0, 0, 0.45));
    max-height: min(420px, 60vh);
    max-width: min(360px, calc(100vw - 16px));
    overflow-x: hidden;
    overflow-y: auto;
    animation: uxSelectOpen 0.12s ease;
}

.ux-select-dropdown.ux-select-open {
    display: block;
}

.ux-select-dropdown:focus {
    outline: none;
}

.ux-select-dropdown.ux-select-flip {
    bottom: calc(100% + 4px);
    top: auto;
    margin-top: 0;
    margin-bottom: 4px;
}

/* Variante OS-level (rendue par os/app.js handleUXSelectOpen) :
   le contenu et le scroll sont deportes dans un wrapper interne pour que
   la scrollbar webkit soit clippee proprement par le border-radius du
   container externe. */
.ux-select-dropdown-os {
    overflow: hidden !important;
    padding: 0;
}
.ux-select-scroll {
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    /* Petit padding interne pour que les options ne touchent pas les
       arrondis du container et que la scrollbar reste a l'interieur. */
    padding: 4px 0;
    /* La hauteur max est posee par JS (positionList) en sync avec celle
       du container externe. */
}
.ux-select-scroll::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
.ux-select-scroll::-webkit-scrollbar-track {
    background: transparent;
}
.ux-select-scroll::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
    border-radius: 0;
    border: 2px solid transparent;
    background-clip: padding-box;
}
.ux-select-scroll::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.32);
    background-clip: padding-box;
}
.ux-select-scroll::-webkit-scrollbar-button { display: none !important; }

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

.ux-select-option {
    padding: 10px 16px;
    font-size: 14px;
    color: var(--text-primary, #f0f0f5);
    cursor: pointer;
    transition: background 0.1s ease;
    user-select: none;
}

.ux-select-option:hover,
.ux-select-option.ux-select-option-active {
    background: var(--bg-hover, rgba(255, 255, 255, 0.06));
}

.ux-select-option.is-selected {
    color: var(--accent-purple, #8b5cf6);
    font-weight: 500;
}

.ux-select-option[disabled] {
    opacity: 0.45;
    cursor: default;
    pointer-events: none;
}

.ux-select-optgroup-label {
    padding: 8px 16px 4px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary, #a0aec0);
    cursor: default;
    user-select: none;
    opacity: 0.7;
}

.ux-select-optgroup-label:not(:first-child) {
    margin-top: 4px;
    border-top: 1px solid var(--border, rgba(255, 255, 255, 0.06));
    padding-top: 10px;
}

.ux-select-option-grouped {
    padding-left: 24px;
}

/* ============================
   MENU D'ACTIONS (popover déclenché par bouton)
   ----------------------------
   Aligné sur .ux-select-dropdown. Pattern utilisé p.ex. par le bouton "+"
   dans la zone de saisie de l'Assistant. Différent de .ux-context-menu
   (clic droit) et de <select data-ux-custom-select>.

   ATTENTION : ne JAMAIS poser padding/border/background/border-radius/
   box-shadow via style inline ou cssText en JS — ces déclarations
   battent le CSS et masquent silencieusement les corrections de style.
   Le JS ne doit positionner que (position, top, left, width, max-height,
   z-index, display).
   ============================ */

.ux-action-menu-wrap {
    position: relative;
    display: inline-block;
}

.ux-action-menu {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 4000;
    min-width: 240px;
    margin: 0;
    padding: 0;
    background: var(--bg-secondary, #12121a);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-radius: 10px;
    box-shadow: var(--shadow-lg, 0 10px 40px rgba(0, 0, 0, 0.45));
    overflow: hidden;
    animation: uxSelectOpen 0.12s ease;
}

.ux-action-menu.open {
    display: block;
}

.ux-action-menu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: 10px 16px;
    border: none;
    border-radius: 0;
    background: transparent;
    appearance: none;
    -webkit-appearance: none;
    color: var(--text-primary, #f0f0f5);
    font-family: inherit;
    font-size: 14px;
    text-align: left;
    cursor: pointer;
    user-select: none;
    transition: background 0.1s ease;
}

.ux-action-menu-item:hover,
.ux-action-menu-item:focus-visible {
    background: var(--bg-hover, rgba(255, 255, 255, 0.06));
    outline: none;
}

.ux-action-menu-item.is-danger {
    color: var(--error, #ef4444);
}

.ux-action-menu-item.is-danger:hover,
.ux-action-menu-item.is-danger:focus-visible {
    background: rgba(239, 68, 68, 0.12);
}

.ux-action-menu-item[disabled] {
    opacity: 0.45;
    cursor: default;
    pointer-events: none;
}

.ux-action-menu-item svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    stroke: currentColor;
    stroke-width: 2;
    fill: none;
}

.ux-action-menu-separator {
    height: 1px;
    margin: 4px 0;
    background: var(--border, rgba(255, 255, 255, 0.08));
}

/* ============================
   BOUTONS STANDARD
   ============================ */

.ux-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px;
    border: none;
    border-radius: 10px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--ux-transition-fast);
    user-select: none;
    white-space: nowrap;
}

.ux-btn svg {
    width: 16px;
    height: 16px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    flex-shrink: 0;
}

/* Bouton par défaut = Vert (action principale) */
.ux-btn-default, .ux-btn {
    background: var(--ux-btn-default);
    color: white;
}
.ux-btn-default:hover, .ux-btn:hover {
    background: var(--ux-btn-default-hover);
    transform: translateY(-1px);
}

/* Bouton primaire = Bleu */
.ux-btn-primary {
    background: var(--ux-btn-primary);
    color: white;
}
.ux-btn-primary:hover {
    background: var(--ux-btn-primary-hover);
    transform: translateY(-1px);
}

/* Bouton secondaire */
.ux-btn-secondary {
    background: var(--ux-btn-secondary);
    color: var(--text-primary, #f0f0f5);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
}
.ux-btn-secondary:hover {
    background: var(--ux-btn-secondary-hover);
    border-color: var(--border-hover, rgba(255, 255, 255, 0.15));
}

/* Bouton danger */
.ux-btn-danger {
    background: var(--ux-btn-danger);
    color: white;
}
.ux-btn-danger:hover {
    background: var(--ux-btn-danger-hover);
    transform: translateY(-1px);
}

/* Variations de couleur */
.ux-btn-purple {
    background: var(--ux-btn-purple);
    color: white;
}
.ux-btn-purple:hover {
    background: var(--ux-btn-purple-hover);
    transform: translateY(-1px);
}

.ux-btn-pink {
    background: var(--ux-btn-pink);
    color: white;
}
.ux-btn-pink:hover {
    background: var(--ux-btn-pink-hover);
    transform: translateY(-1px);
}

.ux-btn-orange {
    background: var(--ux-btn-orange);
    color: white;
}
.ux-btn-orange:hover {
    background: var(--ux-btn-orange-hover);
    transform: translateY(-1px);
}

.ux-btn-cyan {
    background: var(--ux-btn-cyan);
    color: white;
}
.ux-btn-cyan:hover {
    background: var(--ux-btn-cyan-hover);
    transform: translateY(-1px);
}

/* Tailles de boutons */
.ux-btn-sm {
    padding: 8px 14px;
    font-size: 13px;
}

.ux-btn-lg {
    padding: 16px 28px;
    font-size: 16px;
}

/* Bouton icone-only (carre, contient un seul SVG) :
   on force le centrage parfait + un padding compact symetrique. */
.ux-btn-icon {
    justify-content: center;
    align-items: center;
    box-sizing: border-box;
    gap: 0;
    padding: 8px;
    line-height: 1;
    flex: 0 0 auto;
}
.ux-btn-icon > svg {
    display: block;
    margin: 0;
}

/* ============================
   SLIDE-TO-DELETE
   
   Principe anti double-clic :
   1. Premier clic → "Confirmer?" apparaît à droite du bouton
   2. Le container s'agrandit → pousse les boutons adjacents vers la gauche
   3. Deuxième clic → exécute l'action (le bouton "Modifier" a bougé)
   
   Structure HTML requise:
   <div class="ux-slide-delete-container">
       <button class="ux-slide-delete-btn">Supprimer</button>
       <span class="ux-slide-delete-confirm">Confirmer?</span>
   </div>
   ============================ */

.ux-slide-delete-container {
    display: inline-flex;
    align-items: center;
    height: 38px;
}

.ux-slide-delete-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 14px;
    background: var(--ux-btn-danger);
    border: none;
    border-radius: 8px;
    color: white;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease;
    user-select: none;
    white-space: nowrap;
    flex-shrink: 0;
}

.ux-slide-delete-btn:hover {
    background: var(--ux-btn-danger-hover);
}

.ux-slide-delete-btn svg {
    width: 14px;
    height: 14px;
    stroke: currentColor;
    stroke-width: 2;
    fill: none;
    flex-shrink: 0;
}

.ux-slide-delete-confirm {
    color: #f87171;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    max-width: 0;
    opacity: 0;
    padding: 0;
    transition: max-width 0.3s cubic-bezier(0.4, 0, 0.2, 1), 
                opacity 0.2s ease 0.1s,
                padding 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* État révélé :
   - Le texte "Confirmer?" apparaît à droite du bouton
   - Le container s'agrandit → pousse les boutons adjacents vers la gauche
*/
.ux-slide-delete-container.revealed .ux-slide-delete-confirm {
    max-width: 90px;
    opacity: 1;
    padding-left: 10px;
}

/* ============================
   SLIDE TO CONFIRM (style iPhone "slide to unlock")

   Slider draggable de gauche a droite pour confirmer une action critique.
   Utilisation via UX.slideToConfirm({ container, label, color, onConfirm }).

   Structure HTML (generee par UX.slideToConfirm) :
   <div class="ux-slide-to-confirm">
       <div class="ux-stc-track">
           <div class="ux-stc-fill"></div>
           <div class="ux-stc-label">Glisser pour confirmer</div>
           <div class="ux-stc-handle"><svg>...</svg></div>
       </div>
   </div>
   ============================ */

.ux-slide-to-confirm {
    --ux-stc-color: #dc2626;
    --ux-stc-height: 52px;
    --ux-stc-handle-size: 44px;
    width: 100%;
    user-select: none;
    -webkit-user-select: none;
}

.ux-slide-to-confirm .ux-stc-track {
    position: relative;
    height: var(--ux-stc-height);
    border-radius: calc(var(--ux-stc-height) / 2);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    overflow: hidden;
    display: flex;
    align-items: center;
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
}

.ux-slide-to-confirm .ux-stc-fill {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: calc(var(--ux-stc-handle-size) + 8px);
    background: var(--ux-stc-color);
    border-radius: calc(var(--ux-stc-height) / 2);
    z-index: 1;
    transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.ux-slide-to-confirm .ux-stc-label {
    position: relative;
    z-index: 2;
    width: 100%;
    text-align: center;
    color: var(--text-secondary, #a0aec0);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.2px;
    pointer-events: none;
    padding: 0 calc(var(--ux-stc-handle-size) + 12px);
    box-sizing: border-box;
    transition: opacity 0.25s ease, color 0.2s ease;
}

.ux-slide-to-confirm .ux-stc-handle {
    position: absolute;
    top: 50%;
    left: 4px;
    width: var(--ux-stc-handle-size);
    height: var(--ux-stc-handle-size);
    margin-top: calc(var(--ux-stc-handle-size) / -2);
    border-radius: 50%;
    background: var(--ux-stc-color);
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: grab;
    z-index: 3;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.2);
    touch-action: none;
    outline: none;
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.15s ease;
}

.ux-slide-to-confirm .ux-stc-handle:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.ux-slide-to-confirm .ux-stc-handle:focus-visible {
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.25), 0 2px 8px rgba(0, 0, 0, 0.35);
}

.ux-slide-to-confirm.dragging .ux-stc-handle,
.ux-slide-to-confirm .ux-stc-handle:active {
    cursor: grabbing;
}

.ux-slide-to-confirm .ux-stc-handle svg {
    width: 22px;
    height: 22px;
}

.ux-slide-to-confirm.confirmed .ux-stc-label {
    color: #ffffff;
    opacity: 1;
}

/* ============================
   CHECKBOXES & TOGGLES
   ============================ */

.ux-checkbox-group,
.ux-toggle-group {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ux-checkbox-item,
.ux-toggle-item {
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
    user-select: none;
}

.ux-checkbox-item input,
.ux-toggle-item input {
    position: fixed;
    opacity: 0;
    pointer-events: none;
    width: 0;
    height: 0;
    margin: 0;
    padding: 0;
}

.ux-checkbox-custom {
    width: 22px;
    height: 22px;
    border: 2px solid rgba(255, 255, 255, 0.08);
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background var(--ux-transition-fast), border-color var(--ux-transition-fast);
    flex-shrink: 0;
}

.ux-checkbox-item input:checked + .ux-checkbox-custom {
    background: var(--ux-btn-default);
    border-color: var(--ux-btn-default);
}

.ux-checkbox-custom::after {
    content: '';
    width: 12px;
    height: 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    opacity: 0;
    transition: opacity var(--ux-transition-fast);
}

.ux-checkbox-item input:checked + .ux-checkbox-custom::after {
    opacity: 1;
}

/* Radio (meme principe que la case : input masque + pastille personnalisee) */
.ux-radio-group {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ux-radio-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    cursor: pointer;
    user-select: none;
}

.ux-radio-item input {
    position: fixed;
    opacity: 0;
    pointer-events: none;
    width: 0;
    height: 0;
    margin: 0;
    padding: 0;
}

.ux-radio-custom {
    width: 22px;
    height: 22px;
    border: 2px solid rgba(255, 255, 255, 0.22);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color var(--ux-transition-fast), background var(--ux-transition-fast);
    flex-shrink: 0;
    margin-top: 2px;
    box-sizing: border-box;
}

.ux-radio-item input:checked + .ux-radio-custom {
    border-color: var(--ux-btn-default);
    background: rgba(46, 204, 113, 0.12);
}

.ux-radio-custom::after {
    content: '';
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--ux-btn-default);
    opacity: 0;
    transform: scale(0.5);
    transition: opacity var(--ux-transition-fast), transform var(--ux-transition-fast);
}

.ux-radio-item input:checked + .ux-radio-custom::after {
    opacity: 1;
    transform: scale(1);
}

/* Toggle switch */
.ux-toggle-switch {
    width: 44px;
    height: 24px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    position: relative;
    transition: all var(--ux-transition-fast);
    flex-shrink: 0;
}

.ux-toggle-switch::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 20px;
    height: 20px;
    background: #8888a0;
    border-radius: 50%;
    transition: all var(--ux-transition-fast);
}

.ux-toggle-item input:checked + .ux-toggle-switch {
    background: rgba(46, 204, 113, 0.3);
}

.ux-toggle-item input:checked + .ux-toggle-switch::after {
    left: 22px;
    background: var(--ux-btn-default);
}

/* ============================
   DIALOGUES
   ============================ */

.ux-dialog-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.ux-dialog-overlay.visible {
    opacity: 1;
}

.ux-dialog-overlay.closing {
    opacity: 0;
}

.ux-dialog {
    position: absolute;
    /* Largeur maitrisee : le dialogue s'adapte a son contenu (largeur auto)
       avec un minimum confortable et un maximum raisonnable. Les dialogues qui
       ont besoin d'etre plus larges (tableaux, listes, editeurs) doivent definir
       leur propre largeur via `dialogClass` (ex. .mon-app-dlg .ux-dialog). */
    width: fit-content;
    min-width: min(360px, calc(100vw - 32px));
    max-width: min(480px, calc(100vw - 32px));
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary, #12121a);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    box-shadow: 0 30px 100px rgba(0, 0, 0, 0.5);
    overflow: hidden;
    transform: scale(0.95);
    transition: transform 0.2s ease;
}

.ux-dialog-overlay.visible .ux-dialog {
    transform: scale(1);
}

.ux-dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: var(--bg-tertiary, #1a1a25);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    cursor: grab;
    flex-shrink: 0;
}

.ux-dialog-header:active {
    cursor: grabbing;
}

.ux-dialog-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--ux-btn-purple);
}

.ux-dialog-close {
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: all var(--ux-transition-fast);
}

.ux-dialog-close:hover {
    background: rgba(239, 68, 68, 0.2);
}

.ux-dialog-close svg {
    width: 16px;
    height: 16px;
    stroke: #8888a0;
}

.ux-dialog-close:hover svg {
    stroke: var(--ux-btn-danger);
}

.ux-dialog-content {
    padding: 24px;
    font-size: 14px;
    line-height: 1.6;
    color: var(--text-primary, #d0d0d8);
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

.ux-dialog-content p {
    margin: 0;
}

/* Largeur intelligente des dialogues : un message simple (texte seul, rendu
   dans un <p> enfant direct du contenu) se lit sur quelques lignes au lieu
   d'une seule ligne tres longue. Les dialogues riches definissent leur propre
   largeur via leur contenu (divs, champs, textarea) et ne sont pas affectes. */
.ux-dialog-content > p {
    max-width: 460px;
}

.ux-dialog-content label {
    color: var(--text-secondary, #a0aec0);
}

/* Neutraliser le fond blanc impose par l'autofill du navigateur (Chrome, Edge)
   sur les champs reconnus (courriel, mot de passe...). Sans cela, le champ passe
   en fond blanc des qu'une valeur connue est saisie/proposee, ce qui casse le
   theme sombre. L'astuce : un box-shadow interne opaque couvre le fond force, et
   text-fill-color garde le texte lisible. La transition tres longue empeche le
   flash blanc au focus. */
.ux-dialog-content input:-webkit-autofill,
.ux-dialog-content input:-webkit-autofill:hover,
.ux-dialog-content input:-webkit-autofill:focus,
.ux-dialog-content input:-webkit-autofill:active,
.ux-dialog-content textarea:-webkit-autofill {
    -webkit-text-fill-color: var(--text-primary, #f0f0f5);
    -webkit-box-shadow: 0 0 0 1000px var(--bg-secondary, #12121a) inset;
    box-shadow: 0 0 0 1000px var(--bg-secondary, #12121a) inset;
    caret-color: var(--text-primary, #f0f0f5);
    border-color: var(--border, rgba(255, 255, 255, 0.08));
    transition: background-color 99999s ease-in-out 0s;
}

/* ============================
   SAISIE DE CODE (PIN / OTP) — une case par chiffre (UX.attachPinInputs)
   ============================ */
.ux-pin-inputs {
    display: flex;
    gap: 8px;
    justify-content: center;
    flex-wrap: nowrap;
}

.ux-pin-input {
    width: 44px;
    height: 52px;
    text-align: center;
    font-size: 22px;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.05);
    border: 2px solid var(--border, rgba(255, 255, 255, 0.12));
    border-radius: 10px;
    color: var(--text-primary, #f0f0f5);
    font-family: 'Courier New', monospace;
    caret-color: var(--accent, #4a9eff);
    transition: border-color var(--ux-transition-fast), background var(--ux-transition-fast);
}

.ux-pin-input:focus {
    outline: none;
    border-color: var(--accent, #4a9eff);
    background: rgba(255, 255, 255, 0.08);
}

.ux-dialog-footer {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    padding: 12px 20px 16px;
    flex-shrink: 0;
}

/* Bouton pousse a gauche (ex: Supprimer), le reste reste a droite */
.ux-dialog-footer .ux-dialog-btn-left {
    margin-right: auto;
}

.ux-dialog-btn {
    padding: 10px 20px;
    border-radius: 10px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--ux-transition-fast);
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-primary, #f0f0f5);
}

.ux-dialog-btn:hover {
    background: rgba(255, 255, 255, 0.1);
}

.ux-dialog-btn.primary {
    background: var(--ux-btn-default);
    border: none;
    color: white;
}

.ux-dialog-btn.primary:hover {
    background: var(--ux-btn-default-hover);
}

.ux-dialog-btn.danger {
    background: rgba(231, 76, 60, 0.2);
    border-color: rgba(231, 76, 60, 0.3);
    color: var(--ux-btn-danger);
}

.ux-dialog-btn.danger:hover {
    background: var(--ux-btn-danger);
    color: white;
}

/* ============================
   INFO BAR / TOAST  (UX.infoBar) — MODE FLOTTANT
   ----------------------------
   Toast flottant en OVERLAY dans un coin de la fenetre :
   - jamais full-width, jamais colle bord a bord,
   - ne POUSSE JAMAIS le contenu de l'app (aucune reservation d'espace,
     aucun padding sur <body>, aucun redimensionnement),
   - n'occupe aucune place dans le flux (position: fixed, hors flux),
   - s'empile dans le coin choisi (bottom-right par defaut).
   Le toast peut recouvrir une petite partie du contenu : chaque app
   choisit le coin (UX.infoBar.setDefaultPosition / option position) pour
   ne masquer ni commande, ni bouton, ni texte important.
   ============================ */

.ux-infobar-stack {
    position: fixed;
    z-index: 20000;
    display: flex;
    gap: 10px;
    max-width: min(420px, calc(100vw - 32px));
    pointer-events: none;
}

.ux-infobar-stack--bottom-right  { right: 20px; bottom: 20px; flex-direction: column-reverse; align-items: flex-end; }
.ux-infobar-stack--bottom-left   { left: 20px;  bottom: 20px; flex-direction: column-reverse; align-items: flex-start; }
.ux-infobar-stack--top-right     { right: 20px; top: 20px;    flex-direction: column;         align-items: flex-end; }
.ux-infobar-stack--top-left      { left: 20px;  top: 20px;    flex-direction: column;         align-items: flex-start; }
.ux-infobar-stack--bottom-center { left: 50%; transform: translateX(-50%); bottom: 20px; flex-direction: column-reverse; align-items: center; }
.ux-infobar-stack--top-center    { left: 50%; transform: translateX(-50%); top: 20px;    flex-direction: column;         align-items: center; }

.ux-infobar {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    max-width: 420px;
    padding: 12px 14px;
    background: var(--bg-secondary, #161b22);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-left: 3px solid var(--ux-info);
    border-radius: 10px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
    font-size: 14px;
    line-height: 1.4;
    color: var(--text-primary, #f0f0f5);
    pointer-events: auto;
    user-select: none;
    box-sizing: border-box;
    opacity: 0;
    transition: opacity .2s ease, transform .24s cubic-bezier(.16, 1, .3, 1);
    will-change: transform, opacity;
}

/* Sens d'entree selon le coin d'ancrage (glissement depuis le bord) */
.ux-infobar-stack--bottom-right .ux-infobar,
.ux-infobar-stack--top-right .ux-infobar    { transform: translateX(24px); }
.ux-infobar-stack--bottom-left .ux-infobar,
.ux-infobar-stack--top-left .ux-infobar     { transform: translateX(-24px); }
.ux-infobar-stack--top-center .ux-infobar   { transform: translateY(-24px); }
.ux-infobar-stack--bottom-center .ux-infobar{ transform: translateY(24px); }

.ux-infobar.ux-infobar--visible {
    opacity: 1;
    transform: translate(0, 0);
}

/* La sortie reutilise le transform de base du coin (retrait du --visible)
   et eteint l'opacite. */
.ux-infobar--leaving {
    opacity: 0;
}

.ux-infobar__icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    margin-top: 1px;
    stroke: currentColor;
}

.ux-infobar__message {
    flex: 1 1 auto;
    min-width: 0;
    word-wrap: break-word;
    overflow-wrap: anywhere;
}

.ux-infobar__actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.ux-infobar__action {
    appearance: none;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 13px;
    font-weight: 500;
    padding: 5px 10px;
    border-radius: 6px;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, filter .15s ease;
}

.ux-infobar__action:hover {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.25);
}

.ux-infobar__action--primary {
    background: var(--accent, var(--ux-btn-primary));
    border-color: transparent;
    color: #fff;
}

.ux-infobar__action--primary:hover {
    filter: brightness(1.12);
    background: var(--accent, var(--ux-btn-primary));
    border-color: transparent;
}

.ux-infobar__action--danger {
    background: var(--ux-error);
    border-color: transparent;
    color: #fff;
}

.ux-infobar__action--danger:hover {
    filter: brightness(1.12);
    background: var(--ux-error);
    border-color: transparent;
}

.ux-infobar__close {
    appearance: none;
    background: transparent;
    border: none;
    color: var(--text-secondary, rgba(255,255,255,0.55));
    width: 26px;
    height: 26px;
    border-radius: 6px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background .15s ease, color .15s ease;
}

.ux-infobar__close svg {
    width: 14px;
    height: 14px;
}

.ux-infobar__close:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-primary, #fff);
}

.ux-infobar--success { border-left-color: var(--ux-success); }
.ux-infobar--success .ux-infobar__icon { color: var(--ux-success); }

.ux-infobar--error { border-left-color: var(--ux-error); }
.ux-infobar--error .ux-infobar__icon { color: var(--ux-error); }

.ux-infobar--info { border-left-color: var(--ux-info); }
.ux-infobar--info .ux-infobar__icon { color: var(--ux-info); }

.ux-infobar--warning { border-left-color: var(--ux-warning); }
.ux-infobar--warning .ux-infobar__icon { color: var(--ux-warning); }

/* ============================
   PANEL RESIZER (redimensionnement de panneaux)
   ============================ */

/**
 * Composant de panneau redimensionnable
 * 
 * Usage:
 *   <div class="ux-resizable-layout">
 *       <aside class="ux-panel ux-panel-left" id="left-panel">...</aside>
 *       <div class="ux-resizer ux-resizer-left" id="left-resizer"></div>
 *       <main class="ux-panel-main">...</main>
 *       <div class="ux-resizer ux-resizer-right" id="right-resizer"></div>
 *       <aside class="ux-panel ux-panel-right" id="right-panel">...</aside>
 *   </div>
 * 
 * JavaScript:
 *   const leftResizer = UX.resizer({
 *       resizerId: 'left-resizer',
 *       panelId: 'left-panel',
 *       side: 'left',
 *       minWidth: 200,
 *       maxWidth: 500,
 *       storageKey: 'myapp_left_panel',
 *       collapsible: true
 *   });
 */

/* Layout conteneur */
.ux-resizable-layout {
    display: flex;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

/* Panneaux latéraux */
.ux-panel {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--bg-secondary, #12121a);
    flex-shrink: 0;
    /* Pas de transition par défaut - géré par .ux-panel-animating pour collapse/expand */
}

.ux-panel-left {
    width: 280px;
    min-width: 200px;
    border-right: 1px solid var(--border, rgba(255, 255, 255, 0.08));
}

.ux-panel-right {
    width: 320px;
    min-width: 200px;
    border-left: 1px solid var(--border, rgba(255, 255, 255, 0.08));
}

/* Zone principale centrale */
.ux-panel-main {
    flex: 1;
    min-width: 200px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* Barre de redimensionnement verticale */
.ux-resizer {
    width: 6px;
    background: var(--ux-resizer-bg, rgba(255, 255, 255, 0.06));
    cursor: col-resize;
    flex-shrink: 0;
    position: relative;
    transition: background 0.2s ease;
    -webkit-user-select: none;
    user-select: none;
    z-index: 10;
}

.ux-resizer:hover,
.ux-resizer.ux-resizer-dragging {
    background: var(--accent, #8b5cf6);
}

/* Indicateur visuel central - barre verticale */
.ux-resizer::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 3px;
    height: 40px;
    background: var(--ux-resizer-color, var(--accent, #8b5cf6));
    opacity: 0.7;
    border-radius: 2px;
    transition: all 0.2s ease;
}

.ux-resizer:hover::after,
.ux-resizer.ux-resizer-dragging::after {
    background: rgba(255, 255, 255, 0.9);
    opacity: 1;
    height: 60px;
    box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}

/* État fermé du panneau - GAUCHE */
.ux-resizer-left.ux-resizer-collapsed {
    background: linear-gradient(90deg, var(--accent, #8b5cf6), rgba(139, 92, 246, 0.7));
    cursor: pointer;
    width: 8px;
}

.ux-resizer-left.ux-resizer-collapsed::after {
    width: 3px;
    height: 50px;
    background: rgba(255, 255, 255, 0.7);
    opacity: 1;
}

/* Chevron indiquant qu'on peut réouvrir - vers la droite */
.ux-resizer-left.ux-resizer-collapsed::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, calc(-50% - 35px));
    width: 0;
    height: 0;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
    border-left: 6px solid rgba(255, 255, 255, 0.8);
}

/* État fermé du panneau - DROITE */
.ux-resizer-right.ux-resizer-collapsed {
    background: linear-gradient(270deg, var(--accent, #8b5cf6), rgba(139, 92, 246, 0.7));
    cursor: pointer;
    width: 8px;
}

.ux-resizer-right.ux-resizer-collapsed::after {
    width: 3px;
    height: 50px;
    background: rgba(255, 255, 255, 0.7);
    opacity: 1;
}

/* Chevron indiquant qu'on peut réouvrir - vers la gauche */
.ux-resizer-right.ux-resizer-collapsed::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, calc(-50% - 35px));
    width: 0;
    height: 0;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
    border-right: 6px solid rgba(255, 255, 255, 0.8);
}

.ux-resizer.ux-resizer-collapsed:hover {
    background: var(--accent-hover, #7c3aed);
    filter: brightness(1.1);
}

/* Panneau collapsé */
.ux-panel-collapsed {
    min-width: 0 !important;
    width: 0 !important;
    overflow: hidden;
    flex: none !important;
    border: none !important;
}

.ux-panel-collapsed > * {
    opacity: 0;
    pointer-events: none;
}

/* Animation de transition */
.ux-panel-animating {
    transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1), 
                min-width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

/* PERFORMANCE: Désactiver les transitions pendant le drag */
.ux-panel-resizing,
.ux-panel-resizing * {
    transition: none !important;
}

/* Empêcher la sélection de texte pendant le resize */
body.ux-resizing,
body.ux-resizing * {
    user-select: none !important;
    -webkit-user-select: none !important;
    cursor: col-resize !important;
}

/* Désactiver les pointer-events sur les iframes pendant le resize */
body.ux-resizing iframe {
    pointer-events: none !important;
}

/* Tooltip au survol du resizer fermé */
.ux-resizer.ux-resizer-collapsed[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    padding: 6px 12px;
    background: var(--bg-tertiary, #1a1a25);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.1));
    border-radius: 6px;
    font-size: 12px;
    color: var(--text-primary, #f0f0f5);
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
    z-index: 100;
    width: auto;
    height: auto;
}

.ux-resizer-left.ux-resizer-collapsed[data-tooltip]::after {
    left: calc(100% + 8px);
}

.ux-resizer-right.ux-resizer-collapsed[data-tooltip]::after {
    right: calc(100% + 8px);
}

.ux-resizer.ux-resizer-collapsed:hover[data-tooltip]::after {
    opacity: 1;
}

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

@media (max-width: 768px) {
    .ux-dialog {
        min-width: auto;
        width: calc(100vw - 32px);
        max-width: 400px;
    }
    
    .ux-infobar-stack {
        width: 100%;
    }
    .ux-infobar {
        font-size: 13px;
    }
    .ux-infobar--visible {
        padding: 9px 12px;
    }
}

@media (max-width: 480px) {
    .ux-dialog-footer {
        flex-direction: column;
    }
    
    .ux-dialog-btn {
        width: 100%;
        justify-content: center;
        text-align: center;
    }
}

/* ============================
   APP LOADER (écran de chargement global)
   ============================ */

/**
 * Loader plein écran pour les apps
 * 
 * Usage:
 *   1. Ajouter la classe "app-loading" au <body>
 *   2. Ajouter le HTML du loader (ou utiliser UX.showLoader())
 *   3. Appeler UX.appReady() quand les données sont chargées
 * 
 * Exemple HTML:
 *   <body class="app-loading">
 *       <div class="ux-app-loader">
 *           <div class="ux-app-loader-spinner"></div>
 *       </div>
 *       <!-- contenu de l'app -->
 *   </body>
 */

/* État de chargement - cache tout le contenu sauf le loader */
body.app-loading > *:not(.ux-app-loader):not(script):not(link):not(style) {
    visibility: hidden !important;
    opacity: 0 !important;
    pointer-events: none !important;
}

body.app-loading .ux-app-loader {
    visibility: visible !important;
    opacity: 1 !important;
}

/* Transition fluide à la fin du chargement
   IMPORTANT: Exclure les éléments qui gèrent leur propre opacité (toasts, modals, overlays)
   Sinon l'animation force opacity:1 et override leur état par défaut (opacity:0) */
body.app-loaded > *:not(.ux-app-loader):not(.toast-notification):not(.modal):not(.ux-infobar-stack):not(.ux-dialog-overlay):not(.auth-overlay) {
    animation: uxAppFadeIn 0.3s ease forwards;
}

@keyframes uxAppFadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* Container du loader */
.ux-app-loader {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-primary, #0a0a0f);
    z-index: 99999;
    transition: opacity 0.3s ease, visibility 0.3s ease;
}

/* Animation de disparition */
.ux-app-loader.hiding {
    opacity: 0;
    visibility: hidden;
}

/* Spinner animé */
.ux-app-loader-spinner {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    position: relative;
}

.ux-app-loader-spinner::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 3px solid rgba(255, 255, 255, 0.1);
}

.ux-app-loader-spinner::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 3px solid transparent;
    border-top-color: var(--accent, #4a9eff);
    animation: uxSpinnerRotate 0.8s linear infinite;
}

@keyframes uxSpinnerRotate {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

/* Variante avec message */
.ux-app-loader-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

.ux-app-loader-message {
    color: var(--text-secondary, #a0aec0);
    font-size: 14px;
    font-weight: 500;
}

/* ============================
   TEXTAREA AUTO-RESIZE
   
   Textarea qui s'adapte automatiquement en hauteur
   selon son contenu, sans scroll interne tant que
   maxHeight n'est pas atteint.
   
   Usage:
     <textarea class="ux-textarea-auto" rows="1"></textarea>
   
   JavaScript (optionnel, pour contrôle manuel):
     UX.autoResize(document.getElementById('my-textarea'));
     UX.autoResizeAll('.ux-textarea-auto');
   
   Options par défaut:
     - minHeight: hauteur initiale (ou 60px)
     - maxHeight: 400px
     - resetOnEmpty: true (revient à minHeight si vide)
   ============================ */

.ux-textarea-auto {
    width: 100%;
    min-height: 60px;
    max-height: 400px;
    padding: 12px 16px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-radius: 10px;
    color: var(--text-primary, #f0f0f5);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.5;
    resize: none;
    overflow: hidden;
    box-sizing: border-box;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.ux-textarea-auto:focus {
    outline: none;
    border-color: var(--accent, #4a9eff);
    box-shadow: 0 0 0 3px rgba(74, 158, 255, 0.15);
}

.ux-textarea-auto::placeholder {
    color: var(--text-secondary, #a0aec0);
    opacity: 0.7;
}

/* Variante compacte - pour les commentaires */
.ux-textarea-auto-sm {
    min-height: 44px;
    padding: 10px 14px;
    font-size: 13px;
    border-radius: 8px;
}

/* Variante grande - pour les descriptions longues */
.ux-textarea-auto-lg {
    min-height: 100px;
    max-height: 600px;
    padding: 16px 20px;
    font-size: 15px;
}

/* ============================
   MOBILE NAV (navigation panneau mobile)
   ============================ */

/**
 * Transition slide gauche/droite pour les apps avec sidebar + main panel.
 * 
 * Structure HTML attendue :
 *   <div class="app-container ux-mobile-nav">
 *     <div class="sidebar ux-panel ux-mobile-panel" id="sidebar">...</div>
 *     <div class="ux-resizer" id="sidebar-resizer"></div>
 *     <div class="main-content ux-panel-main ux-mobile-panel">...</div>
 *   </div>
 * 
 * Activation : UX.mobileNav({ containerId, breakpoint })
 */

@media (max-width: 768px) {
    .ux-mobile-nav {
        flex-direction: row;
        overflow: hidden;
        width: 200vw;
        transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
    }

    .ux-mobile-nav.ux-mobile-show-main {
        transform: translateX(-100vw);
    }

    .ux-mobile-nav > .ux-panel,
    .ux-mobile-nav > .sidebar {
        width: 100vw !important;
        min-width: 100vw !important;
        flex-shrink: 0;
        height: 100vh;
        border-right: none !important;
    }

    .ux-mobile-nav > .ux-panel-main,
    .ux-mobile-nav > .main-content {
        width: 100vw;
        min-width: 100vw;
        flex-shrink: 0;
        height: 100vh;
    }

    .ux-mobile-nav > .ux-resizer {
        display: none !important;
    }

    .ux-mobile-back {
        display: flex !important;
    }
}

.ux-mobile-back {
    display: none;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    background: var(--bg-tertiary, rgba(30, 30, 45, 0.8));
    color: var(--text-primary, #f0f0f5);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
    flex-shrink: 0;
    user-select: none;
    padding: 0;
}

.ux-mobile-back:hover {
    background: var(--accent, #8b5cf6);
    border-color: var(--accent, #8b5cf6);
}

.ux-mobile-back svg {
    width: 20px;
    height: 20px;
    stroke: currentColor;
    stroke-width: 2;
    fill: none;
}

/* ProductivIA brand typography */
.productivia-brand {
    white-space: nowrap;
}
.productivia-brand .pia-ia {
    font-size: 0.72em;
    position: relative;
    top: -0.35em;
    font-weight: 700;
    letter-spacing: 0.02em;
}

/* ===== UX Player ===== */

.ux-player {
    background: var(--bg-card, rgba(18, 18, 26, 0.95));
    border: 1px solid var(--border, rgba(255, 255, 255, 0.06));
    border-radius: 10px;
    padding: 12px 16px;
    user-select: none;
}

.ux-player-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted, #a0aec0);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 10px;
}

.ux-player-controls {
    display: flex;
    align-items: center;
    gap: 12px;
}

.ux-player-play {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border: none;
    border-radius: 50%;
    background: var(--accent, #4a9eff);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    user-select: none;
    transition: transform 0.15s, background 0.15s;
}

.ux-player-play svg {
    width: 16px;
    height: 16px;
}

.ux-player-play:hover {
    transform: scale(1.08);
}

.ux-player-play:active {
    transform: scale(0.95);
}

.ux-player-wf-stack {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ux-player-wf-wrap {
    flex: 1;
    min-width: 0;
    height: 48px;
    cursor: pointer;
    position: relative;
    border-radius: 4px;
}

/* Dans la pile verticale (timeRuler), ne pas etirer la zone onde sur toute la hauteur */
.ux-player-wf-stack > .ux-player-wf-wrap {
    flex: 0 0 48px;
    height: 48px;
    max-height: 48px;
    align-self: stretch;
}

.ux-player-time-ruler {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 10px;
    line-height: 1.2;
    color: var(--text-muted, #6b7280);
    padding: 0 2px;
    user-select: none;
}

.ux-player-time-ruler-tick {
    flex: 0 0 auto;
}

.ux-player-wf-wrap canvas {
    width: 100%;
    height: 100%;
    display: block;
}

.ux-player-dl {
    width: 26px;
    height: 26px;
    border: none;
    background: transparent;
    color: var(--text-muted, #6b7280);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 5px;
    flex-shrink: 0;
    padding: 0;
    transition: color 0.15s, background 0.15s;
    user-select: none;
}
.ux-player-dl svg { width: 14px; height: 14px; }
.ux-player-dl:hover { color: var(--text-primary, #f0f0f5); background: rgba(255,255,255,0.06); }

.ux-player-time {
    font-size: 12px;
    font-family: var(--font-mono, monospace);
    color: var(--text-muted, #a0aec0);
    white-space: nowrap;
    min-width: 80px;
    text-align: right;
    flex-shrink: 0;
}

/* ===== Mode compact : controles empiles a droite (libere de la largeur pour
   la forme d'onde) -> L1 position courante, L2 duree totale, L3 son + dl ===== */
.ux-player-compact .ux-player-controls {
    gap: 10px;
}
.ux-player-side {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    min-width: 0;
}
.ux-player-compact .ux-player-time {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.15;
    min-width: 0;
    text-align: center;
    gap: 1px;
}
.ux-player-compact .ux-player-time-cur {
    color: var(--accent, #4a9eff);
    font-weight: 600;
}
.ux-player-compact .ux-player-time-dur {
    color: var(--text-muted, #6b7280);
    font-size: 11px;
}
.ux-player-side-icons {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
}

.ux-player-vol-wrap {
    position: relative;
    flex-shrink: 0;
}

.ux-player-vol-btn {
    width: 28px;
    height: 28px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text-muted, #a0aec0);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    user-select: none;
    transition: color 0.15s, background 0.15s;
}

.ux-player-vol-btn svg {
    width: 16px;
    height: 16px;
}

.ux-player-vol-btn:hover {
    color: var(--text-primary, #f0f0f5);
    background: rgba(255, 255, 255, 0.06);
}

.ux-player-vol-popup {
    position: absolute;
    bottom: calc(100% + 8px);
    right: -10px;
    background: var(--bg-secondary, rgba(18, 18, 26, 0.98));
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-radius: 8px;
    padding: 10px 14px;
    width: 120px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(4px);
    transition: opacity 0.15s, transform 0.15s;
    z-index: var(--z-dropdown, 100);
    box-shadow: var(--shadow-lg, 0 8px 24px rgba(0,0,0,0.4));
}

.ux-player-vol-popup.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

.ux-player-vol-track {
    width: 100%;
    height: 6px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 3px;
    position: relative;
    cursor: pointer;
}

.ux-player-vol-fill {
    height: 100%;
    background: var(--accent, #4a9eff);
    border-radius: 3px;
    width: 100%;
    pointer-events: none;
}

.ux-player-vol-thumb {
    width: 14px;
    height: 14px;
    background: #fff;
    border-radius: 50%;
    position: absolute;
    top: 50%;
    left: 100%;
    transform: translate(-50%, -50%);
    box-shadow: 0 1px 4px rgba(0,0,0,0.3);
    pointer-events: none;
}

/* =====================================================
   Lecteur video (UX.videoPlayer)
   ===================================================== */
.ux-video-player {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    border-radius: 10px;
    overflow: hidden;
    user-select: none;
    outline: none;
    font-family: inherit;
    cursor: default;
}

.ux-video-player:focus-visible {
    box-shadow: 0 0 0 2px var(--accent, #4a9eff);
}

.ux-video-player-el {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    background: #000;
    display: block;
    cursor: pointer;
}

.ux-video-player.is-fullscreen {
    border-radius: 0;
    aspect-ratio: auto;
    height: 100%;
}

/* Gros bouton play central (visible en pause uniquement) */
.ux-video-player-bigplay {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(1);
    width: 72px;
    height: 72px;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s, transform 0.2s, background 0.2s;
    z-index: 3;
}

.ux-video-player.is-paused .ux-video-player-bigplay {
    backdrop-filter: blur(6px);
}

.ux-video-player-bigplay svg {
    width: 32px;
    height: 32px;
    margin-left: 4px;
}

.ux-video-player.is-paused .ux-video-player-bigplay {
    opacity: 1;
    pointer-events: auto;
}

/* Mode clavier : on masque le gros bouton PLAY central pour ne pas gener la visualisation.
   Reactive au prochain mouvement de souris > 15 px. */
.ux-video-player.keyboard-mode .ux-video-player-bigplay {
    opacity: 0;
    pointer-events: none;
}

/* Pendant un chargement (spinner visible) ou en cas d'erreur, on cache le gros
   bouton PLAY pour eviter de superposer play + spinner (UX confuse). */
.ux-video-player.is-loading .ux-video-player-bigplay,
.ux-video-player.has-error .ux-video-player-bigplay {
    opacity: 0 !important;
    pointer-events: none !important;
}

.ux-video-player-bigplay:hover {
    background: rgba(0, 0, 0, 0.75);
    transform: translate(-50%, -50%) scale(1.08);
}

/* Spinner de chargement */
.ux-video-player-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
    z-index: 4;
}

.ux-video-player-loading.visible {
    opacity: 1;
}

.ux-video-player-spinner {
    width: 44px;
    height: 44px;
    border: 3px solid rgba(255, 255, 255, 0.18);
    border-top-color: #fff;
    border-radius: 50%;
    animation: ux-video-player-spin 0.8s linear infinite;
}

@keyframes ux-video-player-spin {
    to { transform: rotate(360deg); }
}

.ux-video-player-loading-msg {
    color: rgba(255, 255, 255, 0.85);
    font-size: 12px;
    text-align: center;
    margin-top: 10px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    min-height: 16px;
}

.ux-video-player-loading {
    flex-direction: column;
}

/* Overlay d'erreur */
.ux-video-player-error {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(4px);
    color: #fff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 24px;
    text-align: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
    z-index: 7;
}

.ux-video-player-error.visible {
    opacity: 1;
    pointer-events: auto;
}

.ux-video-player-error-icon {
    width: 48px;
    height: 48px;
    color: #ef4444;
}

.ux-video-player-error-icon svg {
    width: 100%;
    height: 100%;
}

.ux-video-player-error-title {
    font-size: 16px;
    font-weight: 600;
    color: #fff;
    max-width: 80%;
}

.ux-video-player-error-desc {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.7);
    max-width: 80%;
    line-height: 1.5;
}

.ux-video-player-error-retry {
    margin-top: 8px;
    padding: 8px 18px;
    background: var(--accent, #4a9eff);
    color: #fff;
    border: none;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, transform 0.15s;
    font-family: inherit;
}

.ux-video-player-error-retry:hover {
    transform: translateY(-1px);
    filter: brightness(1.15);
}

/* Thumbnail preview (popup sur hover timeline) */
.ux-video-player-thumb {
    position: absolute;
    left: 0;
    bottom: 80px;
    background: rgba(0, 0, 0, 0.85);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 6px;
    padding: 4px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.1s;
    z-index: 5;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

.ux-video-player-thumb.visible {
    opacity: 1;
}

.ux-video-player-thumb canvas {
    display: block;
    border-radius: 4px;
    background: #111;
}

.ux-video-player-thumb-time {
    text-align: center;
    color: #fff;
    font-size: 11px;
    font-family: var(--font-mono, monospace);
    padding: 3px 0 1px;
    letter-spacing: 0.3px;
}

/* Barre de controles (bottom) */
.ux-video-player-controls {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 14px 12px;
    background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.35) 60%, rgba(0,0,0,0) 100%);
    color: #fff;
    opacity: 0;
    transform: translateY(4px);
    pointer-events: none;
    transition: opacity 0.2s, transform 0.2s;
    z-index: 6;
}

.ux-video-player.controls-visible .ux-video-player-controls,
.ux-video-player.is-paused .ux-video-player-controls {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.ux-video-player-play {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background 0.15s, transform 0.15s;
}

.ux-video-player-play svg {
    width: 14px;
    height: 14px;
}

.ux-video-player-play:hover {
    background: rgba(255, 255, 255, 0.25);
}

.ux-video-player-play:active {
    transform: scale(0.95);
}

.ux-video-player-time {
    font-size: 12px;
    font-family: var(--font-mono, monospace);
    color: rgba(255, 255, 255, 0.9);
    white-space: nowrap;
    min-width: 80px;
    flex-shrink: 0;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.ux-video-player-wf-wrap {
    flex: 1;
    min-width: 0;
    height: 36px;
    cursor: pointer;
    position: relative;
    border-radius: 4px;
}

.ux-video-player-wf-wrap canvas {
    width: 100%;
    height: 100%;
    display: block;
}

.ux-video-player-fs {
    width: 32px;
    height: 32px;
    border: none;
    background: transparent;
    color: rgba(255, 255, 255, 0.9);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    flex-shrink: 0;
    border-radius: 6px;
    transition: background 0.15s, color 0.15s;
}

.ux-video-player-fs svg {
    width: 18px;
    height: 18px;
}

.ux-video-player-fs .ux-fs-exit { display: none; }
.ux-video-player.is-fullscreen .ux-video-player-fs .ux-fs-enter { display: none; }
.ux-video-player.is-fullscreen .ux-video-player-fs .ux-fs-exit { display: block; }

.ux-video-player-fs:hover {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}

/* Volume (meme structure que UX.player) */
.ux-video-player-vol-wrap {
    position: relative;
    flex-shrink: 0;
}

.ux-video-player-vol-btn {
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: rgba(255, 255, 255, 0.9);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: background 0.15s, color 0.15s;
}

.ux-video-player-vol-btn svg {
    width: 18px;
    height: 18px;
}

.ux-video-player-vol-btn:hover {
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
}

.ux-video-player-vol-popup {
    position: absolute;
    bottom: calc(100% + 8px);
    right: -4px;
    background: rgba(18, 18, 26, 0.98);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 8px;
    padding: 10px 14px;
    width: 120px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(4px);
    transition: opacity 0.15s, transform 0.15s;
    z-index: var(--z-dropdown, 100);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

.ux-video-player-vol-popup.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}

.ux-video-player-vol-track {
    width: 100%;
    height: 6px;
    background: rgba(255, 255, 255, 0.15);
    border-radius: 3px;
    position: relative;
    cursor: pointer;
}

.ux-video-player-vol-fill {
    height: 100%;
    background: var(--accent, #4a9eff);
    border-radius: 3px;
    width: 100%;
    pointer-events: none;
}

.ux-video-player-vol-thumb {
    width: 14px;
    height: 14px;
    background: #fff;
    border-radius: 50%;
    position: absolute;
    top: 50%;
    left: 100%;
    transform: translate(-50%, -50%);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    pointer-events: none;
}

/* Masquer le curseur natif quand les controles sont caches pendant la lecture */
.ux-video-player.is-playing:not(.controls-visible) {
    cursor: none;
}

/* Menu contextuel generique (UX.contextMenu) */
.ux-context-menu {
    position: fixed;
    /* Doit etre au-dessus de tous les overlays applicatifs : agent flottant
       (panel 200040, FAB 200050), modales, loaders. Reste sous le canal
       mentions OS (999999) qui est reserve aux notifications systeme
       critiques. */
    z-index: 999998;
    background: var(--bg-card, rgba(22, 22, 34, 0.98));
    backdrop-filter: blur(12px);
    border: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    border-radius: 10px;
    padding: 0;
    min-width: 180px;
    box-shadow: var(--shadow-lg, 0 10px 40px rgba(0, 0, 0, 0.45));
    animation: uxCtxFadeIn 0.12s ease;
    overflow: hidden;
}

@keyframes uxCtxFadeIn {
    from { opacity: 0; transform: scale(0.96); }
    to { opacity: 1; transform: scale(1); }
}

.ux-context-menu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 14px;
    box-sizing: border-box;
    background: none;
    border: none;
    color: var(--text-primary, #f0f0f5);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    text-align: left;
}

.ux-context-menu-item:hover {
    background: rgba(255, 255, 255, 0.06);
}

.ux-context-menu-item svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.ux-context-menu-item.danger {
    color: #ef4444;
}

.ux-context-menu-item.danger:hover {
    background: rgba(239, 68, 68, 0.12);
    color: #ef4444;
}

.ux-context-menu-separator {
    display: block;
    height: 1px;
    margin: 0;
    padding: 0;
    border: none;
    background: rgba(255, 255, 255, 0.08);
    flex-shrink: 0;
}

/* Visualiseur micro (UX.micLevelWaveform) — canvas block, dimensions fixees par l’app */
.ux-mic-level-waveform {
    display: block;
    vertical-align: middle;
    max-width: 100%;
}

/* ============================================================================
   SUPPRESSION D'ELEMENTS DE LISTE (.nav-item-deletable)

   Pattern UX standard pour rendre n'importe quel item de liste de sidebar
   supprimable. Voir documentation : app UX, section "Suppression dans la
   sidebar". Utilisable avec n'importe quel contenu (.nav-item, ou un item
   personnalise comme .history-item dans l'app Images).

   Structure DOM attendue :
     .nav-item-deletable                  // wrapper, overflow:hidden
       .nav-item-deletable-slide          // contenu glissant (translateX)
         <ITEM>                           // .nav-item ou tout autre conteneur
         .nav-item-delete-zone            // zone rouge a droite (souris)
           .nav-item-trash-btn            // bouton corbeille
           .nav-item-confirm-text         // « Confirmer ? »
       .nav-item-swipe-bg                 // zone rouge derriere (tactile)

   Etats CSS :
     hover-revealed     -> Hover 0.5s sur l'actif : zone rouge 48px
     confirm-revealed   -> Clic corbeille : zone 140px + texte
     swiping            -> Touch drag en cours
     swiped             -> Swipe valide (>30px) : slide a -60px
   ============================================================================ */

.nav-item-deletable {
    position: relative;
    overflow: hidden;
    flex-shrink: 0;
}

.nav-item-deletable-slide {
    display: flex;
    align-items: center;
    position: relative;
    z-index: 1;
    background: var(--bg-secondary, transparent);
    will-change: transform;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Item interieur : on autorise n'importe quelle classe (pas seulement
   .nav-item) en visant le premier enfant du slide qui n'est pas la zone
   de suppression. Cela laisse les apps utiliser leur propre layout (ex:
   .history-item avec image + meta dans Images). */
.nav-item-deletable .nav-item-deletable-slide > :not(.nav-item-delete-zone) {
    flex: 1;
    min-width: 0;
}

.nav-item-deletable .nav-item {
    border-radius: 0;
}

.nav-item-deletable .nav-item span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
}

.nav-item-delete-zone {
    display: flex;
    align-items: center;
    justify-content: center;
    align-self: stretch;
    width: 0;
    min-width: 0;
    opacity: 0;
    overflow: hidden;
    background: rgba(239, 68, 68, 0.5);
    flex-shrink: 0;
    user-select: none;
    transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1),
                min-width 0.25s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.2s ease;
}

.nav-item-deletable.hover-revealed .nav-item-delete-zone {
    width: 48px;
    min-width: 48px;
    opacity: 1;
}

.nav-item-deletable.confirm-revealed .nav-item-delete-zone {
    width: 140px;
    min-width: 140px;
    opacity: 1;
    justify-content: flex-start;
}

.nav-item-trash-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    min-width: 48px;
    align-self: stretch;
    cursor: pointer;
    background: #ef4444;
}

.nav-item-trash-btn:active {
    background: #dc2626;
}

.nav-item-trash-btn svg {
    width: 18px;
    height: 18px;
    stroke: white;
    fill: none;
    stroke-width: 2;
    flex-shrink: 0;
}

.nav-item-confirm-text {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    flex: 1;
    max-width: 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    font-size: 11px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.85);
    cursor: default;
    letter-spacing: 0.02em;
    transition: max-width 0.25s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.2s ease 0.05s;
}

.nav-item-confirm-text svg {
    flex-shrink: 0;
    stroke: rgba(255, 255, 255, 0.6);
}

.nav-item-deletable.confirm-revealed .nav-item-confirm-text {
    max-width: 100px;
    opacity: 1;
}

.nav-item-swipe-bg {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #ef4444;
    z-index: 0;
    cursor: pointer;
    user-select: none;
    opacity: 0;
    transition: background 0.15s ease, opacity 0.15s ease;
}

.nav-item-deletable.swiping .nav-item-swipe-bg,
.nav-item-deletable.swiped .nav-item-swipe-bg {
    opacity: 1;
}

.nav-item-swipe-bg:active {
    background: #dc2626;
}

.nav-item-swipe-bg svg {
    width: 18px;
    height: 18px;
    stroke: white;
    fill: none;
    stroke-width: 2;
}

/* Fond actif rouge tres leger pendant suppression (souris ou tactile) */
.nav-item-deletable.swiped .nav-item-deletable-slide > :not(.nav-item-delete-zone),
.nav-item-deletable.swiping .nav-item-deletable-slide > :not(.nav-item-delete-zone),
.nav-item-deletable.confirm-revealed .nav-item-deletable-slide > :not(.nav-item-delete-zone) {
    background: rgba(239, 68, 68, 0.1);
}

.nav-item-deletable.swiped .nav-item-deletable-slide {
    transform: translateX(-60px);
}

/* ============================================================================
   ONGLETS DE PANNEAU (.sidebar-tabs-row + .sidebar-tab + .sidebar-tab-add-btn)

   Pattern UX standard pour la barre d'onglets en haut du panneau de gauche.
   Une SEULE ligne contenant :
     - N onglets (.sidebar-tab) qui se partagent la largeur restante
     - Un bouton "+" (.sidebar-tab-add-btn) optionnel, a droite, qui cree un
       nouvel item en fonction de l'onglet actif (l'app gere l'action via
       UX.sidebarTabs.attach({ onAdd })).

   Convention mio.land : ne PAS dupliquer le bouton "+ Nouveau X" sur une ligne
   separee sous les onglets. On integre le "+" dans la barre d'onglets pour
   garder une seule ligne et maximiser l'espace de la liste en dessous.

   Markup attendu :
     <div class="sidebar-tabs-row">
       <div class="sidebar-tabs">
         <button class="sidebar-tab active" data-tab="history"><span>Historique</span></button>
         <button class="sidebar-tab" data-tab="projects"><span>Projets</span></button>
       </div>
       <button class="sidebar-tab-add-btn" title="Nouvel element">
         <svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
       </button>
     </div>
     <div class="sidebar-tab-contents">
       <div class="sidebar-tab-content active" data-tab="history">...</div>
       <div class="sidebar-tab-content" data-tab="projects">...</div>
     </div>

   Voir : app UX, section "Onglets de panneau" (demo + API).
   ============================================================================ */

.sidebar-tabs-row {
    display: flex;
    align-items: stretch;
    gap: 6px;
    min-height: 40px;
    padding: 4px 8px 0;
    border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    flex-shrink: 0;
}

/* Variante : pas d'onglets, juste le bouton "+" - on l'aligne a droite
   pour rester coherent avec le pattern standard (onglets a gauche, "+" a droite). */
.sidebar-tabs-row-add-only {
    justify-content: flex-end;
}

.sidebar-tabs {
    display: flex;
    gap: 0;
    flex: 1;
    align-items: stretch;
    min-width: 0;
}

.sidebar-tab {
    flex: 1;
    padding: 0 8px;
    border: none;
    background: transparent;
    color: var(--text-secondary, rgba(255, 255, 255, 0.6));
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    user-select: none;
    border-bottom: 2px solid transparent;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 36px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Pas de transition : feedback :active instantane au pointerdown. */
}

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

.sidebar-tab:active {
    background: var(--accent, #8b5cf6) !important;
    color: #fff !important;
}

.sidebar-tab.active {
    color: var(--text-primary, #fff);
    border-bottom-color: var(--accent, #8b5cf6);
}

/* Compteur optionnel a droite du libelle (ex: "Historique 100"). Pattern
   utilise par Harmonie, Exercices, etc. Mis en sourdine au repos, pleine
   opacite quand l'onglet est actif. */
.sidebar-tab .tab-count {
    font-size: 10px;
    font-weight: 600;
    color: currentColor;
    opacity: 0.6;
    line-height: 1;
    margin-left: 4px;
}

.sidebar-tab.active .tab-count { opacity: 1; }

/* Bouton "+" a droite : compact, couleur accent, signale l'affordance de
   creation. L'app le wire via UX.sidebarTabs.attach({ onAdd }). */
.sidebar-tab-add-btn {
    flex-shrink: 0;
    align-self: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid rgba(74, 158, 255, 0.25);
    border-radius: 6px;
    background: linear-gradient(135deg, rgba(74, 158, 255, 0.10), rgba(74, 158, 255, 0.04));
    color: var(--accent, #4a9eff);
    cursor: pointer;
    user-select: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .15s, border-color .15s, transform .08s;
}

.sidebar-tab-add-btn:hover {
    background: linear-gradient(135deg, rgba(74, 158, 255, 0.18), rgba(74, 158, 255, 0.08));
    border-color: rgba(74, 158, 255, 0.45);
}

.sidebar-tab-add-btn:active {
    transform: scale(0.94);
}

.sidebar-tab-add-btn svg {
    width: 16px;
    height: 16px;
    stroke: currentColor;
    stroke-width: 2.2;
    fill: none;
    display: block;
}

/* Conteneurs de contenu d'onglet : panneaux superposes (position absolute)
   pour bascules instantanees. Toggle visibility plutot que display:none/block
   afin d'eviter un layout pass complet sur le panneau entrant. */
.sidebar-tab-contents {
    flex: 1;
    position: relative;
    min-height: 0;
    overflow: hidden;
}

.sidebar-tab-content {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    visibility: hidden;
    pointer-events: none;
    z-index: 0;
    contain: layout paint style;
}

.sidebar-tab-content.active {
    visibility: visible;
    pointer-events: auto;
    z-index: 1;
}

/* ============================================================================
   UX.tooltip  -  Infobulle Material Design (survol)

   Remplace les infobulles natives du navigateur (attribut title) par une
   bulle solide, rectangulaire, avec une largeur maximale qui force le retour
   a la ligne du texte (au lieu d'une longue ligne horizontale illisible).

   - Surface inverse (sombre sur theme clair, claire sur theme sombre) facon
     Material Design 3.
   - Elevation (ombre), coins arrondis, petite fleche orientee vers la cible.
   - Apparition/disparition animees (fade + scale + leger glissement).

   S'utilise partout via l'attribut title (auto-converti) ou data-ux-tooltip.
   ============================================================================ */
.ux-tooltip {
    position: fixed;
    top: 0;
    left: 0;
    /* Toujours au-dessus de tout (grille d'apps, fenetres, dialogues OS qui
       montent jusqu'a ~100000). Une infobulle est l'element transitoire le
       plus prioritaire visuellement. */
    z-index: 2147483600;
    max-width: 280px;
    box-sizing: border-box;
    padding: 8px 12px;
    border-radius: 8px;
    /* Verre givre : fond translucide + flou d'arriere-plan */
    background: rgba(30, 30, 42, 0.62);
    -webkit-backdrop-filter: blur(18px) saturate(160%);
    backdrop-filter: blur(18px) saturate(160%);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: #f4f4fb;
    font-family: var(--font-ui, 'Inter', -apple-system, BlinkMacSystemFont, sans-serif);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.45;
    letter-spacing: 0.1px;
    text-align: left;
    box-shadow:
        0 8px 24px rgba(0, 0, 0, 0.32),
        0 2px 6px rgba(0, 0, 0, 0.24),
        inset 0 1px 0 rgba(255, 255, 255, 0.08);
    pointer-events: none;
    opacity: 0;
    transform: translate(var(--ux-tip-tx, 0), var(--ux-tip-shift, 4px)) scale(0.94);
    transform-origin: var(--ux-tip-origin, center top);
    transition:
        opacity 0.14s cubic-bezier(0.4, 0, 0.2, 1),
        transform 0.16s cubic-bezier(0.34, 1.2, 0.64, 1);
    will-change: opacity, transform;
}

.ux-tooltip.visible {
    opacity: 1;
    transform: translate(var(--ux-tip-tx, 0), 0) scale(1);
}

.ux-tooltip-text {
    /* Forme rectangulaire : on autorise le retour a la ligne et on limite a
       quelques lignes pour rester compact (le titre complet reste dans title). */
    display: -webkit-box;
    -webkit-line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
    word-break: normal;
    white-space: normal;
}

/* Fleche : triangle plein pointant vers la cible (rendu net, pas de losange).
   Couleur calee sur la teinte du verre pour se fondre avec la bulle. */
.ux-tooltip-arrow {
    position: absolute;
    width: 0;
    height: 0;
    border: 7px solid transparent;
    pointer-events: none;
}

/* Bulle au-dessus de la cible -> fleche en bas, pointe vers le BAS */
.ux-tooltip[data-placement="top"] .ux-tooltip-arrow {
    bottom: -6px;
    border-bottom-width: 0;
    border-top-color: rgba(36, 36, 50, 0.86);
}

/* Bulle en dessous de la cible -> fleche en haut, pointe vers le HAUT */
.ux-tooltip[data-placement="bottom"] .ux-tooltip-arrow {
    top: -6px;
    border-top-width: 0;
    border-bottom-color: rgba(36, 36, 50, 0.86);
}

/* Repli si backdrop-filter non supporte : fond plus opaque pour rester lisible
   (la fleche est un triangle plein, inchangee par le repli). */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .ux-tooltip { background: rgba(30, 30, 42, 0.96); }
}

@media (prefers-reduced-motion: reduce) {
    .ux-tooltip {
        transition: opacity 0.1s linear;
        transform: none;
    }
    .ux-tooltip.visible {
        transform: none;
    }
}
