/* =============================================
   Backstage — Design System
   Aligné sur la charte anomalyproduction.fr
   Fond sombre, accent rouge, typo rock
   ============================================= */

/* Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Oswald:wght@400;500;600;700&display=swap');

/* -----------------------------------------------
   CSS Custom Properties (Design Tokens)
   ----------------------------------------------- */
:root {
    /* Background */
    --bg-primary: #0a0a0a;
    --bg-secondary: #141414;
    --bg-tertiary: #1e1e1e;
    --bg-card: #181818;
    --bg-hover: #252525;
    --bg-input: #1a1a1a;

    /* Accent (Rouge Anomaly) */
    --accent: #d81c1c;
    --accent-hover: #a10f0f;
    --accent-light: #e2453f;
    --accent-glow: rgba(216, 28, 28, 0.14);
    --accent-glow-strong: rgba(216, 28, 28, 0.3);

    /* Text */
    --text-primary: #f0f0f0;
    --text-secondary: #8a8a8a;
    --text-muted: #555;
    --text-accent: #d81c1c;

    /* Status — teintes distinctes de l'accent (jamais rouge, pour ne
       pas confondre une action destructive avec un bouton principal) */
    --success: #22c55e;
    --success-bg: rgba(34, 197, 94, 0.1);
    --danger: #e2733a;
    --danger-bg: rgba(226, 115, 58, 0.1);
    --warning: #f59e0b;
    --warning-bg: rgba(245, 158, 11, 0.1);
    --info: #3b82f6;
    --info-bg: rgba(59, 130, 246, 0.1);

    /* Borders */
    --border: #2a2a2a;
    --border-light: #333;
    --border-accent: rgba(216, 28, 28, 0.3);

    /* Typography */
    --font-heading: 'Oswald', sans-serif;
    --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

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

    /* Border Radius */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
    --radius-full: 50%;

    /* Shadows */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.6);
    --shadow-glow: 0 0 20px rgba(216, 28, 28, 0.15);

    /* Transitions */
    --transition-fast: 150ms ease;
    --transition-base: 250ms ease;
    --transition-slow: 400ms ease;

    /* Layout */
    --sidebar-width: 260px;
    --header-height: 64px;
}

/* -----------------------------------------------
   Reset & Base
   ----------------------------------------------- */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    max-width: 100%;
    overflow-x: hidden;
}

body {
    font-family: var(--font-body);
    background: var(--bg-primary);
    color: var(--text-primary);
    line-height: 1.6;
    min-height: 100vh;
    max-width: 100%;
    overflow-x: hidden;
}

a {
    color: var(--accent);
    text-decoration: none;
    transition: color var(--transition-fast);
}

a:hover {
    color: var(--accent-light);
}

img {
    max-width: 100%;
    height: auto;
}

/* -----------------------------------------------
   Typography
   ----------------------------------------------- */
h1,
h2,
h3,
h4,
h5,
h6 {
    font-family: var(--font-heading);
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    line-height: 1.2;
    color: var(--text-primary);
}

h1 {
    font-size: 2rem;
}

h2 {
    font-size: 1.5rem;
}

h3 {
    font-size: 1.2rem;
}

h4 {
    font-size: 1rem;
}

.page-title {
    font-size: 1.75rem;
    margin-bottom: var(--space-xl);
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.page-title .icon {
    font-size: 1.5rem;
}

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

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

.text-success {
    color: var(--success);
}

.text-danger {
    color: var(--danger);
}

/* -----------------------------------------------
   Layout — App Shell
   ----------------------------------------------- */
/* minmax(0, 1fr) et non 1fr : une piste `1fr` a pour minimum la taille
   min-content de son contenu, donc elle s'élargit au lieu de contraindre.
   C'est ce qui laissait l'en-tête pousser la mise en page à 400 px sur un
   écran de 375, et plus généralement ce qui permet à un tableau large de
   déborder la colonne principale. */
.app-layout {
    display: grid;
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    grid-template-rows: var(--header-height) 1fr;
    min-height: 100vh;
}

/* Header */
.app-header {
    grid-column: 1 / -1;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--space-xl);
    position: sticky;
    top: 0;
    z-index: 100;
}

/* Le bloc de gauche doit pouvoir rétrécir. Un élément flex a
   min-width:auto par défaut : sans cette remise à zéro, il refuse de
   descendre sous la largeur de son texte, qui part alors à la ligne. */
.app-header > .flex {
    min-width: 0;
}

.app-header__logo {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    min-width: 0;
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-primary);
}

.app-header__logo .logo-icon {
    font-size: 1.6rem;
}

/* Le nom de la structure peut être long (« Anomaly Production ») : sans
   nowrap il passait sur deux lignes dans un en-tête haut de 64 px, et
   débordait donc par-dessus le contenu de la page. C'est ce qui donnait
   l'impression que l'en-tête se chevauchait avec son propre texte. */
.app-header__logo span {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    background: linear-gradient(135deg, var(--accent), var(--accent-light));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.app-header__right {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    flex-shrink: 0;
}

.app-header__artist {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-xs) var(--space-md);
    background: var(--accent-glow);
    border: 1px solid var(--border-accent);
    border-radius: var(--radius-sm);
    color: var(--accent);
    font-size: 0.85rem;
    font-weight: 500;
}

/* Sélecteur de contexte (Groupe / Structure) — remplace le <select>
   natif par un vrai composant : déclencheur + menu déroulant stylé,
   groupé par type, avec la coche sur l'entrée active. */
.context-switcher {
    position: relative;
}

.context-switcher__trigger {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    height: 38px;
    padding: 0 var(--space-md);
    background: var(--accent-glow);
    border: 1px solid var(--border-accent);
    border-radius: var(--radius-sm);
    color: var(--accent);
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    max-width: 240px;
    transition: background var(--transition-fast);
}

.context-switcher__trigger:hover,
.context-switcher__trigger[aria-expanded="true"] {
    background: var(--accent-glow-strong);
}

.context-switcher__icon {
    flex-shrink: 0;
    font-size: 1rem;
}

.context-switcher__label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.context-switcher__chevron {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    transition: transform var(--transition-fast);
}

.context-switcher__trigger[aria-expanded="true"] .context-switcher__chevron {
    transform: rotate(180deg);
}

.context-switcher__menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 240px;
    max-width: min(320px, 90vw);
    max-height: 60vh;
    overflow-y: auto;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-sm);
    z-index: 200;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--transition-fast), transform var(--transition-fast), visibility var(--transition-fast);
}

.context-switcher__menu.open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.context-switcher__group+.context-switcher__group {
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--border);
}

.context-switcher__group-title {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    padding: var(--space-xs) var(--space-sm);
}

.context-switcher__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    width: 100%;
    min-height: 40px;
    padding: var(--space-xs) var(--space-sm);
    background: none;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.88rem;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition-fast);
}

.context-switcher__item:hover,
.context-switcher__item:focus-visible {
    background: var(--bg-hover);
    outline: none;
}

.context-switcher__item.active {
    color: var(--accent);
    background: var(--accent-glow);
    font-weight: 600;
}

.context-switcher__item .check {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--accent);
}

@media (max-width: 560px) {
    .context-switcher__label {
        display: none;
    }

    .context-switcher__trigger {
        padding: 0 var(--space-sm);
    }
}

.app-header__user {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.app-header__user .avatar {
    width: 34px;
    height: 34px;
    background: var(--accent);
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.85rem;
    color: #ffffff;
}

.btn-logout {
    background: none;
    border: none;
    color: var(--text-primary);
    cursor: pointer;
    padding: var(--space-xs);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: all var(--transition-fast);
}

.btn-logout:hover {
    color: var(--danger);
    transform: translateX(3px);
}

/* Bouton « Installer » de l'en-tête. Discret par nature : il ne se
   montre qu'une fois, sur les appareils où l'installation est possible
   et pas déjà faite (cf. initInstallApp dans app.js). */
.btn-install {
    background: none;
    border: 1px solid var(--border-accent, var(--border));
    border-radius: var(--radius-full);
    color: var(--text-primary);
    cursor: pointer;
    padding: 6px 12px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.82rem;
    font-weight: 600;
    white-space: nowrap;
    transition: all var(--transition-fast);
}

.btn-install:hover {
    color: var(--accent);
    border-color: var(--accent);
}

/* Sur petit écran, l'icône suffit : l'en-tête y est déjà à l'étroit. */
@media (max-width: 640px) {
    .btn-install__label {
        display: none;
    }
}

/* Sidebar */
.app-sidebar {
    background: var(--bg-secondary);
    border-right: 1px solid var(--border);
    padding: var(--space-lg) 0;
    overflow-y: auto;
}

.sidebar-section {
    margin-bottom: var(--space-lg);
}

.sidebar-section__title {
    font-family: var(--font-body);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
    padding: 0 var(--space-lg);
    margin-bottom: var(--space-sm);
}

.sidebar-nav {
    list-style: none;
}

.sidebar-nav__item {
    margin: 2px 0;
}

.sidebar-nav__link {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-sm) var(--space-lg);
    color: var(--text-secondary);
    font-size: 0.9rem;
    font-weight: 400;
    transition: all var(--transition-fast);
    border-left: 3px solid transparent;
}

.sidebar-nav__link:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-left-color: var(--border-light);
}

.sidebar-nav__link.active {
    color: var(--accent);
    background: var(--accent-glow);
    border-left-color: var(--accent);
    font-weight: 500;
}

.sidebar-nav__link .nav-icon {
    font-size: 1.1rem;
    width: 24px;
    text-align: center;
}

.sidebar-nav__link--sub {
    padding-left: calc(var(--space-lg) + 36px);
    font-size: 0.85rem;
}

/* Main Content */
.app-main {
    padding: var(--space-xl);
    overflow-y: auto;
    max-width: 1400px;
}

/* Sidebar Overlay */
.sidebar-overlay {
    display: none;
}

/* -----------------------------------------------
   Cards
   ----------------------------------------------- */
.card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-lg);
    transition: all var(--transition-base);
}

.card:hover {
    border-color: var(--border-light);
    box-shadow: var(--shadow-md);
}

.card--accent {
    border-color: var(--border-accent);
    background: linear-gradient(135deg, var(--bg-card), rgba(216, 28, 28, 0.03));
}

.card--accent:hover {
    box-shadow: var(--shadow-glow);
}

.card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-md);
}

.card__title {
    font-size: 0.8rem;
    font-family: var(--font-body);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-secondary);
    font-weight: 600;
}

.card__icon {
    font-size: 1.3rem;
    color: var(--accent);
}

.card__value {
    font-family: var(--font-heading);
    font-size: 2rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: var(--space-xs);
}

.card__subtitle {
    font-size: 0.8rem;
    color: var(--text-secondary);
}

/* Stat Cards Grid */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--space-lg);
    margin-bottom: var(--space-xl);
}

/* -----------------------------------------------
   Tables
   ----------------------------------------------- */
.table-wrapper {
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-card);
}

table {
    width: 100%;
    border-collapse: collapse;
}

thead th {
    background: var(--bg-tertiary);
    padding: var(--space-md) var(--space-lg);
    text-align: left;
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-secondary);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

tbody td {
    padding: var(--space-md) var(--space-lg);
    border-bottom: 1px solid var(--border);
    font-size: 0.9rem;
    vertical-align: middle;
}

tbody tr {
    transition: background var(--transition-fast);
}

tbody tr:hover {
    background: var(--bg-hover);
}

tbody tr:last-child td {
    border-bottom: none;
}

/* Cellule d'actions de table (icônes modifier/supprimer...) — sans
   cette règle, plusieurs boutons dans une même cellule s'empilaient
   sans espacement ni alignement cohérent.

   La cellule reste une `table-cell` : en `display:flex` elle sortait
   du modèle tabulaire et ne suivait plus la hauteur de sa ligne, si
   bien que sa bordure inférieure se décalait de quelques pixels dès
   qu'une ligne dépassait une hauteur de texte. C'est le contenu, pas
   la cellule, qui s'aligne. */
.table-actions {
    text-align: right;
    white-space: nowrap;
}

.table-actions > * {
    vertical-align: middle;
}

.table-actions > * + * {
    margin-left: var(--space-xs);
}

/* Les formulaires d'action (POST de suppression, de bascule...) ne
   doivent pas casser l'alignement horizontal des icônes. */
.table-actions form {
    display: inline-block;
    margin: 0;
}

/* Table totals row */
tfoot td {
    padding: var(--space-md) var(--space-lg);
    font-weight: 700;
    font-family: var(--font-heading);
    font-size: 1rem;
    background: var(--accent-glow);
    color: var(--accent);
    border-top: 2px solid var(--accent);
    vertical-align: middle;
}

.td-amount {
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 1rem;
    white-space: nowrap;
}

.td-amount--cash {
    color: var(--success);
}

.td-amount--card {
    color: var(--info);
}

.td-amount--total {
    color: var(--accent);
}

/* -----------------------------------------------
   Buttons
   ----------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    padding: 0 var(--space-lg);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: all var(--transition-fast);
    text-decoration: none;
    white-space: nowrap;
    height: 38px;
    box-sizing: border-box;
}

.btn:active {
    transform: scale(0.97);
}

.btn--primary {
    background: var(--accent);
    color: #ffffff;
    border-color: var(--accent);
}

.btn--primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #ffffff;
}

.btn--secondary {
    background: var(--bg-tertiary);
    color: var(--text-primary);
    border-color: var(--border);
}

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

.btn--danger {
    background: transparent;
    color: var(--danger);
    border-color: var(--danger);
}

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

.btn--ghost {
    background: transparent;
    color: var(--text-secondary);
    border-color: transparent;
}

.btn--ghost:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.btn--success {
    background: #27ae60;
    border-color: #27ae60;
    color: #ffffff;
}

.btn--success:hover {
    background: #219653;
    border-color: #219653;
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(39, 174, 96, 0.3);
}

.btn--info {
    background: #3498db;
    border-color: #3498db;
    color: #ffffff;
}

.btn--info:hover {
    background: #2980b9;
    border-color: #2980b9;
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
}

.btn--purple {
    background: #8e44ad;
    border-color: #8e44ad;
    color: #ffffff;
}

.btn--purple:hover {
    background: #732d91;
    border-color: #732d91;
    color: #ffffff;
    box-shadow: 0 4px 12px rgba(142, 68, 173, 0.3);
}

.btn--sm {
    padding: var(--space-xs) var(--space-md);
    font-size: 0.8rem;
}

.btn--lg {
    padding: var(--space-md) var(--space-xl);
    font-size: 1rem;
}

.btn-group {
    display: flex;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

/* Action secondaire discrète : un lien, pas un bouton. Sert aux actions
   qu'on ne veut surtout pas voir cliquées par réflexe (supprimer une
   connexion), là où un .btn plein attire trop l'œil. */
.btn-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--font-body);
    font-size: 0.82rem;
    color: var(--text-secondary);
    text-decoration: none;
    cursor: pointer;
    transition: color var(--transition-fast);
}

.btn-link:hover {
    color: var(--text-primary);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.btn-link--danger:hover {
    color: var(--danger);
}

/* Bouton icône carré (œil, copie). Discret au repos, cadré au survol. */
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all var(--transition-fast);
}

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

.icon-btn:active {
    transform: scale(0.92);
}

.icon-btn.is-on {
    color: var(--accent-light);
}

.icon-btn.is-ok {
    color: var(--success);
}

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

/* Barre de filtre : une rangée compacte plutôt qu'une carte pleine
   largeur presque vide. Les champs font la taille d'une date, pas la
   moitié de l'écran, et les raccourcis sont poussés à droite. */
.filter-bar {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
    padding: var(--space-md);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.filter-bar__form {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin: 0;
}

/* Libellé à gauche du champ : « Du » et « Au » n'ont pas besoin d'une
   ligne à eux au-dessus d'un sélecteur de date. */
.filter-bar__field {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    font-size: 0.8rem;
    color: var(--text-secondary);
}

.filter-bar__sep {
    color: var(--text-muted);
}

.form-input--date {
    width: auto;
    min-width: 150px;
    padding: var(--space-sm) var(--space-md);
    /* Sans ça, le sélecteur natif et son icône de calendrier s'affichent
       en thème clair : une pastille blanche au milieu d'un fond noir. */
    color-scheme: dark;
}

.filter-bar__presets {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
    margin-left: auto;
}

/* Explication d'un filtre ajusté par la page elle-même. Sur sa propre
   ligne (flex-basis 100%) : glissée à côté des pastilles, elle les
   ferait sauter à la ligne dès que la fenêtre se resserre. */
.filter-bar__note {
    flex-basis: 100%;
    margin: 0;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.filter-chip {
    padding: 5px 12px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg-input);
    font-size: 0.78rem;
    color: var(--text-secondary);
    text-decoration: none;
    white-space: nowrap;
    transition: all var(--transition-fast);
}

.filter-chip:hover {
    color: var(--text-primary);
    border-color: var(--border-light);
    background: var(--bg-hover);
}

.filter-chip.is-active {
    color: var(--accent-light);
    border-color: var(--border-accent);
    background: var(--accent-glow);
}

@media (max-width: 640px) {
    .filter-bar__presets {
        margin-left: 0;
        width: 100%;
    }

    .form-input--date {
        min-width: 0;
        flex: 1;
    }
}

/* Phrase d'introduction sous un titre de page. La largeur est bridée
   volontairement — au-delà d'environ 80 caractères, l'œil perd sa ligne
   en revenant à gauche. C'était jusqu'ici un max-width posé en style
   inline, page par page, avec une valeur différente à chaque fois. */
.page-intro {
    max-width: 80ch;
    margin: 0;
    font-size: 0.92rem;
    line-height: 1.65;
    color: var(--text-secondary);
}

/* Section à l'intérieur d'un formulaire : regroupe des champs de même
   nature sous un titre discret, pour qu'une carte longue se lise en
   blocs plutôt qu'en une file de champs indifférenciés. */
.form-section {
    padding-bottom: var(--space-lg);
    margin-bottom: var(--space-lg);
    border-bottom: 1px solid var(--border);
}

.form-section:last-of-type {
    padding-bottom: 0;
    margin-bottom: 0;
    border-bottom: 0;
}

.form-section__title {
    /* Peut porter une pastille d'état à côté du libellé. */
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin: 0;
    font-family: var(--font-heading);
    font-size: 0.9rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-primary);
}

.form-section__hint {
    margin: 2px 0 var(--space-md);
    font-size: 0.78rem;
    color: var(--text-secondary);
}

/* Liste de raccourcis (Com & Media) : chaque ligne est entièrement
   cliquable. Plus de bouton posé dans la ligne — c'est la ligne qui est
   le bouton, ce qui supprime la concurrence visuelle entre quatre
   boutons de poids différents empilés. */
.shortcut-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

.shortcut {
    display: flex;
    align-items: stretch;
    gap: var(--space-xs);
}

.shortcut__main {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex: 1;
    min-width: 0;
    padding: var(--space-sm) var(--space-md);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    text-decoration: none;
    transition: all var(--transition-fast);
}

.shortcut__main:hover {
    background: var(--bg-hover);
    border-color: var(--border-light);
    transform: translateX(2px);
}

.shortcut__icon {
    flex: 0 0 auto;
    font-size: 1.05rem;
    line-height: 1;
    filter: grayscale(0.25);
}

.shortcut__body {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.shortcut__label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-primary);
}

/* Le domaine de destination, tronqué : il informe sans jamais pousser
   la colonne latérale à s'élargir. */
.shortcut__hint {
    font-size: 0.75rem;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.shortcut__arrow {
    margin-left: auto;
    padding-left: var(--space-sm);
    font-size: 0.9rem;
    color: var(--text-muted);
    transition: color var(--transition-fast);
}

.shortcut__main:hover .shortcut__arrow {
    color: var(--text-primary);
}

/* Le raccourci principal (billetterie) se distingue par un filet
   d'accent, pas par un aplat rouge : la hiérarchie reste lisible sans
   qu'un seul bouton aspire tout le regard. */
.shortcut__main.is-primary {
    border-left: 2px solid var(--accent);
    background: var(--accent-glow);
}

.shortcut__main.is-primary:hover {
    background: var(--accent-glow-strong);
}

.shortcut__main.is-primary .shortcut__arrow {
    color: var(--accent-light);
}

/* Lien manquant : la ligne reste cliquable et mène au champ à remplir. */
.shortcut__main.is-empty {
    background: transparent;
    border: 1px dashed var(--border-light);
}

.shortcut__main.is-empty .shortcut__label,
.shortcut__main.is-empty .shortcut__icon {
    color: var(--text-secondary);
    opacity: 0.65;
}

.shortcut__main.is-empty:hover {
    border-color: var(--accent);
    border-style: dashed;
    background: transparent;
}

.shortcut__main.is-empty:hover .shortcut__arrow {
    color: var(--accent-light);
}

.shortcut__copy {
    align-self: center;
}

/* Interrupteur compact pour un réglage binaire qui est un état, pas une
   action : il tient dans un en-tête de carte, à côté d'un badge. */
.switch {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    cursor: pointer;
    user-select: none;
}

.switch__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.switch__track {
    position: relative;
    display: block;
    flex: 0 0 auto;
    width: 36px;
    height: 20px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-light);
    border-radius: 999px;
    transition: all var(--transition-fast);
}

.switch__knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    background: var(--text-secondary);
    border-radius: 50%;
    transition: all var(--transition-fast);
}

.switch__label {
    font-size: 0.8rem;
    color: var(--text-secondary);
    transition: color var(--transition-fast);
}

.switch__input:checked + .switch__track {
    background: var(--success-bg);
    border-color: var(--success);
}

.switch__input:checked + .switch__track .switch__knob {
    left: 18px;
    background: var(--success);
}

.switch__input:checked ~ .switch__label {
    color: var(--success);
}

.switch__input:focus-visible + .switch__track {
    box-shadow: 0 0 0 3px var(--accent-glow);
}

.switch:hover .switch__track {
    border-color: var(--text-secondary);
}

/* Barre d'actions en pied de carte : actions secondaires à gauche,
   action principale calée à droite. */
.card__actions {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
    margin-top: var(--space-lg);
    padding-top: var(--space-md);
    border-top: 1px solid var(--border);
}

.card__actions-end {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-left: auto;
}

@media (max-width: 640px) {
    .card__actions-end {
        margin-left: 0;
        width: 100%;
    }

    .card__actions-end .btn,
    .card__actions-end form {
        flex: 1;
    }

    .card__actions-end form .btn {
        width: 100%;
    }
}

/* -----------------------------------------------
   Forms
   ----------------------------------------------- */
.form-group {
    margin-bottom: var(--space-lg);
}

.form-label {
    display: block;
    font-size: 0.8rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary);
    margin-bottom: var(--space-sm);
}

.form-input,
.form-select,
.form-textarea {
    width: 100%;
    padding: var(--space-md);
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 16px;
    transition: all var(--transition-fast);
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-glow);
}

.form-input::placeholder {
    color: var(--text-muted);
}

/* -----------------------------------------------
   Champs de fichier

   Le contrôle natif garde son bouton système — gris clair, police de
   l'OS, coins carrés — au milieu d'une interface sombre, et le libellé
   « Aucun fichier choisi » sort en noir sur noir selon le navigateur.
   On ne peut pas remplacer le bouton, mais ::file-selector-button se
   style entièrement.

   Le même habillage existait déjà, mais seulement sous .doc-upload__input
   (documents d'inventaire) : tout champ fichier ajouté ailleurs repartait
   du rendu système. La règle est donc posée sur le sélecteur d'élément ;
   .doc-upload__input n'en garde que ses écarts de taille.
   ----------------------------------------------- */
input[type="file"] {
    padding: var(--space-sm) var(--space-md);
    color: var(--text-secondary);
    font-size: 0.85rem;
    line-height: 1.6;
    cursor: pointer;
}

input[type="file"]::file-selector-button {
    margin-right: var(--space-md);
    padding: 6px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-tertiary);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--transition-fast);
}

input[type="file"]::file-selector-button:hover {
    border-color: var(--accent);
    background: var(--bg-hover);
    color: var(--accent-light);
}

/* Préfixe -webkit- : Safari, y compris sur iPhone, ne reconnaît pas
   encore la forme standard. */
input[type="file"]::-webkit-file-upload-button {
    margin-right: var(--space-md);
    padding: 6px 14px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-tertiary);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

/* -----------------------------------------------
   Champs de date et d'heure

   Le sélecteur natif s'affiche en thème clair par défaut : une pastille
   blanche au milieu d'un fond noir, avec une icône de calendrier presque
   invisible. `color-scheme` bascule tout le widget — popup du calendrier
   comprise — en sombre. La règle était posée sur .form-input--date,
   c'est-à-dire les seules barres de filtre ; tous les autres champs de
   date de l'application, à commencer par celui de la création d'une
   date, y échappaient.
   ----------------------------------------------- */
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"] {
    color-scheme: dark;
}

/* L'icône native est minuscule et sans contraste. On l'agrandit, on la
   met à la couleur d'accent au survol, et surtout on garde le curseur
   « main » sur tout le champ : le clic ouvre le calendrier où qu'il
   tombe (cf. openDatePicker dans app.js). */
input[type="date"],
input[type="time"],
input[type="datetime-local"] {
    cursor: pointer;
}

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    width: 18px;
    height: 18px;
    padding: 2px;
    border-radius: var(--radius-sm);
    opacity: 0.55;
    cursor: pointer;
    transition: opacity var(--transition-fast), background var(--transition-fast);
}

input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator {
    opacity: 1;
    background: var(--accent-glow);
}

/* Firefox n'expose pas l'indicateur, mais laisse styler les segments. */
input[type="date"]::-webkit-datetime-edit-fields-wrapper {
    padding: 0;
}

input[type="date"]:focus::-webkit-datetime-edit-day-field,
input[type="date"]:focus::-webkit-datetime-edit-month-field,
input[type="date"]:focus::-webkit-datetime-edit-year-field {
    background: var(--accent-glow);
    border-radius: 3px;
}

.form-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%238a8a8a' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    padding-right: 36px;
}

.form-textarea {
    min-height: 100px;
    resize: vertical;
}

/* Champ masqué avec son œil : le bouton se pose dans le champ, la
   réserve de padding l'empêche de recouvrir la saisie. */
.input-reveal {
    position: relative;
}

.input-reveal .form-input {
    padding-right: 44px;
}

.input-reveal__btn {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
}

.input-reveal__btn:active {
    transform: translateY(-50%) scale(0.92);
}

/* Ligne « clé enregistrée » : aperçu masqué, œil, copie, retour d'état. */
.secret-stored {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
    margin-top: var(--space-sm);
    font-size: 0.8rem;
    color: var(--text-secondary);
}

.secret-stored__value {
    padding: 2px 8px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    color: var(--text-secondary);
    word-break: break-all;
}

.secret-stored__value.is-revealed {
    color: var(--text-primary);
    border-color: var(--border-accent);
    background: var(--accent-glow);
    user-select: all;
}

.secret-stored__tools {
    display: inline-flex;
    align-items: center;
    gap: var(--space-xs);
}

.secret-stored__feedback {
    font-size: 0.75rem;
    color: var(--success);
}

.secret-stored__feedback.is-error {
    color: var(--warning);
}

.form-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-lg);
}

.form-inline {
    display: flex;
    align-items: end;
    gap: var(--space-md);
    flex-wrap: wrap;
}

.form-inline .form-group {
    margin-bottom: 0;
    flex: 1;
    min-width: 150px;
}

/* -----------------------------------------------
   Flash Messages (Notifications)
   ----------------------------------------------- */
.flash {
    padding: var(--space-md) var(--space-lg);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-lg);
    display: flex;
    align-items: center;
    gap: var(--space-md);
    font-size: 0.9rem;
    animation: flashSlideIn 0.3s ease;
}

@keyframes flashSlideIn {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.flash--success {
    background: var(--success-bg);
    border: 1px solid var(--success);
    color: var(--success);
}

.flash--error {
    background: var(--danger-bg);
    border: 1px solid var(--danger);
    color: var(--danger);
}

/* Information à traiter, ni succès ni erreur — ex. les comptes en
   attente d'accès sur Administration → Utilisateurs. */
.flash--warning {
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.45);
    color: #f59e0b;
}

.flash__close {
    margin-left: auto;
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    font-size: 1.2rem;
    opacity: 0.7;
    transition: opacity var(--transition-fast);
}

.flash__close:hover {
    opacity: 1;
}

/* -----------------------------------------------
   Badges / Tags
   ----------------------------------------------- */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    padding: 2px 10px;
    border-radius: 20px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.badge--cash {
    background: var(--success-bg);
    color: var(--success);
    border: 1px solid rgba(34, 197, 94, 0.3);
}

.badge--card {
    background: var(--info-bg);
    color: var(--info);
    border: 1px solid rgba(59, 130, 246, 0.3);
}

.badge--other {
    background: var(--warning-bg);
    color: var(--warning);
    border: 1px solid rgba(245, 158, 11, 0.3);
}

.badge--active {
    background: var(--success-bg);
    color: var(--success);
}

.badge--inactive {
    background: var(--danger-bg);
    color: var(--danger);
}

.badge--upcoming {
    background: var(--accent-glow);
    color: var(--accent);
    border: 1px solid var(--border-accent);
}

.badge--past {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
}

/* Statuts génériques (event/venue status, journal d'activité) —
   utilisent les mêmes tokens sémantiques que le reste de l'appli. */
.badge--success {
    background: var(--success-bg);
    color: var(--success);
}

.badge--warning {
    background: var(--warning-bg);
    color: var(--warning);
}

.badge--danger {
    background: var(--danger-bg);
    color: var(--danger);
}

.badge--info {
    background: var(--info-bg);
    color: var(--info);
}

.badge--accent {
    background: var(--accent-glow);
    color: var(--accent);
    border: 1px solid var(--border-accent);
}

.badge--primary {
    background: rgba(142, 68, 173, 0.1);
    color: #8e44ad;
}

.badge--secondary {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
}

/* -----------------------------------------------
   Empty State
   ----------------------------------------------- */
.empty-state {
    text-align: center;
    padding: var(--space-2xl);
    color: var(--text-muted);
}

.empty-state__icon {
    font-size: 3rem;
    margin-bottom: var(--space-md);
    opacity: 0.5;
}

.empty-state__text {
    font-size: 1rem;
    margin-bottom: var(--space-lg);
}

/* -----------------------------------------------
   Login Page
   ----------------------------------------------- */
.login-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-primary);
    background-image:
        radial-gradient(ellipse at 20% 50%, rgba(216, 28, 28, 0.08) 0%, transparent 50%),
        radial-gradient(ellipse at 80% 20%, rgba(216, 28, 28, 0.05) 0%, transparent 40%);
}

.login-card {
    width: 100%;
    max-width: 420px;
    padding: var(--space-2xl);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.login-card__logo {
    text-align: center;
    margin-bottom: var(--space-xl);
}

.login-card__logo h1 {
    font-family: var(--font-heading);
    font-size: 2.2rem;
    background: linear-gradient(135deg, var(--accent), var(--accent-light));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    margin-bottom: var(--space-xs);
}

.login-card__logo p {
    color: var(--text-secondary);
    font-size: 0.85rem;
}

.login-card .btn--primary,
.login-card .btn--secondary {
    width: 100%;
    justify-content: center;
    padding: var(--space-md);
    font-size: 0.95rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Séparateur « ou » entre la connexion classique et Google */
.login-divider {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    margin: var(--space-lg) 0;
    color: var(--text-secondary);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.login-divider::before,
.login-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

/* Bouton Google : fond clair et libellé sombre, conformément aux
   consignes de marque de Google — le seul élément de l'interface qui
   échappe volontairement au thème sombre du reste de l'application. */
.btn--google {
    width: 100%;
    background: #ffffff;
    color: #1f1f1f;
    border-color: #dadce0;
    font-weight: 500;
}

.btn--google:hover {
    background: #f5f6f7;
    border-color: #c6cacd;
    color: #1f1f1f;
}

.btn--google svg {
    flex-shrink: 0;
}

.login-hint {
    margin-top: var(--space-md);
    font-size: 0.78rem;
    text-align: center;
    line-height: 1.5;
}

/* -----------------------------------------------
   Modal / Dialog
   ----------------------------------------------- */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    visibility: hidden;
    transition: all var(--transition-base);
}

.modal-overlay.active {
    opacity: 1;
    visibility: visible;
}

.modal {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-xl);
    max-width: 500px;
    width: 90%;
    transform: scale(0.95) translateY(10px);
    transition: transform var(--transition-base);
    box-shadow: var(--shadow-lg);
}

.modal-overlay.active .modal {
    transform: scale(1) translateY(0);
}

.modal__title {
    font-size: 1.2rem;
    margin-bottom: var(--space-md);
}

.modal__body {
    color: var(--text-secondary);
    margin-bottom: var(--space-lg);
}

.modal__actions {
    display: flex;
    gap: var(--space-md);
    justify-content: flex-end;
}

/* -----------------------------------------------
   Page header with actions
   ----------------------------------------------- */
.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-xl);
    flex-wrap: wrap;
    gap: var(--space-md);
}

.page-header__title {
    font-size: 1.75rem;
    display: flex;
    align-items: center;
    gap: var(--space-md);
    margin: 0;
}

.page-header__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.page-header__actions form,
.page-header__actions .stock-action-form {
    display: inline-flex;
    align-items: center;
    margin: 0;
}

/* -----------------------------------------------
   Section divider
   ----------------------------------------------- */
.section {
    margin-bottom: var(--space-xl);
}

.section__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-lg);
}

.section__title {
    font-size: 1.1rem;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

/* -----------------------------------------------
   Toast Notifications
   ----------------------------------------------- */
.toast-container {
    position: fixed;
    bottom: var(--space-xl);
    right: var(--space-xl);
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.toast {
    padding: var(--space-md) var(--space-lg);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    font-size: 0.85rem;
    animation: toastIn 0.3s ease;
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

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

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

@keyframes toastIn {
    from {
        opacity: 0;
        transform: translateX(20px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* -----------------------------------------------
   Utility classes
   ----------------------------------------------- */
.flex {
    display: flex;
}

.flex-center {
    display: flex;
    align-items: center;
    justify-content: center;
}

.flex-between {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.gap-sm {
    gap: var(--space-sm);
}

.gap-md {
    gap: var(--space-md);
}

.gap-lg {
    gap: var(--space-lg);
}

.mt-sm {
    margin-top: var(--space-sm);
}

.mt-md {
    margin-top: var(--space-md);
}

.mt-lg {
    margin-top: var(--space-lg);
}

.mb-sm {
    margin-bottom: var(--space-sm);
}

.mb-md {
    margin-bottom: var(--space-md);
}

.mb-lg {
    margin-bottom: var(--space-lg);
}

/* .mb-xl / .mt-xl étaient utilisés dans les templates (cartes des pages
   événement, salle, activités) sans jamais avoir été déclarés : les
   blocs se retrouvaient collés les uns aux autres. */
.mb-xl {
    margin-bottom: var(--space-xl);
}

.mt-xl {
    margin-top: var(--space-xl);
}

.text-right {
    text-align: right;
}

.text-center {
    text-align: center;
}

.w-full {
    width: 100%;
}

/* !important nécessaire : en mode "cartes" (< 768px), la règle
   `.table-responsive-cards tr { display: block }` est plus spécifique
   et rouvrait toutes les lignes masquées (formulaires d'édition d'un
   cachet, etc.) dès qu'on réduisait la fenêtre. */
.hidden {
    display: none !important;
}

/* Cache visuellement un élément sans le retirer de l'arbre
   d'accessibilité ni de l'ordre de tabulation (contrairement à
   display:none) — utilisé pour les inputs radio/checkbox habillés en
   boutons (ex: sélecteur de mode de paiement). */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.payment-btn-group label.btn {
    position: relative;
}

.payment-btn-group label.btn:focus-within {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* -----------------------------------------------
   Responsive & Touch Design System (Tablet & Mobile)
   ----------------------------------------------- */
.mobile-toggle {
    display: none;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 1.5rem;
    cursor: pointer;
    padding: var(--space-xs);
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    transition: background var(--transition-fast);
}

.mobile-toggle:hover,
.mobile-toggle:focus {
    background: var(--bg-hover);
}

@media (max-width: 1024px) {
    .app-layout {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: var(--header-height) 1fr;
    }

    .app-sidebar {
        position: fixed;
        left: -100%;
        top: var(--header-height);
        bottom: 0;
        width: var(--sidebar-width);
        z-index: 95;
        transition: left var(--transition-base);
        box-shadow: var(--shadow-lg);
    }

    .app-sidebar.open {
        left: 0;
    }

    .sidebar-overlay {
        display: none;
        position: fixed;
        inset: 0;
        top: var(--header-height);
        background: rgba(0, 0, 0, 0.6);
        backdrop-filter: blur(3px);
        z-index: 90;
    }

    .sidebar-overlay.open {
        display: block;
    }

    .mobile-toggle {
        display: inline-flex;
    }

    .app-main {
        padding: var(--space-lg);
    }

    .stats-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: var(--space-md);
    }

    .form-row {
        grid-template-columns: 1fr;
    }

    .page-header {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-md);
    }

    .page-header__actions {
        width: 100%;
        display: flex;
        flex-wrap: wrap;
        gap: var(--space-sm);
    }

    .page-header__actions .btn,
    .page-header__actions .stock-action-form {
        flex: 1 1 auto;
        min-width: 140px;
    }

    .page-header__actions .btn {
        width: 100%;
        justify-content: center;
        white-space: normal;
        text-align: center;
    }

    .app-header {
        padding: 0 var(--space-lg);
    }
}

@media (max-width: 768px) {
    .app-header {
        padding: 0 var(--space-md);
    }

    .app-header__artist {
        display: none;
    }

    .app-main {
        padding: var(--space-md);
    }

    .page-title {
        font-size: 1.4rem;
    }

    .page-header__title {
        font-size: 1.4rem;
    }

    .btn {
        min-height: 42px;
    }

    .page-header__actions {
        flex-direction: column;
    }

    .page-header__actions .btn,
    .page-header__actions .stock-action-form {
        width: 100% !important;
        min-width: 0 !important;
    }

    .hide-mobile {
        display: none !important;
    }
}

/* En-tête sur petit écran.

   Aucune règle ne l'adaptait : il gardait sa mise en page de bureau —
   logo à 1.4rem, sélecteur de contexte jusqu'à 240 px, nom de
   l'utilisateur — sur un écran de 375 px. Résultat, le bloc de droite
   dépassait du viewport et le nom de la structure passait à la ligne,
   par-dessus le contenu. */
@media (max-width: 640px) {
    .app-header {
        gap: var(--space-sm);
        padding: 0 var(--space-md);
    }

    /* Taille calée sur « Anomaly Production » — le nom réellement
       affiché — pour qu'il tienne en entier à 375 px. Un nom plus long
       se coupe proprement en points de suspension. */
    .app-header__logo {
        gap: var(--space-sm);
        font-size: 0.88rem;
        letter-spacing: 0.02em;
    }

    .app-header > .flex {
        gap: var(--space-sm);
    }

    .app-header__right {
        gap: var(--space-sm);
    }

    /* Le nom du contexte est déjà affiché par le logo, juste à gauche :
       le répéter dans le sélecteur mangeait la place des deux. Il reste
       lisible dans le menu déroulant, une fois ouvert. */
    .context-switcher__label {
        display: none;
    }

    .context-switcher__trigger {
        padding: 0 var(--space-sm);
    }
}

@media (max-width: 480px) {
    .stats-grid {
        grid-template-columns: 1fr;
    }

    .app-header__user span:not(.avatar) {
        display: none;
    }

    .btn-group {
        flex-direction: column;
        width: 100%;
    }

    .btn-group .btn {
        width: 100%;
        justify-content: center;
    }

    .page-header__title {
        font-size: 1.25rem;
    }
}

/* -----------------------------------------------
   Animations
   ----------------------------------------------- */
@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.animate-fade-in {
    animation: fadeIn 0.4s ease;
}

.animate-slide-up {
    animation: slideUp 0.4s ease;
}

/* Staggered card animations */
/* Toutes les tuiles s'animent, pas seulement les quatre premières : au
   delà, la cascade est plafonnée — un décalage qui continue de croître
   se lit comme une attente, plus comme une animation. */
.stats-grid>.card {
    animation: slideUp 0.4s ease both;
}

.stats-grid>.card:nth-child(1) {
    animation-delay: 0s;
}

.stats-grid>.card:nth-child(2) {
    animation-delay: 0.1s;
}

.stats-grid>.card:nth-child(3) {
    animation-delay: 0.2s;
}

.stats-grid>.card:nth-child(n+4) {
    animation-delay: 0.3s;
}

/* -----------------------------------------------
   Scrollbar
   ----------------------------------------------- */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: var(--bg-primary);
}

::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--text-muted);
}

/* -----------------------------------------------
   Print styles
   ----------------------------------------------- */
@media print {

    .app-sidebar,
    .app-header,
    .btn,
    .mobile-toggle,
    .no-print {
        display: none !important;
    }

    .app-layout {
        grid-template-columns: 1fr;
        grid-template-rows: 1fr;
    }

    .app-main {
        padding: 0;
    }

    body {
        background: white;
        color: black;
    }

    .card {
        border-color: #ddd;
        break-inside: avoid;
    }
}

/* =============================================
   Backstage Improvements — Custom Extensions
   ============================================= */

/* 1. Tabs Layout */
/* La barre d'onglets défile horizontalement quand elle ne tient pas.
   La scrollbar est masquée (elle est disgracieuse et absente sur
   mobile) : ce sont les dégradés sur les bords qui signalent qu'il
   reste des onglets, sinon le défilement est totalement muet — on ne
   soupçonne même pas qu'il y a d'autres onglets à droite. */
.tabs-wrapper {
    position: relative;
    margin-bottom: var(--space-lg);
}

.tabs-wrapper::before,
.tabs-wrapper::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 36px;
    pointer-events: none;
    /* Pas de transition : le dégradé doit suivre le défilement au doigt
       sans latence, et une opacité animée depuis 0 peut rester bloquée
       à son état de départ quand la classe est posée avant le premier
       rendu. */
    display: none;
    z-index: 1;
}

.tabs-wrapper::before {
    left: 0;
    background: linear-gradient(to right, var(--bg-primary) 15%, rgba(10, 10, 10, 0));
}

.tabs-wrapper::after {
    right: 0;
    background: linear-gradient(to left, var(--bg-primary) 15%, rgba(10, 10, 10, 0));
}

/* Règles séparées volontairement : grouper ::before et ::after dans une
   même liste de sélecteurs se résout mal selon les moteurs. */
.tabs-wrapper.can-scroll-start::before {
    display: block;
}

.tabs-wrapper.can-scroll-end::after {
    display: block;
}

.tabs {
    display: flex;
    border-bottom: 2px solid var(--border);
    gap: var(--space-xs);
    overflow-x: auto;
    scroll-behavior: smooth;
    -ms-overflow-style: none;
    /* IE and Edge */
    scrollbar-width: none;
    /* Firefox */
}

.tabs::-webkit-scrollbar {
    display: none;
    /* Chrome, Safari and Opera */
}

/* Repère de position sous la barre d'onglets : une vraie mini-scrollbar,
   rendue visible parce que celle du navigateur est masquée. La longueur
   du curseur dit la part visible, sa position dit où l'on en est — plus
   direct que des points, et sans phrase à lire.
   Affiché uniquement quand ça déborde (classe posée par le JS). */
.tabs-wrapper.is-overflowing .tabs-hint {
    display: block;
}

.tabs-hint {
    display: none;
    position: relative;
    height: 3px;
    margin-top: 8px;
    border-radius: 999px;
    background: var(--border-light);
    overflow: hidden;
}

.tabs-hint__thumb {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 30%; /* recalculé par le JS */
    border-radius: 999px;
    /* Gris et non rouge : juste au-dessus se trouve le soulignement de
       l'onglet actif, lui aussi rouge. Deux barres de la même couleur
       collées l'une à l'autre se lisent mal. */
    background: #6a6a6a;
    transition: transform var(--transition-fast);
    will-change: transform;
}

.tab-btn {
    background: none;
    border: none;
    color: var(--text-secondary);
    padding: var(--space-sm) var(--space-lg);
    font-family: var(--font-heading);
    font-size: 0.95rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    cursor: pointer;
    transition: all var(--transition-fast);
    border-bottom: 3px solid transparent;
    margin-bottom: -2px;
    white-space: nowrap;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 768px) {
    .tab-btn {
        /* Cible tactile d'au moins 44px de haut : les onglets étaient
           serrés au point d'être difficiles à viser au pouce. */
        padding: 11px var(--space-md);
        font-size: 0.85rem;
        min-height: 44px;
    }
}

.tab-btn:hover {
    color: var(--text-primary);
    border-bottom-color: var(--border-light);
}

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

.tab-content {
    animation: fadeIn var(--transition-base);
}

/* 2. Convertible Currency Hover/Indications */
.convertible-currency {
    position: relative;
    transition: all var(--transition-fast);
    border-bottom: 1px dotted var(--border-accent);
    display: inline-block;
    padding-bottom: 1px;
    white-space: nowrap;
}

td.convertible-currency,
th.convertible-currency {
    display: table-cell;
}

.convertible-currency:hover {
    color: var(--accent-light) !important;
    background-color: rgba(216, 28, 28, 0.06);
    border-bottom-style: solid;
    border-bottom-color: var(--accent-light);
    border-radius: var(--radius-sm);
}

.currency-equivalent {
    display: block;
    font-size: 0.65em;
    color: var(--text-secondary);
    font-weight: normal;
    margin-top: 2px;
}

/* Justificatif rattaché à une ligne de budget : le lien et sa croix de
   suppression tiennent sur la même ligne, au même corps que les autres
   métadonnées de la ligne (cf. .currency-equivalent). */
.budget-doc {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 2px;
    font-size: 0.65em;
    font-weight: normal;
}

.budget-doc .doc-link {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.budget-doc__remove {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    padding: 0;
    border: none;
    border-radius: 3px;
    background: none;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.budget-doc__remove:hover {
    background: var(--danger-bg);
    color: var(--danger);
}

.convertible-currency.converted {
    border-bottom-color: var(--success);
}

/* 3. Spinner Loader */
@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

.spinner {
    display: inline-block;
    width: 24px;
    height: 24px;
    border: 3px solid rgba(216, 28, 28, 0.15);
    border-radius: 50%;
    border-top-color: var(--accent);
    animation: spin 0.8s linear infinite;
    vertical-align: middle;
}

/* 4. Responsive Adaptations */
@media (max-width: 768px) {
    .table-wrapper {
        position: relative;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .table-wrapper:not(.table-responsive-cards) table {
        min-width: 600px;
    }

    .form-inline {
        flex-direction: column;
        align-items: stretch !important;
        gap: var(--space-md);
    }

    .form-inline .form-group {
        width: 100%;
    }

    .form-inline button {
        width: 100%;
        justify-content: center;
        height: 48px !important;
    }
}

/* 4b. Responsive Card Tables (< 768px) */
@media (max-width: 768px) {

    .table-responsive-cards table,
    .table-responsive-cards thead,
    .table-responsive-cards tbody,
    .table-responsive-cards th,
    .table-responsive-cards td,
    .table-responsive-cards tr {
        display: block;
        width: 100%;
    }

    .table-responsive-cards {
        background: transparent;
        border: none;
    }

    .table-responsive-cards table {
        min-width: 0 !important;
        border: none;
    }

    .table-responsive-cards thead,
    .table-responsive-cards tfoot {
        display: none;
    }

    .table-responsive-cards tr {
        background: var(--bg-card);
        border: 1px solid var(--border);
        border-radius: var(--radius-md);
        margin-bottom: var(--space-md);
        padding: var(--space-md);
        box-shadow: var(--shadow-sm);
    }

    .table-responsive-cards tr:hover {
        background: var(--bg-hover);
        border-color: var(--border-light);
    }

    .table-responsive-cards td {
        border: none;
        border-bottom: 1px dashed var(--border-light);
        padding: var(--space-xs) 0;
        display: flex;
        align-items: center;
        justify-content: space-between;
        text-align: right;
        font-size: 0.9rem;
        min-height: 38px;
    }

    .table-responsive-cards td:last-child {
        border-bottom: none;
        padding-bottom: 0;
        justify-content: flex-end;
    }

    .table-responsive-cards td::before {
        content: attr(data-label);
        font-weight: 600;
        font-size: 0.75rem;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--text-secondary);
        text-align: left;
        margin-right: var(--space-md);
        flex-shrink: 0;
    }

    .table-responsive-cards td:empty::before {
        display: none;
    }

    .table-responsive-cards td.table-actions {
        margin-top: var(--space-xs);
        padding-top: var(--space-sm);
        border-top: 1px solid var(--border);
        border-bottom: none;
        justify-content: flex-end;
        gap: var(--space-sm);
    }
}

/* Sticky First Column for Matrix Tables */
.table-sticky-col {
    overflow-x: auto;
    position: relative;
}

.table-sticky-col th:first-child,
.table-sticky-col td:first-child {
    position: sticky;
    left: 0;
    z-index: 5;
    background: var(--bg-card);
    border-right: 2px solid var(--border);
}

.table-sticky-col thead th:first-child {
    z-index: 6;
    background: var(--bg-tertiary);
}

/* 5. Event View Custom Responsive Actions & Back Link */
.btn-back {
    display: inline-flex;
    align-items: center;
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-weight: 500;
    margin-bottom: var(--space-md);
    transition: color var(--transition-fast), transform var(--transition-fast);
}

.btn-back:hover {
    color: var(--accent);
    transform: translateX(-3px);
}

.event-actions {
    display: flex;
    gap: var(--space-sm);
    align-items: center;
    flex-wrap: wrap;
}

.event-actions-secondary {
    display: flex;
    gap: var(--space-sm);
}

@media (max-width: 768px) {
    .page-header--event {
        flex-direction: column;
        align-items: stretch !important;
        gap: var(--space-md);
    }

    .event-actions {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
        gap: var(--space-sm);
    }

    .event-action-main {
        width: 100%;
        justify-content: center;
    }

    .event-actions-secondary {
        display: flex;
        width: 100%;
        gap: var(--space-sm);
    }

    .event-actions-secondary .btn,
    .event-actions-secondary .btn--secondary,
    .event-actions-secondary .btn--danger {
        flex: 1;
        justify-content: center;
    }
}

/* 6. Refunded Sales Strikethrough style */
.sale-row--refunded {
    text-decoration: line-through;
    opacity: 0.55;
    color: var(--text-secondary);
    background-color: rgba(217, 83, 79, 0.03);
}

.sale-row--refunded td {
    border-color: rgba(255, 255, 255, 0.04) !important;
}

.sale-row--refunded .badge {
    text-decoration: none !important;
    opacity: 0.7;
}

.sale-row--refunded .convertible-currency {
    border-bottom: none !important;
}

/* 7. Stock Multi-Location Responsive Layout */
.stock-layout {
    display: grid;
    grid-template-columns: 1fr 300px;
    gap: var(--space-xl);
    align-items: start;
}

@media (max-width: 992px) {
    .stock-layout {
        grid-template-columns: 1fr;
        gap: var(--space-lg);
    }
}

/* 8. Responsive Location Tabs */
.location-tabs {
    display: flex;
    gap: var(--space-sm);
    margin-bottom: var(--space-lg);
    overflow-x: auto;
    white-space: nowrap;
    -webkit-overflow-scrolling: touch;
    padding: var(--space-xs) 0;
    scrollbar-width: none;
}

.location-tabs::-webkit-scrollbar {
    display: none;
}

.location-tabs__link {
    padding: var(--space-sm) var(--space-md);
    text-decoration: none;
    color: var(--text-secondary);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-weight: 600;
    font-size: 0.9rem;
    transition: all var(--transition-fast);
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

.location-tabs__link:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
    border-color: var(--border-light);
}

.location-tabs__link.active {
    color: #ffffff;
    background: var(--accent);
    border-color: var(--accent);
}

/* Ajout d'un emplacement : dans la barre d'onglets, mais volontairement
   en retrait — c'est une action de configuration, pas une destination. */
.location-tabs__add {
    padding: var(--space-sm) var(--space-md);
    color: var(--text-muted);
    background: transparent;
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    transition: all var(--transition-fast);
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}

.location-tabs__add:hover {
    color: var(--text-primary);
    border-color: var(--border-light);
    background: var(--bg-hover);
}

/* -----------------------------------------------
   Sessions de stock — colonne de droite
   ----------------------------------------------- */

.session-panel__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    padding-bottom: var(--space-md);
    border-bottom: 1px solid var(--border);
}

.session-panel__form {
    padding-top: var(--space-md);
}

.session-panel__empty {
    margin: var(--space-md) 0 0;
    font-size: 0.82rem;
    line-height: 1.6;
}

.session-list {
    margin-top: var(--space-xs);
}

.session-row {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--border);
}

.session-row:last-child {
    border-bottom: none;
}

/* La ligne courante se signale par une barre à gauche plutôt que par un
   encadré : dans une colonne étroite, un cadre dans un cadre ajoute deux
   bordures parallèles à quelques pixels l'une de l'autre. */
.session-row.is-current {
    margin-left: calc(-1 * var(--space-md));
    padding-left: calc(var(--space-md) - 3px);
    border-left: 3px solid var(--accent);
}

.session-row__main {
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* min-width:0 est ce qui autorise l'ellipsis : sans lui, un élément
       flex refuse de passer sous la largeur de son contenu, et le nom de
       la session repoussait les boutons hors de la carte. */
    min-width: 0;
    flex: 1;
    text-decoration: none;
    color: inherit;
}

.session-row__name {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.session-row__main:hover .session-row__name {
    color: var(--accent);
}

.session-row__date {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.session-row__flag {
    color: var(--success);
    font-weight: 600;
}

.session-row__actions {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
}

.session-row__actions form {
    margin: 0;
}

/* 9. Responsive Payment Choice Buttons */
.payment-btn-group {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-sm);
    width: 100%;
}

@media (max-width: 580px) {
    .payment-btn-group {
        grid-template-columns: 1fr;
    }
}

.payment-btn-group .btn {
    width: 100%;
    min-height: 44px;
    font-size: 0.9rem;
    font-weight: 600;
}

/* 10. Currency Bar Responsive Layout */
.currency-bar {
    margin-bottom: var(--space-md);
    padding: var(--space-md);
    background: var(--bg-card);
    border-radius: var(--radius-md);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
}

.currency-bar__state {
    min-width: 0;
}

/* Contrôle segmenté : un choix unique parmi n, dans un bloc continu.
   Des boutons séparés se lisent comme n actions ; ici la sélection est
   clairement l'état d'un même réglage. */
.segmented {
    display: inline-flex;
    padding: 3px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    gap: 2px;
    flex-wrap: wrap;
}

.segmented__option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px 16px;
    border-radius: calc(var(--radius-sm) - 2px);
    font-size: 0.85rem;
    color: var(--text-secondary);
    cursor: pointer;
    white-space: nowrap;
    transition: all var(--transition-fast);
}

.segmented__option:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

/* L'état sélectionné vient du CSS et non du JS : le rendu reste correct
   même si le script n'a pas encore tourné. */
.segmented__option:has(input:checked) {
    background: var(--accent);
    color: #ffffff;
}

.segmented__option:has(input:focus-visible) {
    box-shadow: 0 0 0 3px var(--accent-glow);
}

/* Contexte du concert dans la barre de saisie. */
.sale-context {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin-left: auto;
    font-size: 0.82rem;
    color: var(--text-secondary);
}

.sale-context__place {
    color: var(--text-primary);
}

.form-select--event {
    min-width: 320px;
    max-width: 100%;
}

/* Total de la vente en cours : lisible d'un coup d'œil au stand. */
.sale-total {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
}

.sale-total__label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
}

.sale-total__value {
    font-family: var(--font-heading);
    font-size: 1.6rem;
    font-weight: 600;
    transition: transform var(--transition-fast);
}

@media (max-width: 640px) {
    .sale-context {
        margin-left: 0;
        width: 100%;
    }

    .form-select--event {
        min-width: 0;
        width: 100%;
    }

    .segmented {
        width: 100%;
    }

    .segmented__option {
        flex: 1;
    }
}

/* Mouvement de caisse entre deux comptages. C'est la ligne qu'on cherche
   en fin de soirée — la recette encaissée, ou ce qui est parti en banque —
   elle doit se lire sans être cherchée. */
.cash-move {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.cash-move.is-in {
    color: var(--success);
    background: var(--success-bg);
    border: 1px solid rgba(34, 197, 94, 0.35);
}

.cash-move.is-out {
    color: var(--danger);
    background: var(--danger-bg);
    border: 1px solid rgba(226, 115, 58, 0.35);
}

/* Champ de montant : c'est la valeur qu'on relit pour vérifier une
   saisie, elle mérite d'être plus grande que le reste du formulaire.
   Chiffres à chasse fixe pour que les colonnes s'alignent à l'œil. */
.amount-input {
    font-size: 1.15rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
}

/* Comptage de caisse : deux colonnes, billets et pièces, chacune une
   liste coupure / quantité / sous-total. Une grille plutôt qu'un tableau
   parce que la saisie se fait au clavier, ligne après ligne. */
.cash-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-xl);
}

.cash-row {
    display: grid;
    grid-template-columns: 5.5rem 1fr 5.5rem;
    align-items: center;
    gap: var(--space-sm);
    padding: 3px 0;
}

.cash-row__denom {
    font-size: 0.85rem;
    color: var(--text-secondary);
    text-align: right;
    white-space: nowrap;
}

.cash-row__qty {
    padding: var(--space-sm) var(--space-md);
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* Le sous-total reste discret tant qu'il vaut zéro : seules les coupures
   réellement comptées doivent attirer l'œil pendant la saisie. */
.cash-row__sub {
    font-size: 0.82rem;
    text-align: right;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.cash-row__sub.is-filled {
    color: var(--text-primary);
    font-weight: 600;
}

/* Suivi des paiements : un bloc par bénéficiaire, avec son total. C'est
   l'unité qui compte — on paie une personne, pas une ligne. */
.payee {
    margin-bottom: var(--space-lg);
}

.payee:last-child {
    margin-bottom: 0;
}

.payee__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-md);
    padding-bottom: var(--space-xs);
    margin-bottom: var(--space-xs);
    border-bottom: 1px dashed var(--border);
}

.payee__name {
    font-family: var(--font-heading);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--text-primary);
}

.payee__total {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-secondary);
    white-space: nowrap;
}

/* Avancement compact, pour une cellule de tableau : la barre donne
   l'ordre de grandeur, le rapport chiffré juste en dessous donne le
   détail. Plus lisible qu'un pourcentage seul dans une colonne étroite. */
.mini-progress {
    width: 70px;
    height: 5px;
    border-radius: 999px;
    background: var(--bg-input);
    overflow: hidden;
}

.mini-progress span {
    display: block;
    height: 100%;
    border-radius: 999px;
    transition: width var(--transition-base);
}

/* Inventaire ----------------------------------------------------------- */

/* Emoji de catégorie en tête de ligne : il distingue le son de la
   lumière ou de la buvette d'un coup d'œil, là où une liste de noms se
   parcourt ligne à ligne. */
.inv-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 38px;
    height: 38px;
    border-radius: var(--radius-md);
    background: var(--bg-input);
    border: 1px solid var(--border);
    font-size: 1.05rem;
}

/* Pastille d'alerte : stock bas, péremption, matériel hors service. */
.status-chip--warning {
    color: var(--warning);
    border-color: rgba(245, 158, 11, 0.35);
    background: var(--warning-bg);
}

.status-chip--warning .status-chip__dot {
    background: var(--warning);
}

/* Planning équipe ------------------------------------------------------ */

/* Le mois entier ne tient pas dans une colonne d'écran : la grille défile
   horizontalement dans son propre conteneur, jamais la page. */
.planning-scroll {
    overflow-x: auto;
    margin: 0 calc(-1 * var(--space-md));
    padding: 0 var(--space-md);
}

.planning-grid {
    border-collapse: separate;
    border-spacing: 2px;
    width: auto;
    min-width: 100%;
}

.planning-grid th,
.planning-grid td {
    padding: 0;
    border: 0;
    text-align: center;
    vertical-align: middle;
}

.planning-grid thead th {
    width: 26px;
    padding: 4px 0;
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--text-secondary);
    line-height: 1.2;
}

.planning-grid__dow {
    display: block;
    font-size: 0.6rem;
    color: var(--text-muted);
}

/* La colonne des noms reste visible pendant le défilement horizontal —
   une pastille sans son nom ne veut rien dire. */
.planning-grid__name {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 170px;
    padding: var(--space-xs) var(--space-sm) !important;
    text-align: left !important;
    background: var(--bg-card);
}

.planning-grid__person {
    display: block;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--text-primary);
}

.planning-grid__meta {
    display: block;
    font-size: 0.7rem;
    color: var(--text-secondary);
}

.planning-grid tbody td {
    height: 30px;
    border-radius: var(--radius-sm);
    background: var(--bg-input);
}

.planning-grid tbody td.is-weekend,
.planning-grid thead th.is-weekend {
    background: rgba(255, 255, 255, 0.035);
}

.planning-grid tbody td.is-booked {
    background: var(--accent-glow);
}

.planning-grid tbody td.is-conflict {
    background: var(--warning-bg);
    box-shadow: inset 0 0 0 1px var(--warning);
}

/* Occupé d'après l'agenda personnel. Des hachures discrètes plutôt
   qu'un aplat : l'information se lit sans jamais couvrir une date
   attribuée, qui reste le sujet du tableau. Déclaré avant .is-booked
   dans le flux visuel pour que ce dernier prime en cas de cumul. */
.planning-grid tbody td.is-busy {
    background-image: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 3px,
        var(--border-light, rgba(255, 255, 255, 0.14)) 3px,
        var(--border-light, rgba(255, 255, 255, 0.14)) 4px
    );
}

.planning-grid__dot {
    display: block;
    width: 12px;
    height: 12px;
    margin: 0 auto;
    border-radius: 50%;
    background: var(--accent);
    transition: transform var(--transition-fast);
}

.planning-grid__dot:hover {
    transform: scale(1.35);
}

.planning-grid__count {
    font-family: var(--font-heading);
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--warning);
}

/* Comptabilité ------------------------------------------------------- */

/* Précision sous une valeur : le tiers d'une écriture, le concert dont
   elle vient, la mention « prévisionnel ». */
.ledger-sub {
    display: block;
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--text-secondary);
}

/* Le bouton « Joindre » est un label qui enveloppe un input file caché :
   sans ça, le contrôle natif impose son propre rendu dans un tableau. */
.receipt-form {
    margin: 0;
}

.receipt-form label {
    cursor: pointer;
}

/* Répartition par catégorie : la barre donne l'ordre de grandeur, le
   chiffre donne la valeur. */
.cat-row {
    margin-bottom: var(--space-md);
}

.cat-row:last-child {
    margin-bottom: 0;
}

.cat-row__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-md);
    margin-bottom: 4px;
    font-size: 0.85rem;
}

.cat-row__bar {
    height: 6px;
    border-radius: 999px;
    background: var(--bg-input);
    overflow: hidden;
}

.cat-row__bar span {
    display: block;
    height: 100%;
    border-radius: 999px;
}

/* Champ de logo : l'aperçu à gauche, les commandes à droite. Voir tout
   de suite ce qui est enregistré évite de réenvoyer un fichier « au cas
   où ». Le damier rappelle qu'un PNG peut être transparent. */
.logo-field {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    flex-wrap: wrap;
}

.logo-field__preview {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 160px;
    height: 90px;
    padding: var(--space-sm);
    border: 1px dashed var(--border-light);
    border-radius: var(--radius-sm);
    background-color: var(--bg-input);
    background-image:
        linear-gradient(45deg, rgba(255, 255, 255, 0.03) 25%, transparent 25%),
        linear-gradient(-45deg, rgba(255, 255, 255, 0.03) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, rgba(255, 255, 255, 0.03) 75%),
        linear-gradient(-45deg, transparent 75%, rgba(255, 255, 255, 0.03) 75%);
    background-size: 12px 12px;
    background-position: 0 0, 0 6px, 6px -6px, -6px 0;
}

.logo-field__preview img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.logo-field__empty {
    font-size: 0.78rem;
    color: var(--text-muted);
}

.logo-field__controls {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    flex: 1;
    min-width: 220px;
}

.session-banner {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    padding: var(--space-sm) var(--space-md);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    font-size: 0.85rem;
}

/* Devise de référence → devise encaissée. Le sens de lecture porte
   l'information : c'est dans ce sens que le taux s'applique. */
.currency-flow {
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.currency-flow__item {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.currency-flow__item strong {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    letter-spacing: 0.02em;
}

.currency-flow__label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
}

.currency-flow__active {
    color: var(--accent-light);
}

.currency-flow__arrow {
    color: var(--text-muted);
}

.currency-bar__rate {
    margin: var(--space-xs) 0 0;
    font-size: 0.78rem;
    color: var(--text-secondary);
}

.currency-bar__form {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

/* Cours du jour : une ligne à part, sous les deux blocs, parce que c'est
   une information et non un réglage. */
.currency-bar__market {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    flex-wrap: wrap;
    width: 100%;
    padding-top: var(--space-sm);
    border-top: 1px solid var(--border);
    font-size: 0.78rem;
    color: var(--text-secondary);
}

.form-select--compact,
.form-input--rate {
    width: auto;
    min-width: 92px;
    padding: var(--space-sm) var(--space-md);
    font-size: 0.85rem;
}

.form-select--compact {
    padding-right: 30px;
}

.form-input--rate {
    min-width: 96px;
    max-width: 110px;
}

/* Prix de référence rappelé à côté du prix encaissé. */
.price-reference {
    display: block;
    font-size: 0.78rem;
    font-weight: 400;
    color: var(--text-secondary);
}

/* Champ de recherche : l'icône vit dans le champ, et une croix apparaît
   dès qu'il y a quelque chose à effacer. */
.search-field {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 220px;
}

.search-field__icon {
    position: absolute;
    left: 12px;
    width: 16px;
    height: 16px;
    color: var(--text-secondary);
    pointer-events: none;
}

.search-field__input {
    padding-left: 38px;
    padding-right: 38px;
}

.search-field__clear {
    position: absolute;
    right: 6px;
}

.search-result-count {
    margin: 0;
    font-size: 0.8rem;
}

@media (max-width: 768px) {
    .currency-bar__form {
        margin-left: 0;
        width: 100%;
    }
}

/* 11. Event & Venue Detail Layouts & Responsive Lists */
.event-layout {
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);
    margin-top: var(--space-md);
}

/* Sur mobile la colonne latérale passe en tête : quand elle contient des
   raccourcis (Com & Media), on vient surtout les ouvrir en déplacement,
   pas remplir le formulaire. Réservé aux layouts qui le demandent — les
   autres onglets gardent leur ordre naturel. */
.event-layout--sidebar-first .event-layout__sidebar {
    order: -1;
}

@media (min-width: 992px) {
    .event-layout {
        display: grid;
        grid-template-columns: 2fr 1fr;
        gap: var(--space-xl);
        align-items: start;
    }

    /* En deux colonnes, l'ordre du flux reprend ses droits : le
       formulaire à gauche, les raccourcis à droite. */
    .event-layout--sidebar-first .event-layout__sidebar {
        order: 0;
    }
}

.event-details-card {
    border-left: 4px solid var(--accent);
}

.event-details-list {
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
}

.event-details-list li {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--border-light);
    list-style: none !important;
}

.event-details-list li:last-child {
    border-bottom: none;
}

.event-details-list .details-icon {
    font-size: 1.25rem;
    color: var(--accent);
    background: var(--accent-glow);
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-accent);
    flex-stable: 0;
}

.event-details-list .details-content {
    flex: 1;
    min-width: 0;
    word-break: break-word;
}

.event-details-list .label {
    display: block;
    font-size: 0.75rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-xs);
}

.event-details-list .value {
    font-size: 1rem;
    font-weight: 500;
    color: var(--text-primary);
}

.responsive-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-md);
}

/* Deux colonnes fixes : sans ça, quatre champs dans une carte large
   s'alignent sur une seule ligne et chaque URL devient illisible. */
.responsive-form-grid--pairs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 768px) {
    .responsive-form-grid--pairs {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 576px) {
    .responsive-form-grid {
        grid-template-columns: 1fr;
    }
}

@media (min-width: 768px) {
    .responsive-form-grid--schedule {
        grid-template-columns: 110px 1.5fr 2fr auto;
        align-items: flex-end;
    }

    .responsive-form-grid--contacts {
        grid-template-columns: 1.2fr 1.2fr 1fr 1.2fr auto;
        align-items: flex-end;
    }

    .responsive-form-grid--booking {
        grid-template-columns: 1fr 1fr;
    }
}

/* 12. Event Detail — Fiche horaire (planning) */
.timeline-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}

.timeline-item {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    background: var(--bg-primary);
    border: 1px solid var(--border);
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-sm);
}

@media (max-width: 576px) {
    .timeline-item {
        flex-wrap: wrap;
        gap: var(--space-xs);
    }
}

.timeline-time {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--accent);
    min-width: 65px;
}

.timeline-label {
    font-weight: 600;
    color: var(--text-primary);
}

.page-header--event .page-header__title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-xs) var(--space-sm);
    font-size: clamp(1.2rem, 4vw, 1.75rem);
    line-height: 1.3;
}

/* 13. Event Detail — Barre d'onglets scrollable horizontalement
   Le conteneur de défilement est `.tabs`, pas `.tabs-wrapper` : le
   wrapper doit rester fixe pour servir de repère aux dégradés de bord
   (voir .tabs-wrapper::before/::after plus haut), qui sinon défileraient
   avec le contenu.
   `min-width: max-content` sur `.tabs` annulait purement et simplement
   l'overflow : la barre s'étirait au-delà de son parent et, le body
   étant en overflow-x hidden, les derniers onglets étaient coupés et
   totalement inatteignables au doigt. */
.tabs-wrapper {
    border-bottom: 2px solid var(--border);
    padding-bottom: 2px;
}

.tabs-wrapper .tabs {
    display: flex;
    gap: var(--space-xs);
    margin-bottom: 0;
    border-bottom: none;
    white-space: nowrap;
    min-width: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Sans ça les onglets se compriment au lieu de déborder, et il n'y a
   plus rien à faire défiler. */
.tabs-wrapper .tab-btn {
    flex: 0 0 auto;
}

/* 14. Event Detail — Bouton bascule "Acompte payé" */
.deposit-toggle-badge {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border-radius: var(--radius-md);
    border: 2px solid var(--border);
    cursor: pointer;
    font-weight: 600;
    font-size: 0.95rem;
    transition: all 0.25s ease;
    user-select: none;
    background: var(--bg-primary);
    width: fit-content;
}

.deposit-toggle-badge:focus-within {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.deposit-toggle-badge.is-paid {
    background: rgba(39, 174, 96, 0.15);
    border-color: var(--success);
    color: #2ec4b6;
    box-shadow: 0 0 12px rgba(39, 174, 96, 0.25);
}

.deposit-toggle-badge.is-pending {
    background: rgba(243, 156, 18, 0.1);
    border-color: rgba(243, 156, 18, 0.4);
    color: var(--warning);
}

.deposit-toggle-badge:hover {
    transform: translateY(-1px);
}

/* 15. Admin — Fiches Groupe repliables (Groupes & Clés API) */
.admin-group-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

.admin-group-card {
    padding: 0;
    overflow: hidden;
}

.admin-group-card__summary {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-lg);
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    color: inherit;
    font: inherit;
    flex-wrap: wrap;
}

.admin-group-card__summary:hover {
    background: var(--bg-hover);
}

.admin-group-card__meta {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    min-width: 0;
}

.admin-group-card__icon {
    font-size: 1.5rem;
    flex-shrink: 0;
}

.admin-group-card__name {
    display: block;
    font-weight: 600;
    font-size: 1.05rem;
}

.admin-group-card__slug {
    display: block;
    font-size: 0.8rem;
    color: var(--text-secondary);
}

.admin-group-card__badges {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.admin-group-card__chevron {
    width: 18px;
    height: 18px;
    color: var(--text-secondary);
    transition: transform var(--transition-fast);
    flex-shrink: 0;
}

.admin-group-card__summary[aria-expanded="true"] .admin-group-card__chevron {
    transform: rotate(180deg);
}

.admin-group-card__body {
    display: none;
    padding: 0 var(--space-lg) var(--space-lg);
    border-top: 1px solid var(--border);
}

.admin-group-card__body.open {
    display: block;
    padding-top: var(--space-lg);
}

.admin-group-card__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding-top: var(--space-md);
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}

/* Pastille d'identité d'un groupe : ses initiales, à défaut d'un logo.
   Distingue les groupes entre eux là où une même icône les confondait. */
.group-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: var(--radius-md);
    background: var(--accent-glow);
    border: 1px solid var(--border-accent);
    font-family: var(--font-heading);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--accent-light);
}

/* État d'un réglage : une puce colorée. Un réglage absent doit se lire
   comme neutre — pas comme une alerte, comme le faisait un tiret gris à
   côté de coches vertes. */
.status-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg-input);
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--text-secondary);
    white-space: nowrap;
}

.status-chip__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-muted);
    flex-shrink: 0;
}

.status-chip.is-on {
    color: var(--success);
    border-color: rgba(34, 197, 94, 0.35);
    background: var(--success-bg);
}

.status-chip.is-on .status-chip__dot {
    background: var(--success);
}

.status-chip--info {
    color: var(--info);
    border-color: rgba(59, 130, 246, 0.35);
    background: var(--info-bg);
}

.status-chip--info .status-chip__dot {
    background: var(--info);
}

/* Variante sans puce, pour une simple étiquette (la devise). */
.status-chip--plain {
    font-family: var(--font-heading);
    font-weight: 600;
    color: var(--text-primary);
}

.group-avatar--sm {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
}

/* Membres d'un groupe : lecture seule, en grille pour qu'une équipe de
   huit personnes ne fasse pas huit lignes de haut. */
.member-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: var(--space-xs);
    margin: 0;
    padding: 0;
    list-style: none;
}

.member-list__item {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    min-width: 0;
    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    border: 1px solid var(--border);
}

.member-list__item.is-inactive {
    opacity: 0.55;
}

.member-list__body {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.member-list__name {
    font-size: 0.85rem;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.member-list__role {
    font-size: 0.72rem;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.settings-section {
    margin-bottom: var(--space-lg);
}

.settings-section__title {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-secondary);
    margin-bottom: var(--space-md);
    padding-bottom: var(--space-xs);
    border-bottom: 1px dashed var(--border);
}

@media (max-width: 640px) {
    .admin-group-card__summary {
        align-items: flex-start;
    }

    .admin-group-card__badges {
        width: 100%;
        justify-content: space-between;
    }
}

/* 16. Profil utilisateur — bannière avatar + champs mot de passe */
.profile-banner__body {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    flex-wrap: wrap;
}

.profile-avatar {
    position: relative;
    flex-shrink: 0;
    width: 96px;
    height: 96px;
}

.profile-avatar__img,
.profile-avatar__initials {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    border: 3px solid var(--accent);
    box-shadow: var(--shadow-md);
}

.profile-avatar__img {
    object-fit: cover;
    transition: opacity var(--transition-fast);
}

.profile-avatar__initials {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--accent);
    font-size: 2.2rem;
    font-weight: 700;
    color: #ffffff;
}

/* Bouton d'édition toujours visible (pas de survol requis : doit
   fonctionner identiquement sur mobile tactile et sur desktop). */
.profile-avatar__edit-btn {
    position: absolute;
    bottom: -2px;
    right: -2px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: #ffffff;
    border: 3px solid var(--bg-card);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background var(--transition-fast), transform var(--transition-fast);
}

.profile-avatar__edit-btn svg {
    width: 15px;
    height: 15px;
}

.profile-avatar__edit-btn:hover {
    background: var(--accent-hover);
    transform: scale(1.08);
}

.profile-banner__info {
    flex: 1;
    min-width: 200px;
}

.profile-banner__name {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text-primary);
}

.profile-banner__username {
    color: var(--text-secondary);
    font-size: 0.88rem;
    margin-top: 2px;
    margin-bottom: var(--space-md);
}

.profile-banner__actions {
    display: flex;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.profile-banner__hint {
    margin-top: var(--space-sm);
    font-size: 0.82rem;
    color: var(--warning);
}

.link-btn {
    background: none;
    border: none;
    padding: 0;
    color: inherit;
    text-decoration: underline;
    font: inherit;
    cursor: pointer;
}

/* Champ mot de passe avec bouton afficher/masquer */
.field-with-toggle {
    position: relative;
}

.field-with-toggle input {
    padding-right: 44px;
}

.field-with-toggle__btn {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    border-radius: var(--radius-sm);
    background: none;
    border: none;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.field-with-toggle__btn svg {
    width: 18px;
    height: 18px;
}

.field-with-toggle__btn:hover {
    color: var(--text-secondary);
    background: var(--bg-hover);
}

.field-with-toggle__btn.is-visible {
    color: var(--accent);
}

@media (max-width: 480px) {
    .profile-banner__body {
        flex-direction: column;
        text-align: center;
    }

    .profile-banner__actions {
        justify-content: center;
    }
}

/* 17. Formulaire "ajout rapide" encadré (utilisé dans events/view.php
   pour line-up, budget, contacts, planning...) — remplace le style
   inline dupliqué à l'identique sur chaque formulaire. */
.inline-form {
    background: var(--bg-primary);
    padding: var(--space-md);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
}

.inline-form--accent {
    border-color: var(--border-accent);
}

.inline-form--row {
    display: flex;
    gap: var(--space-sm);
    align-items: center;
    flex-wrap: wrap;
}

/* Journal des opérations (Activity log) */
.activity-timeline {
    position: relative;
    padding-left: 28px;
    border-left: 2px solid var(--border-accent);
    margin-left: 12px;
    margin-top: var(--space-md);
}

.activity-timeline__item {
    position: relative;
    margin-bottom: var(--space-lg);
}

.activity-timeline__item:last-child {
    margin-bottom: 0;
}

.activity-timeline__bullet {
    position: absolute;
    left: -41px;
    top: 2px;
    background: var(--bg-card);
    border: 2px solid var(--border-accent);
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    box-shadow: var(--shadow-sm);
}

.activity-timeline__card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-md) var(--space-lg);
    box-shadow: var(--shadow-sm);
}

.activity-timeline__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-xs);
    flex-wrap: wrap;
    gap: var(--space-sm);
}

.activity-timeline__who {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.activity-timeline__body {
    color: var(--text-secondary);
    font-size: 0.95rem;
    line-height: 1.4;
    margin-top: var(--space-xs);
}

/* -----------------------------------------------
   Onglet Cachets — bandeau deal, jauge de paiement,
   barre d'actions rapides et part de cachet
   ----------------------------------------------- */

/* Les 4 chiffres du deal, lisibles sans scroller. Toujours 2 ou 4
   colonnes, jamais 3 : un auto-fit laisserait une tuile orpheline sur
   les largeurs intermédiaires. minmax(0, 1fr) et pas 1fr, sinon la
   largeur minimale du contenu déséquilibre les colonnes. */
.deal-grid,
.info-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}

@media (min-width: 900px) {

    .deal-grid,
    .info-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.deal-tile,
.info-tile {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--space-md);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.deal-tile--accent,
.info-tile--accent {
    border-color: var(--border-accent);
    background: var(--accent-glow);
}

.deal-tile--ok {
    border-color: rgba(34, 197, 94, 0.35);
    background: var(--success-bg);
}

.deal-tile__label,
.info-tile__label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
}

.deal-tile__value,
.info-tile__value {
    font-family: var(--font-heading);
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.15;
    color: var(--text-primary);
    word-break: break-word;
}

.deal-tile__value--accent,
.info-tile__value--accent {
    color: var(--accent);
}

/* Les deux familles partagent leurs modificateurs : les templates
   mélangent `info-tile__value` et `deal-tile__value--ok`, et l'inverse.
   Sans ces alias, `info-tile__value--ok` ne colorait rien — la tuile
   « Recettes » de l'onglet Budget n'était pas verte, sans que ça se
   remarque. */
.deal-tile__value--ok,
.info-tile__value--ok {
    color: var(--success);
}

.deal-tile__value--muted,
.info-tile__value--muted {
    color: var(--text-muted);
}

.deal-tile__meta,
.info-tile__meta {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

.deal-tile__action {
    margin-top: auto;
    padding-top: var(--space-sm);
}

/* Jauge encaissé / attendu */
.pay-progress__track {
    height: 8px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: 999px;
    overflow: hidden;
}

.pay-progress__fill {
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
    transition: width var(--transition-base);
}

.pay-progress__fill.is-settled {
    background: var(--success);
}

.pay-progress__legend {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-xs);
    margin-top: 6px;
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* Barre d'actions rapides (statut, copie du récap, édition) */
.deal-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-sm);
}

.deal-toolbar__group {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
}

.deal-toolbar__spacer {
    margin-left: auto;
}

.deal-toolbar__label {
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary);
}

/* width:auto pour annuler le width:100% global des champs, sinon le
   select étire sa ligne et fait passer les boutons à la ligne. */
.deal-toolbar .form-select {
    margin-bottom: 0;
    width: auto;
    min-width: 190px;
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
}

/* -----------------------------------------------
   Tableau de bord — suivi par date
   ----------------------------------------------- */
.date-row {
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--border);
}

.date-row:last-of-type {
    border-bottom: none;
}

.date-row__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-sm) var(--space-md);
}

.date-row__name {
    font-weight: 600;
    color: var(--text-primary);
    text-decoration: none;
}

.date-row__name:hover {
    color: var(--accent);
}

/* -----------------------------------------------
   Checklist de production
   ----------------------------------------------- */
/* Bandeau d'avancement : un seul bloc en tête d'onglet. Quatre tuiles
   répétaient ce que la liste dit déjà ligne par ligne, et repoussaient
   la checklist elle-même sous la ligne de flottaison. */
.checklist-head {
    margin-bottom: var(--space-lg);
    padding: var(--space-md);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.checklist-head__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}

.checklist-head__score {
    display: flex;
    align-items: baseline;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.checklist-head__percent {
    font-family: var(--font-display, inherit);
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1;
}

.checklist-head__meta {
    font-size: 0.82rem;
    color: var(--text-secondary);
}

.checklist-head__actions {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
}

.checklist-head__track {
    height: 6px;
    background: var(--bg-tertiary);
    border-radius: 999px;
    overflow: hidden;
}

.checklist-head__fill {
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
    transition: width var(--transition-base);
}

.checklist-head__fill.is-settled {
    background: var(--success);
}

.task-filters {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
    margin-top: var(--space-md);
}

/* Les pastilles de filtre existent en <a> ailleurs dans l'application ;
   ici ce sont des <button>, qui n'héritent ni la police ni le curseur. */
.task-filters .filter-chip {
    font-family: inherit;
    cursor: pointer;
}

.filter-chip__count {
    margin-left: 4px;
    opacity: 0.65;
    font-variant-numeric: tabular-nums;
}

.task-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-md);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--border);
}

/* Le séparateur se règle sur le conteneur : `.task-row:last-of-type`
   visait la fin de la carte, mais chaque ligne est désormais seule dans
   son .task-item et perdrait donc toutes les bordures. */
.task-item:last-child > .task-row {
    border-bottom: none;
}

/* Flèches de réordonnancement : discrètes, et assez hautes pour rester
   atteignables au pouce une fois empilées. */
.task-move {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.task-move__btn {
    width: 24px;
    height: 16px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--text-muted);
    font-size: 0.6rem;
    line-height: 1;
    cursor: pointer;
}

.task-move__btn:hover {
    border-color: var(--border);
    background: var(--bg-hover);
    color: var(--text-primary);
}

.task-row.is-done .task-row__label {
    color: var(--text-secondary);
    text-decoration: line-through;
    text-decoration-color: var(--text-muted);
}

.task-row.is-cancelled {
    opacity: 0.5;
}

.task-row.is-cancelled .task-row__label {
    text-decoration: line-through;
}

/* Une tâche en retard doit sauter aux yeux dans une liste de quinze
   lignes : la date en rouge seule ne suffit pas. */
.task-row.is-late {
    border-left: 3px solid var(--warning);
    margin-left: calc(-1 * var(--space-md));
    padding-left: calc(var(--space-md) - 3px);
    background: linear-gradient(to right, var(--warning-bg), transparent 40%);
}

.task-row__toggle {
    margin: 0;
    flex-shrink: 0;
}

/* Case à cocher : gros bouton tactile, sans habillage de bouton. */
.task-check {
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color var(--transition-fast), background var(--transition-fast);
}

.task-check:hover {
    border-color: var(--accent);
    background: var(--bg-hover);
}

.task-check--static {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: default;
}

.task-row__body {
    flex: 1 1 auto;
    min-width: 0;
}

.task-row__label {
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.35;
    word-break: break-word;
}

.task-row__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-sm);
    margin-top: 5px;
}

.task-meta {
    font-size: 0.78rem;
    color: var(--text-secondary);
}

.task-meta--late {
    color: var(--warning);
    font-weight: 600;
}

.task-row__actions {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-shrink: 0;
}

.task-edit {
    margin: 0 0 var(--space-md);
    padding: var(--space-md);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

/* Pastille d'alerte dans le libellé d'un onglet */
.tab-alert {
    font-size: 0.85em;
}

@media (max-width: 640px) {

    /* Les actions restent sur la même ligne : les faire passer dessous
       ajoutait une ligne entière par tâche, ce qui rendait une checklist
       de quinze lignes interminable à parcourir au pouce. */
    .task-row {
        gap: var(--space-sm);
    }

    .task-row__actions {
        flex-direction: column;
        gap: 2px;
    }

    /* Les flèches repassent côte à côte : empilées dans une colonne déjà
       empilée, elles ajoutaient deux lignes par tâche. */
    .task-move {
        flex-direction: row;
    }

    .task-move__btn {
        width: 22px;
        height: 22px;
    }

    .checklist-head__actions {
        width: 100%;
    }

    .task-row__label {
        font-size: 0.9rem;
    }
}

/* -----------------------------------------------
   Onglet Production — déroulé de journée
   ----------------------------------------------- */

/* Intertitre à l'intérieur d'une carte */
.section-heading {
    margin: 0 0 var(--space-sm);
    font-family: var(--font-body);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--text-secondary);
}

.section-heading--sub {
    margin-top: var(--space-lg);
    padding-top: var(--space-md);
    border-top: 1px solid var(--border);
}

/* Fiche d'un groupe : en-tête récapitulatif + formulaire dépliable */
.band-sheet {
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--border);
}

.band-sheet:last-of-type {
    border-bottom: none;
}

.band-sheet__head {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--space-md);
}

.band-sheet__id {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
    flex: 1 1 220px;
}

.band-sheet__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    flex: 2 1 260px;
}

.band-fact {
    font-size: 0.8rem;
    color: var(--text-secondary);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 3px 9px;
}

.band-fact--missing {
    color: var(--warning);
    border-color: rgba(245, 158, 11, 0.4);
    background: var(--warning-bg);
}

.band-sheet__form {
    margin-top: var(--space-md);
    padding: var(--space-md);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.band-sheet__form .section-heading--sub:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

/* Total des repas à prévoir */
.meal-total {
    margin-top: var(--space-lg);
    padding: var(--space-md);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.meal-total__line {
    display: flex;
    justify-content: space-between;
    gap: var(--space-md);
    padding: 4px 0;
    font-size: 0.9rem;
    color: var(--text-secondary);
}

.meal-total__line--sum {
    margin-top: var(--space-xs);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--border);
    color: var(--text-primary);
    font-size: 1rem;
}

.meal-total__line--sum strong {
    color: var(--accent);
}

/* Blocs de faits (salle, hébergement, merch) dans le résumé logistique */
.fact-block {
    margin-top: var(--space-lg);
    padding-top: var(--space-md);
    border-top: 1px solid var(--border);
}

/* Intertitre + son bouton d'édition sur la même ligne : un bloc qui se
   modifie doit le dire là où il s'affiche, pas dans un « Modifier »
   global en haut de carte qu'on ne relie pas au bloc. */
.fact-block__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}

/* Ligne de la salle : tout ce qui la décrit tient ici, le détail vit sur
   sa fiche. Voir le commentaire du template pour le pourquoi. */
.venue-line {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-md);
    flex-wrap: wrap;
    padding: var(--space-md);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.venue-line__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1;
}

.venue-line__name {
    font-weight: 600;
    color: var(--text-primary);
}

.venue-line__meta {
    font-size: 0.82rem;
    color: var(--text-secondary);
}

.venue-line__actions {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    flex-wrap: wrap;
    flex-shrink: 0;
}

.fact-line {
    display: flex;
    justify-content: space-between;
    gap: var(--space-md);
    padding: 5px 0;
    font-size: 0.9rem;
    color: var(--text-secondary);
    border-bottom: 1px dashed var(--border);
}

.fact-line:last-child {
    border-bottom: none;
}

.fact-line strong {
    color: var(--text-primary);
    text-align: right;
}

.fact-block__text {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--text-secondary);
    white-space: pre-wrap;
}

/* -----------------------------------------------
   Import de contacts depuis l'annuaire d'une salle
   ----------------------------------------------- */
/* Panneau d'import de contacts depuis une salle. Fond neutre : les
   contacts de la salle rattachée arrivent désormais tout seuls à la
   création de la date, ce panneau ne sert plus qu'au cas particulier
   (piocher chez une autre salle) et n'a plus à crier en rouge. */
.import-panel {
    padding: var(--space-md);
    background: var(--bg-tertiary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.import-panel__title {
    color: var(--text-primary) !important;
}

.import-panel__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-bottom: var(--space-md);
}

.import-panel__title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--accent);
}

.import-panel__select {
    width: auto;
    min-width: 220px;
    max-width: 100%;
    margin: 0 0 0 auto;
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
}

/* Recherche dans le carnet. Poussée à droite comme le sélecteur de
   salle, et le champ prend la place restante : c'est le geste principal
   du panneau, pas une option. */
.import-panel__search {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    flex-wrap: wrap;
    margin: 0 0 0 auto;
}

.import-panel__search .form-input {
    width: auto;
    min-width: 240px;
    margin-bottom: 0;
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
}

.import-list {
    display: grid;
    gap: var(--space-xs);
    max-height: 320px;
    overflow-y: auto;
    margin-bottom: var(--space-md);
}

.import-item {
    display: flex;
    align-items: flex-start;
    gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color var(--transition-fast);
}

.import-item:hover {
    border-color: var(--border-accent);
}

.import-item.is-disabled {
    opacity: 0.55;
    cursor: default;
}

.import-item.is-disabled:hover {
    border-color: var(--border);
}

.import-item__check {
    width: 18px;
    height: 18px;
    margin-top: 2px;
    flex-shrink: 0;
    accent-color: var(--accent);
    cursor: inherit;
}

.import-item__body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.import-item__line {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
}

.import-item__meta {
    font-size: 0.8rem;
    color: var(--text-secondary);
    word-break: break-word;
}

.import-panel__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
}

@media (max-width: 640px) {
    .import-panel__select {
        margin-left: 0;
        width: 100%;
    }
}

/* -----------------------------------------------
   Documents joints (fiches techniques PDF)
   ----------------------------------------------- */
.doc-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-md);
    padding: var(--space-md) 0;
    border-bottom: 1px solid var(--border);
}

.doc-row:last-of-type {
    border-bottom: none;
}

.doc-row--venue {
    padding: var(--space-md);
    margin-bottom: var(--space-md);
    background: var(--bg-hover);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
}

.doc-row__who {
    flex: 1 1 200px;
    min-width: 0;
}

.doc-row__file {
    flex: 2 1 240px;
    min-width: 0;
    font-size: 0.9rem;
    word-break: break-word;
}

.doc-row__actions {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin-left: auto;
    flex-wrap: wrap;
}

.doc-link {
    color: var(--accent);
    text-decoration: none;
    font-weight: 600;
}

.doc-link:hover {
    text-decoration: underline;
}

.doc-upload {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    margin: 0;
    flex-wrap: wrap;
}

/* Le champ fichier natif est large et disgracieux. Le contraindre en
   largeur ne suffisait pas : son libellé « Aucun fichier sélectionné »
   restait, rogné en « A… » au milieu de la ligne. On le rend donc
   transparent — seul le bouton natif reste visible, et le nom du fichier
   choisi s'affiche dans .doc-upload__name, à côté. */
.doc-upload__input {
    width: auto;
    max-width: 160px;
    padding: 5px 8px;
    font-size: 0.78rem;
    color: transparent;
}

/* Fiche d'un lieu — adresse, coordonnées et GPS côte à côte.
   Ces trois blocs vivaient dans une colonne d'un tiers de large, où
   chaque valeur repassait à la ligne. À l'horizontale ils tiennent sur
   une seule bande, et le reste de la fiche récupère la page entière. */
.venue-access {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xl);
    align-items: flex-start;
}

.venue-access__block {
    flex: 1 1 220px;
    min-width: 0;
}

/* Le bloc GPS porte un bouton : il se cale à droite quand la place le
   permet, et repasse dans le flux dès que la ligne se replie. */
.venue-access__block--end {
    flex-grow: 0;
}

.venue-access__value {
    margin-top: 6px;
    font-size: 0.95rem;
    line-height: 1.5;
    word-break: break-word;
}

.doc-upload__name {
    font-size: 0.78rem;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.doc-upload__input::file-selector-button {
    margin-right: 8px;
    padding: 4px 10px;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    background: var(--bg-hover);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
}

.doc-upload__input::file-selector-button:hover {
    border-color: var(--accent);
    color: var(--accent);
}

@media (max-width: 640px) {
    .doc-row__actions {
        margin-left: 0;
        width: 100%;
    }

    .doc-upload {
        width: 100%;
    }

    .doc-upload__input {
        max-width: none;
        flex: 1 1 140px;
    }
}

/* Rôle sur la soirée : même forme qu'un .badge mais sans majuscules
   forcées ni interlettrage — « Tête d'affiche » en capitales espacées
   fait déborder la colonne Rôle sur les écrans intermédiaires. */
.role-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 0.75rem;
    font-weight: 600;
}

/* Téléphone / email dans un tableau : un lien texte sobre, jamais un
   badge — un numéro de 14 caractères dans une pastille étroite
   retombait à la ligne et cassait la hauteur de toute la ligne.
   Partagé par le carnet de contacts, la fiche salle et l'onglet
   Contacts d'une date. */
.contact-line-link {
    color: var(--text-secondary);
    font-size: 0.85rem;
    text-decoration: none;
    white-space: nowrap;
}

.contact-line-link:hover {
    color: var(--accent);
    text-decoration: underline;
}

/* Une adresse mail longue ne doit pas élargir la colonne indéfiniment :
   elle se tronque plutôt, le titre au survol donne la valeur entière. */
.contact-line-link--mail {
    display: inline-block;
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
}

/* Contacts d'un événement : rôle, étiquette d'origine (repris de la
   fiche salle) et estompage d'une ligne désactivée pour cette date
   sans être supprimée (cf. Models\Event::toggleContact). */
.event-contact-role {
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
}

.event-contact-name {
    white-space: nowrap;
}

/* Étiquette discrète : une pastille pleine par ligne suffisait à
   doubler la hauteur du tableau pour une information secondaire. */
.event-contact-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border: 1px solid var(--border);
    border-radius: 10px;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    vertical-align: 1px;
    white-space: nowrap;
}

.event-contact-tag--off {
    border-color: rgba(245, 158, 11, 0.45);
    color: var(--warning);
}

.event-contact-row--inactive {
    opacity: 0.55;
}

.event-contact-row--inactive:hover {
    opacity: 1;
}

/* Part d'un groupe dans le total du plateau */
.share-bar {
    display: block;
    height: 4px;
    margin-top: 6px;
    margin-left: auto;
    max-width: 120px;
    background: var(--bg-tertiary);
    border-radius: 999px;
    overflow: hidden;
}

.share-bar__fill {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
}

/* En mode "cartes" (tableau empilé), chaque cellule est un flex : la
   barre de part de cachet n'y a pas de largeur propre et n'apporte
   rien puisque le montant est déjà lisible en pleine largeur. */
@media (max-width: 768px) {
    .table-responsive-cards .share-bar {
        display: none;
    }
}

@media (max-width: 640px) {

    .deal-grid,
    .info-grid {
        gap: var(--space-sm);
    }

    .deal-tile__value,
    .info-tile__value {
        font-size: 1.15rem;
    }

    .deal-toolbar__spacer {
        margin-left: 0;
    }

    .deal-toolbar,
    .deal-toolbar__group,
    .deal-toolbar .form-select {
        width: 100%;
    }

    .share-bar {
        margin-left: 0;
        max-width: none;
    }
}
/* -----------------------------------------------
   Journal — valeurs avant / après
   ----------------------------------------------- */

/* Le journal disait ce qui avait été touché, jamais ce qui avait changé.
   Ce bloc porte le détail sous la description, sans la remplacer : la
   phrase reste ce qui se lit d'un coup d'œil. */
.change-list {
    margin: var(--space-sm) 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.change-list__item {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-xs);
    padding: 3px 0;
    font-size: 0.78rem;
    line-height: 1.5;
}

.change-list__label {
    color: var(--text-secondary);
    font-weight: 600;
}

.change-list__label::after {
    content: ' :';
}

/* L'ancienne valeur reste lisible : barrée, elle deviendrait pénible à
   relire alors que c'est justement ce qu'on vient chercher. Le contraste
   suffit à dire laquelle des deux est la nouvelle. */
.change-list__from {
    color: var(--text-muted);
}

.change-list__arrow {
    color: var(--text-muted);
}

.change-list__to {
    color: var(--text-primary);
    font-weight: 600;
}

/* -----------------------------------------------
   Invitations — pointage à l'entrée
   ----------------------------------------------- */

/* Case à cocher pleine largeur de cellule : à la porte, on vise avec le
   pouce sur un téléphone, dans le noir. Un vrai bouton, pas une icône
   de 12 px. */
.guest-check {
    font-size: 1.25rem;
    line-height: 1;
    padding: 6px 10px;
    min-width: 44px;
    min-height: 44px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.guest-check:hover {
    background: var(--bg-hover);
    border-color: var(--border-light);
}

.guest-check.is-in {
    border-color: rgba(34, 197, 94, 0.45);
    background: var(--success-bg);
}

/* La ligne pointée s'efface légèrement : ce qui reste à faire est ce
   qui n'est pas encore coché, et c'est là que le regard doit tomber. */
.guest-row--in {
    opacity: 0.62;
}

.guest-row--in:hover {
    opacity: 1;
}

/* Horaires saisis directement dans le tableau du déroulé de journée.
   Les champs doivent tenir dans une cellule sans élargir la colonne :
   une largeur fixe, et le sélecteur natif du navigateur pour le reste. */
.form-input--time {
    width: auto;
    min-width: 6.5rem;
    max-width: 100%;
    padding: 4px 8px;
    font-size: 0.85rem;
}

.time-range {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

/* Retour des réglages de notifications, sous les boutons de Mon profil. */
.push-status:empty { display: none; }

.push-status {
    margin: var(--space-md) 0 0;
    font-size: 0.85rem;
    color: var(--text-secondary);
    max-width: 70ch;
}

.push-status--error { color: var(--danger); }
