/* ============================================
   ASSIMIL BACK-OFFICE - THEME & DESIGN TOKENS
   All CSS custom properties (variables) are
   defined here for easy theming.
   ============================================ */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');

:root {
    /* - Logo - */
    --color-logo: #0277c0;
    --logo-height: 45px;
    --logo-height-login: 55px;
    --logo-height-sidebar: 26px;

    /* - Brand colors - */
    --color-primary: #3ab3ff;
    --color-primary-light: #7dcfff;
    --color-primary-lighter: #b0e2ff;
    --color-primary-rgb: 58, 179, 255;
    --color-secondary: #fdac05;
    --color-secondary-light: #fdc248;
    --color-danger: #ff4757;
    --color-danger-light: #ff6b7a;
    --color-error: #ff0042;
    --color-error-bg: #fef2f2;
    --color-error-border: #fca5a5;
    --color-error-text: #cc0000;
    --color-success: #70c3f6;
    --color-warning: #e67e33;
    --color-purple: #cd1dff;
    /* Neutre : une pastille qui ne dit ni un état ni une action, seulement « voir ». */
    --color-neutral: #d2d2d2;
    /* Le gris des gestes qui CONSULTENT — emporter le fichier, ouvrir la liste des mots.
       Plus soutenu que `--color-neutral`, qui sert a dire « pas encore possible » : une
       icone blanche sur #d2d2d2 se devinait plus qu'elle ne se lisait. */
    --color-neutral-strong: #8e959c;
    /* Le son : le teal des ressources audio de la page des ressources, déjà en place. */
    --color-audio: #20a6b3;
    /* PRODUIRE la piste, et non l'entendre : la meme famille, en plus sombre. Ecouter et
       telecharger n'engagent rien ; generer remplace ce qu'on ecoutait. */
    --color-audio-make: #15707a;
    /* REFAIRE L'AUDIO : le geste le plus destructeur de la page apres la corbeille — il
       efface une interpretation qu'on ne retrouvera pas. Corail et non rouge : c'est un
       geste normal du travail, pas une suppression. */
    --color-coral: #ff7050;
    --color-audio-make-rgb: 21, 112, 122;
    --color-green: #27ae60;
    --color-info: #4871a0;
    --color-info-bg: #f0f9ff;
    --color-info-border: #bae6fd;
    --color-info-text: #0369a1;

    /* - Text - */
    --text-primary: #1e293b;
    --text-secondary: #64748b;
    --text-muted: #94a3b8;
    --text-on-dark: #cbd5e1;
    --text-on-primary: #ffffff;
    --text-separator: #bababa;
    --text-body: #333333;
    --text-link: #414951;
    --text-link-accent: #3ab3ff;

    /* - Backgrounds - */
    --page-bg: #f0f0f0;
    --card-bg: #ffffff;
    --bg-subtle: #f7f7f7;
    --bg-catalog: #dddbdb; /* fond colonne "diffusion catalogue" (Firestore), distincte des plateformes de paiement */
    --bg-hover: #f5f5f5;
    --bg-highlight: #fafafa;
    --bg-muted: #f6f6f6;
    --bg-purple-light: #fbeefa;

    /* - Borders - */
    --border-color: transparent;
    --border-light: transparent;
    --border-input: #e0e0e0;

    /* - Sidebar - */
    --sidebar-width: 220px;
    --sidebar-collapsed-width: 72px;
    --sidebar-bg: #ffffff;
    --sidebar-hover: #f5f5f5;
    --sidebar-submenu-bg: #fafafa;
    --sidebar-text: #64748b;
    --sidebar-text-hover: #1e293b;
    --sidebar-border: #e8e8e8;

    /* - Header - */
    --header-height: 52px;

    /* - Icon circle sizes (pastilles rondes avec icône) - */
    --icon-circle-size: 48px;
    --icon-circle-font-size: 1.8em;

    /* - Radius - */
    --radius-pill: 50px;
    --radius-lg: 12px;
    --radius-md: 8px;
    --radius-sm: 6px;
    --radius-xs: 4px;

    /* - Spacing - */
    --space-xs: 4px;
    --space-sm: 8px;
    --space-md: 12px;
    --space-lg: 16px;
    --space-xl: 20px;
    --space-2xl: 30px;

    /* - Font sizes - (bumped +1 step for readability) */
    --font-2xs: 0.72rem;
    --font-xs: 0.82rem;
    --font-sm: 0.88rem;
    --font-base: 0.95rem;
    --font-md: 1rem;
    --font-lg: 1.1rem;

    /* - Shadows - */
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);
    --shadow-focus: 0 0 0 3px rgba(var(--color-primary-rgb), 0.1);

    /* - Transitions - */
    --transition-fast: 0.15s ease;
    --transition-normal: 0.25s ease;

    /* - Bootstrap overrides - */
    --bs-primary: var(--color-primary);
    --bs-primary-rgb: var(--color-primary-rgb);
}


/* ---------------------------------------------------------------------------
   BOUTON ROND A ICONE — la classe etait employee par `_searchForm.gsp` sans
   avoir jamais ete definie : la forme ne vivait que dans un `style=` recopie
   d'un formulaire a l'autre. Une seule definition, et tous les ecrans suivent.
   --------------------------------------------------------------------------- */
.btn.icon-btn {
    border-radius: 50%;
    width: 42px;
    height: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
}

.btn.icon-btn i.ph {
    font-size: 1.3em;
}

/* LES ICONES DES LIGNES D'INFORMATION — a peine plus grandes que le texte, pour
   se lire d'un coup d'oeil sans le dominer. Posee ici plutot qu'en `style=` sur
   chaque icone : elles sont rendues par des templates partages entre la liste
   des achats, celle des suspects et les notifications. */
.info-muted > i.ph,
.info-date > i.ph,
li.info-muted > i.ph {
    font-size: 1.15em;
    vertical-align: -0.08em;
}


/* ---------------------------------------------------------------------------
   CARTE D'INFORMATION — une zone encadree dans une liste de details.

   Definie ici plutot que par ecran : `stat-card` est deja recopiee dans deux
   vues, et une troisieme definition en ferait une convention introuvable. Ces
   regles ont vecu quelques heures dans un `<style>` de la page des suspects, le
   temps de chercher l'apparence sans repasser par `assetCompile` — et la page
   des ACHATS, qui rend le meme template, n'en voyait rien.

   Les jetons du theme plutot que des valeurs en dur : `--radius-lg`, `--space-*`,
   `--shadow-sm` et `--font-2xs` disent la meme chose partout.
   --------------------------------------------------------------------------- */
/* LES JETONS DU THEME PLUTOT QUE DES VALEURS EN DUR : --radius-lg, --space-*, --shadow-sm
       et --font-2xs existent depuis toujours et disent la meme chose partout. */
    .info-card {
        display: block;
        width: fit-content;
        max-width: 100%;
        list-style: none;
        border: 1px solid var(--border-input);
        border-radius: var(--radius-lg);
        padding: var(--space-md) var(--space-lg);
        margin: var(--space-sm) 0;
        background: var(--card-bg);
        box-shadow: var(--shadow-sm);
    }

    /* ⚠️ BATTUE EN SPECIFICITE SANS CETTE LIGNE. `.list table tbody td ul li { padding: 1px 0 }`
       vaut 0,1,5 contre 0,1,0 : dans une colonne de tableau — c'est-a-dire partout ou cette
       carte sert — son `padding` etait purement et simplement barre. On ne surcharge que la
       propriete en cause, et seulement dans le contexte qui la reprenait. */
    .list table tbody td ul li.info-card {
        padding: var(--space-md) var(--space-lg);
    }

    .info-card > div {
        line-height: 1.6;
    }

    .info-card > div + div {
        margin-top: var(--space-xs);
    }

    /* LA FORME PERIMEE S'EFFACE, ELLE NE CRIE PAS : pointilles gris, fond transparent, pas
       d'ombre. Le regard va d'abord a la forme vivante, et ne trouve celle-ci que s'il la
       cherche — elle revient a pleine opacite au survol. */
    .info-card--deprecated {
        position: relative;
        margin-top: var(--space-lg);
        border-style: dashed;
        border-color: var(--border-input);
        background: transparent;
        box-shadow: none;
        opacity: 0.7;
    }

    .info-card--deprecated:hover {
        opacity: 1;
    }

    /* LE TITRE A CHEVAL SUR LA BORDURE, comme la legende d'un cadre : il nomme la zone sans
       lui prendre une ligne. */
    .info-card--deprecated .deprecated-title {
        position: absolute;
        top: -0.7em;
        left: var(--space-md);
        padding: 0 var(--space-xs);
        background: var(--page-bg);
        font-size: var(--font-2xs);
        font-variant: small-caps;
        letter-spacing: 0.06em;
        font-weight: 600;
        color: var(--text-muted);
    }

/* ============================================
   BASE STYLES — ASSIMIL BACK-OFFICE
   Uses CSS variables defined in style.css :root
   ============================================ */

/* FONT STACK */
body,
input, select, textarea {
    font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-size: 14px;
}

h1, h2, h3, h4, h5, h6 {
    line-height: 1.1;
}

/* BASE LAYOUT */

html {
    background-color: var(--page-bg);
    height: 100%;
    box-sizing: border-box;
}

html * {
    margin: 0;
}

body {
    background: var(--page-bg);
    color: var(--text-body);
    margin: 0;
    max-width: none;
    overflow-x: hidden;
}

.formFieldset {
    padding: var(--space-lg);
    border: 1px solid var(--border-color) !important;
    border-radius: var(--radius-md);
}

a:link, a:visited, a:hover {
    color: var(--text-link);
}

a:hover, a:active {
    outline: none;
}

h1 {
    color: var(--text-primary);
    font-weight: 400;
    font-size: 1.8em;
    margin: 0.6em 0 0.3em 0;
}

ul {
    padding: 0;
}

img {
    border: 0;
}

/* GENERAL */

.content h1 {
    border-bottom: 1px solid var(--border-input);
    margin: 0.6em 1em 1em;
    padding: 0 0.25em;
}

.content p {
    margin: 0.6em 1em 1em;
    padding: 0 0.25em;
}

.content table {
    margin-top: 1.5em;
}

th {
    background-color: var(--bg-subtle);
}

table .btn {
    padding: 2px 0;
}

.scaffold-list h1 {
    border: none;
}

.footer {
    background: var(--border-color);
    color: var(--text-secondary);
    clear: both;
    font-size: 0.8em;
    margin-top: 1em;
    padding: 0.5em 1em;
    min-height: 0.5em;
}

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

.spinner {
    position: fixed;
    top: var(--space-lg);
    right: var(--space-lg);
    z-index: 9999;
    color: var(--color-primary);
    font-size: 42px;
}

.spinner i {
    display: block;
    animation: spin 0.8s linear infinite;
}

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

/* FORMS */

fieldset,
.property-list {
    margin: 0.4em 1em 0 1em;
    padding: 0.3em 1.2em 1em;
    position: relative;
    zoom: 1;
    border: none;
}

.property-list .fieldcontain {
    list-style: none;
    overflow: hidden;
    zoom: 1;
}

.fieldcontain {
    margin-top: 0.8em;
}

.fieldcontain label,
.fieldcontain .property-label {
    color: var(--text-secondary);
    text-align: right;
    width: 25%;
    font-size: var(--font-base);
}

.fieldcontain .property-label {
    float: left;
}

.fieldcontain .property-value {
    display: block;
    margin-left: 27%;
}

label {
    cursor: pointer;
    display: inline-block;
    margin: 0 0.25em 0 0;
    font-size: var(--font-base);
}

/* PILL-SHAPED FORM CONTROLS */
input, select, textarea {
    background-color: var(--card-bg);
    font-size: var(--font-md);
    padding: 0.5em 1em;
    border: 1px solid var(--border-input);
    border-radius: var(--radius-pill);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

input:focus, select:focus, textarea:focus {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-focus);
    outline: none;
}

/* Bootstrap form-control override for pill shape */
.form-control, .form-select {
    border-radius: var(--radius-pill) !important;
    padding: 0.45em 1.2em !important;
    font-size: var(--font-base) !important;
    border-color: var(--border-input) !important;
}

/* Select needs extra right padding for dropdown arrow */
select.form-select:not([multiple]):not([size]),
select:not([multiple]):not([size]) {
    padding-right: 3em !important;
    background-position: right 1em center;
}

.form-control:focus, .form-select:focus {
    border-color: var(--color-primary) !important;
    box-shadow: var(--shadow-focus) !important;
}

/* Floating labels need adjustment for pill shape */
.form-floating > .form-control,
.form-floating > .form-select {
    border-radius: var(--radius-pill) !important;
    padding: 1em 1.2em 0.4em !important;
}

.form-floating > label {
    padding-left: 1.2em;
}

/* Textarea should NOT be pill-shaped */
textarea,
textarea.form-control {
    border-radius: var(--radius-lg) !important;
}

/* Multi-select and sized selects should NOT be pill-shaped */
.form-select[multiple],
.form-select[size]:not([size="1"]),
select[multiple] {
    border-radius: var(--radius-lg) !important;
    vertical-align: top;
}

select {
    padding: 0.4em 0.8em;
}

textarea {
    width: 250px;
    height: 120px;
    overflow: auto;
    vertical-align: top;
}

.required-indicator {
    color: var(--color-primary);
    display: inline-block;
    font-weight: bold;
    margin-left: 0.3em;
    position: relative;
    top: 0.1em;
}

/* EMBEDDED PROPERTIES */

fieldset.embedded {
    background-color: transparent;
    border: 1px solid var(--border-color);
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
    box-shadow: none;
    border-radius: var(--radius-md);
}

fieldset.embedded legend {
    margin: 0 1em;
}

/* MESSAGES AND ERRORS */

.errors,
.message {
    font-size: var(--font-base);
    line-height: 1.8;
    margin: 0.8em 0;
    padding: 0.25em;
    border-radius: var(--radius-md);
    overflow-wrap: anywhere;
    word-break: break-word;
}

.message {
    background: var(--color-info-bg);
    border: 1px solid var(--color-info-border);
    color: var(--color-info-text);
    padding: 10px 14px;
}

.errors {
    background: var(--color-error-bg);
    border: 1px solid var(--color-error-border);
    color: var(--color-error);
    padding: 10px 14px;
    white-space: pre-wrap;
}

.errors ul,
.message {
    padding: 0;
}

.errors li {
    padding-left: 2em;
    list-style-type: none;
    list-style: none;
}

.errors li:before {
    font-family: 'FontAwesome';
    content: "\f071";
    color: var(--color-error);
    margin-right: 10px;
}

.message {
    padding-left: 1.5em;
}

/* form fields with errors */

.error input, .error select, .error textarea {
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
    color: var(--color-error-text);
}

.error input:focus, .error select:focus, .error textarea:focus {
    box-shadow: 0 0 0 3px rgba(252, 165, 165, 0.3);
}

input:invalid, select:invalid, textarea:invalid {
    background: var(--color-error-bg);
    border-color: var(--color-error-border);
    color: var(--color-error-text);
}

input:invalid:focus, select:invalid:focus, textarea:invalid:focus {
    box-shadow: 0 0 0 3px rgba(252, 165, 165, 0.3);
}

/* TABLES */

table {
    width: 100%;
    margin-bottom: 0.8em;
}

tr {
    border: 0;
}

tr > td:first-child, tr > th:first-child {
    padding-left: 1em;
}

tr > td:last-child, tr > th:last-child {
    padding-right: 1em;
}

td, th {
    line-height: 1.4em;
    padding: 0.4em 0.5em;
    text-align: left;
    vertical-align: top;
}

th {
    color: var(--text-secondary);
    font-weight: 600;
    line-height: 1.5em;
    padding: 0.3em 0.5em;
    font-size: var(--font-sm);
}

thead th {
    white-space: nowrap;
}

th a {
    display: block;
    text-decoration: none;
}

th a:link, th a:visited {
    color: var(--text-secondary);
}

th a:hover, th a:focus {
    color: var(--text-primary);
}

th.sortable a {
    background-position: right;
    background-repeat: no-repeat;
}

th.asc a {
    background-image: url(skin/sorted_asc-d4a12261579f19fd589cc94bdb1756a5.svg);
}

th.desc a {
    background-image: url(skin/sorted_desc-282b731c420ec8fedbe9439ce440024c.svg);
}

.odd {
    background: var(--bg-subtle);
}

.even {
    background: var(--card-bg);
}

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

/* PAGINATION */

.pagination {
    border-top: 0;
    margin: 0;
    padding: 0.3em 0.2em;
    text-align: center;
    background-color: var(--bg-subtle);
    border-radius: var(--radius-sm);
}

.pagination a,
.pagination .currentStep {
    color: var(--text-secondary);
    display: inline-block;
    margin: 0 0.1em;
    padding: 0.2em 0.6em;
    text-decoration: none;
    border-radius: var(--radius-xs);
}

.pagination a:hover, .pagination a:focus,
.pagination .currentStep {
    background-color: var(--color-primary);
    color: var(--text-on-primary);
    outline: none;
}

/* ACTION BUTTONS */

.buttons {
    border-top: solid 1px var(--border-color);
    overflow: hidden;
    padding: 0.3em;
    margin: 0.1em 0 0 0;
    border: none;
}

.buttons input,
.buttons a,
.buttons button {
    float: right;
    background-color: var(--color-danger);
    border: 0;
    color: var(--text-on-primary);
    cursor: pointer;
    display: inline-block;
    font-family: inherit;
    margin: 0;
    overflow: visible;
    padding: 0.35em 1em;
    text-decoration: none;
    border-radius: var(--radius-pill);
    margin-right: var(--space-md);
    font-size: var(--font-base);
}

.buttons input:hover, .buttons input:focus,
.buttons a:hover, .buttons a:focus,
.buttons button:hover, .buttons button:focus {
    background-color: var(--color-danger-light);
    color: var(--text-on-primary);
    outline: none;
}

a.skip {
    position: absolute;
    left: -9999px;
}

/* LOGIN PAGE */

.login_page {
    margin-left: auto;
    margin-right: auto;
    width: 320px;
}

.login_page h1 {
    margin: var(--space-2xl) 0;
}

.login_page input {
    width: 100%;
    margin-top: 5px;
    margin-bottom: var(--space-lg);
}

.login_page .submit_button,
.login_page .btn,
.login_page button[type="submit"] {
    margin-top: 10px;
    width: 100%;
    background-color: var(--color-primary);
    border: none;
    padding: 10px 15px;
    color: var(--text-on-primary);
    border-radius: var(--radius-pill) !important;
    font-weight: 600;
    font-size: var(--font-base);
}

/* MISC */

.form-info {
    font-size: 0.8em;
    color: var(--text-muted);
}

.large-label-form .fieldcontain label {
    width: 50%;
}

.legende {
    display: inline-block;
    float: right;
    margin-right: var(--space-xl);
    margin-bottom: var(--space-xl);
    padding: 10px;
    border: 1px solid var(--border-color);
    font-size: 0.8em;
    border-radius: var(--radius-md);
    background: var(--card-bg);
}

.legende h3 {
    font-size: 11px;
    margin-bottom: var(--space-sm);
    text-transform: uppercase;
}

.legende ul {
    list-style: none;
}

.legende li {
    vertical-align: middle;
    margin-bottom: var(--space-xs);
}

.legende li .description {
    vertical-align: top;
    padding-left: var(--space-sm);
}

.legende_item {
    height: 18px;
    width: 18px;
    display: inline-block;
}

.legende_label {
    padding: var(--space-xs) var(--space-sm);
    margin-right: var(--space-xs);
}

h3.formSection {
    border-bottom: 1px solid var(--border-color);
    font-weight: normal;
    font-size: var(--font-base);
}

h4.formSection {
    margin-top: 10px;
    margin-bottom: 6px;
}

.whatsnew-html h5 {
    font-size: larger;
    margin-bottom: 6px;
    margin-top: var(--space-md);
}

.whatsnew-html h6 {
    font-size: 10pt;
    margin-bottom: 6px;
    margin-top: var(--space-md);
}

input:-webkit-autofill:focus {
    background-color: rgba(126, 214, 223, 0.17) !important;
}

h1, h2, h3 {
    margin-top: 10px;
    margin-bottom: 5px;
}

h2 {
    font-size: 1.1em;
}

.filename {
    font-style: italic;
}

.exceptionMessage {
    margin: 10px;
    border: 1px solid #000;
    padding: 5px;
    background-color: #E9E9E9;
}

.stack,
.snippet {
    margin: 0 25px 10px;
}

.stack,
.snippet {
    border: 1px solid #ccc;
    -mox-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
}

/* error details */
.error-details {
    border-top: 1px solid #FFAAAA;
    -mox-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    border-bottom: 1px solid #FFAAAA;
    -mox-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
    background-color: #FFF3F3;
    line-height: 1.5;
    overflow: hidden;
    padding: 5px;
    padding-left: 25px;
}

.error-details dt {
    clear: left;
    float: left;
    font-weight: bold;
    margin-right: 5px;
}

.error-details dt:after {
    content: ":";
}

.error-details dd {
    display: block;
}

/* stack trace */
.stack {
    padding: 5px;
    overflow: auto;
    height: 150px;
}

/* code snippet */
.snippet {
    background-color: #fff;
    font-family: monospace;
}

.snippet .line {
    display: block;
}

.snippet .lineNumber {
    background-color: #ddd;
    color: #999;
    display: inline-block;
    margin-right: 5px;
    padding: 0 3px;
    text-align: right;
    width: 3em;
}

.snippet .error {
    background-color: #fff3f3;
    font-weight: bold;
}

.snippet .error .lineNumber {
    background-color: #faa;
    color: #333;
    font-weight: bold;
}

.snippet .line:first-child .lineNumber {
    padding-top: 5px;
}

.snippet .line:last-child .lineNumber {
    padding-bottom: 5px;
}
/* ============================================
   ASSIMIL BACK-OFFICE - MODERN SIDEBAR LAYOUT
   Variables are defined in theme.css
   ============================================ */

body, input, select, textarea, button, a, h1, h2, h3, h4, h5, h6, p, span, div, li, td, th, label {
    font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* ============================================
   SIDEBAR
   ============================================ */

.app-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--sidebar-width);
    background-color: var(--sidebar-bg);
    z-index: 1040;
    overflow-y: auto;
    overflow-x: hidden;
    transition: width var(--transition-normal);
    display: flex;
    flex-direction: column;
}

/* Collapsed state - icons only */
.app-sidebar.collapsed {
    width: var(--sidebar-collapsed-width);
}

.sidebar-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-sm);
    min-height: var(--header-height);
}

/* "MENU" label in header */
.sidebar-menu-label {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 1.5px;
    color: var(--text-primary);
    text-transform: uppercase;
}

.app-sidebar.collapsed .sidebar-menu-label {
    display: none;
}

.sidebar-env-badge {
    background-color: var(--color-primary);
    color: var(--text-on-primary);
    font-size: var(--font-2xs);
    padding: 2px var(--space-sm);
    border-radius: var(--radius-pill);
    text-transform: uppercase;
    font-weight: 600;
    letter-spacing: 0.5px;
    transition: opacity var(--transition-fast);
}

.app-sidebar.collapsed .sidebar-env-badge {
    opacity: 0;
    width: 0;
    padding: 0;
    overflow: hidden;
}

.sidebar-nav {
    list-style: none;
    padding: var(--space-sm) 0;
    margin: 0;
    flex: 1;
}

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

.sidebar-menu-item {
    position: relative;
}

.sidebar-menu-item > a,
.sidebar-menu-item > .sidebar-menu-toggle {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px var(--space-lg);
    color: var(--sidebar-text);
    text-decoration: none;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    font-weight: 500;
    transition: background-color var(--transition-fast), color var(--transition-fast);
    cursor: pointer;
    border: none;
    background: none;
    width: 100%;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
}

.app-sidebar.collapsed .sidebar-menu-item > a,
.app-sidebar.collapsed .sidebar-menu-item > .sidebar-menu-toggle {
    padding: 14px 0;
    justify-content: center;
    gap: 0;
}

.sidebar-menu-item > a:hover,
.sidebar-menu-item > .sidebar-menu-toggle:hover {
    background-color: var(--sidebar-hover);
    color: var(--sidebar-text-hover);
}

.sidebar-menu-item > a:link,
.sidebar-menu-item > a:visited {
    color: var(--sidebar-text);
}

.sidebar-menu-item > a:hover {
    color: var(--sidebar-text-hover);
}

/* Icon styling - Phosphor outline icons */
.sidebar-menu-item > a i.ph,
.sidebar-menu-toggle i.ph:first-child {
    width: 24px;
    text-align: center;
    font-size: 1.35rem;
    color: var(--text-secondary);
    flex-shrink: 0;
    transition: color var(--transition-fast);
}

/* Label text - hidden when collapsed */
.sidebar-menu-item > a > span,
.sidebar-menu-toggle > span {
    transition: opacity var(--transition-fast);
}

.app-sidebar.collapsed .sidebar-menu-item > a > span,
.app-sidebar.collapsed .sidebar-menu-toggle > span {
    display: none;
}

/* Submenu arrow - hidden when collapsed */
.submenu-arrow {
    margin-left: auto;
    font-size: 0.7rem !important;
    transition: transform 0.2s, color var(--transition-fast);
    color: var(--text-muted) !important;
    flex-shrink: 0;
}

.app-sidebar.collapsed .submenu-arrow {
    display: none;
}

.sidebar-menu-item.has-submenu.open > .sidebar-menu-toggle .submenu-arrow {
    transform: rotate(90deg);
}

/* ---- Active menu item ---- */
.sidebar-menu-item.active > a,
.sidebar-menu-item.active > .sidebar-menu-toggle {
    color: var(--sidebar-text-hover);
}

.sidebar-menu-item.active > a i.ph,
.sidebar-menu-item.active > .sidebar-menu-toggle i.ph:first-child {
    color: var(--color-logo);
}

/* Active indicator - small round dot, only for items without submenu */
.sidebar-menu-item.active:not(.has-submenu)::before {
    content: '';
    position: absolute;
    left: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 6px;
    height: 6px;
    background-color: var(--color-logo);
    border-radius: 50%;
}

/* Active indicator - dot next to active submenu item, centered under parent icon */
.sidebar-submenu li.active::before {
    content: '';
    position: absolute;
    left: 28px;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 6px;
    height: 6px;
    background-color: var(--color-logo);
    border-radius: 50%;
}

.sidebar-submenu li {
    position: relative;
}

/* Sub-menu */
.sidebar-submenu {
    list-style: none;
    padding: 0;
    margin: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--transition-normal);
    background-color: var(--sidebar-submenu-bg);
}

.sidebar-menu-item.has-submenu.open > .sidebar-submenu {
    max-height: 500px;
}

/* Hide submenu when sidebar is collapsed */
.app-sidebar.collapsed .sidebar-submenu {
    max-height: 0 !important;
}

.sidebar-submenu li a,
.sidebar-submenu li a:link,
.sidebar-submenu li a:visited {
    display: block;
    padding: 6px var(--space-lg) 6px 44px;
    color: var(--sidebar-text);
    text-decoration: none;
    font-size: var(--font-sm);
    transition: color var(--transition-fast), background-color var(--transition-fast);
}

.app-sidebar.collapsed .sidebar-submenu li a {
    padding-left: var(--space-lg);
}

.sidebar-submenu li a:hover {
    color: var(--sidebar-text-hover);
    background-color: var(--sidebar-hover);
}

.sidebar-submenu li.active a,
.sidebar-submenu li.active a:link,
.sidebar-submenu li.active a:visited {
    color: var(--color-logo);
    font-weight: 600;
}

/* ---- Sidebar footer with collapse toggle ---- */
.sidebar-collapse-btn {
    background: none;
    border: none;
    color: var(--sidebar-text);
    cursor: pointer;
    padding: var(--space-sm) var(--space-md);
    opacity: 0.6;
    transition: opacity var(--transition-fast);
    font-size: 1.1rem;
}

.sidebar-collapse-btn:hover {
    opacity: 1;
}

/* ---- Tooltip on hover when collapsed ---- */
.app-sidebar.collapsed .sidebar-menu-item > a,
.app-sidebar.collapsed .sidebar-menu-item > .sidebar-menu-toggle {
    position: relative;
}

.app-sidebar.collapsed .sidebar-menu-item > a::after,
.app-sidebar.collapsed .sidebar-menu-item > .sidebar-menu-toggle::after {
    content: attr(data-tooltip);
    position: absolute;
    left: calc(var(--sidebar-collapsed-width) + 6px);
    top: 50%;
    transform: translateY(-50%);
    background: var(--text-primary);
    color: var(--text-on-primary);
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    font-size: var(--font-xs);
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast);
    z-index: 1050;
    box-shadow: var(--shadow-md);
}

.app-sidebar.collapsed .sidebar-menu-item > a:hover::after,
.app-sidebar.collapsed .sidebar-menu-item > .sidebar-menu-toggle:hover::after {
    opacity: 1;
}

/* ============================================
   TOP HEADER
   ============================================ */

.top-header {
    height: var(--header-height);
    background: var(--card-bg);
    border-bottom: none;
    display: flex;
    align-items: center;
    padding: 0 var(--space-xl);
    gap: var(--space-md);
    position: sticky;
    top: 0;
    z-index: 1030;
}

.top-header-logo {
    display: flex;
    align-items: center;
    text-decoration: none;
    gap: var(--space-sm);
}

/* SVG logo sizing and coloring */
.top-header-logo .logo-svg {
    height: var(--logo-height);
    width: auto;
    color: var(--color-logo);
}

/* On login page (no-sidebar), make logo larger */
.main-wrapper.no-sidebar .top-header-logo .logo-svg {
    height: var(--logo-height-login);
}

/* "Back-office" text next to logo */
.header-bo-text {
    color: var(--text-primary);
    font-weight: 500;
    font-size: var(--font-sm);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.top-header .mainTitle {
    background-color: var(--color-primary);
    color: var(--text-on-primary);
    padding: 2px var(--space-sm);
    border-radius: var(--radius-pill);
    font-size: var(--font-2xs);
    text-transform: uppercase;
    font-weight: 600;
    float: none;
    margin: 0;
}

/* Sidebar SVG logo */
.sidebar-header .logo-svg {
    height: var(--logo-height-sidebar);
    width: auto;
    color: var(--color-logo);
}

.sidebar-toggle-btn {
    display: none; /* hidden on desktop */
    background: none;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 6px 10px;
    font-size: var(--font-lg);
    color: var(--text-primary);
    cursor: pointer;
}

.sidebar-toggle-btn:hover {
    background-color: var(--page-bg);
}

.top-header-user {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.headerUserInfo {
    color: var(--text-secondary);
    font-size: 0.8rem;
    text-transform: uppercase;
    font-weight: 500;
}

.header-logout-btn,
.header-logout-btn:link,
.header-logout-btn:visited {
    color: var(--text-secondary);
    font-size: var(--font-sm);
    text-decoration: none;
    padding: var(--space-xs) 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    transition: all var(--transition-fast);
}

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

/* ============================================
   MAIN WRAPPER & PAGE CONTENT
   ============================================ */

.main-wrapper {
    margin-left: var(--sidebar-width);
    min-height: 100vh;
    background-color: var(--page-bg);
    display: flex;
    flex-direction: column;
    transition: margin-left var(--transition-normal);
}

/* When sidebar is collapsed */
.main-wrapper.sidebar-collapsed {
    margin-left: var(--sidebar-collapsed-width);
}

.page-content {
    flex: 1;
    padding: var(--space-xl);
}

/* When no sidebar (login page) */
.main-wrapper.no-sidebar {
    margin-left: 0;
}

.main-wrapper.no-sidebar .top-header {
    justify-content: center;
}

.main-wrapper.no-sidebar .sidebar-toggle-btn {
    display: none;
}

.main-wrapper.no-sidebar .top-header-logo {
    display: flex;
}

/* Login page */
.main-wrapper.no-sidebar .top-header {
    padding-top: var(--space-xl);
    background-color: var(--card-bg);
}

.main-wrapper.no-sidebar .content-area {
    background-color: var(--card-bg);
}

.login_page {
    max-width: 400px;
    margin: 40px auto 0;
    background: var(--card-bg);
    border-radius: var(--radius-lg);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
    padding: var(--space-xl) var(--space-xl) var(--space-lg);
}

.login_page h1 {
    font-weight: 300 !important;
    font-size: 1.5rem;
    text-align: center;
    letter-spacing: 1px;
    color: var(--text-primary);
    margin-bottom: var(--space-xl);
}

.login_page .form-control {
    border: none;
    border-bottom: 1px solid var(--border-light);
    border-radius: 0;
    padding-left: 0;
    background: transparent;
    font-size: 0.95rem;
}

.login_page .form-control:focus {
    box-shadow: none;
    border-bottom-color: var(--color-primary);
}

.login_page .form-floating label {
    padding-left: 0;
    color: var(--text-muted);
}

.login_page .btn-theme {
    width: 100%;
    padding: 12px;
    font-size: 1rem;
    letter-spacing: 0.5px;
    margin-top: var(--space-md);
}

/* Overlay for mobile */
.sidebar-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0.4);
    z-index: 1035;
}

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

/* ============================================
   BUTTONS
   ============================================ */

.custom-form div {
    margin-bottom: var(--space-md);
}

a.btn, a.btn:link, a.btn:visited, a.btn:hover {
    color: var(--text-on-primary);
    text-decoration: none;
    border-radius: var(--radius-pill);
}

.btn {
    color: var(--text-on-primary);
    border-radius: var(--radius-pill) !important;
    font-size: 0.8rem;
}

.btn-theme, .btn-theme-secondary {
    border-radius: var(--radius-pill) !important;
}

.btn-theme:hover {
    background-color: var(--color-primary-lighter) !important;
    border-color: var(--color-primary-lighter) !important;
}

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

.checkbox-label {
    padding-left: 10px;
    padding-top: 3px;
}

.form-check-label {
    padding-left: 10px;
}

.btn-theme {
    background-color: var(--color-primary-light);
    border-color: var(--color-primary-light);
}

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

.btn-sm .ph {
    font-size: 1.3em;
    vertical-align: middle;
}

.btn-smart-width {
    width: auto;
    padding: var(--space-xs) 10px;
}

.icon-btn {
    width: 35px;
    height: 35px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 !important;
}

.icon-btn .ph {
    font-size: 1.3em;
}

/* ---- Warning banner ---- */
.warning-banner {
    padding: var(--space-md) var(--space-lg);
    background: rgba(var(--color-primary-rgb), 0.08);
    border: 1px solid rgba(var(--color-primary-rgb), 0.3);
    border-radius: 8px;
    font-size: 0.9em;
}

.btn-default {
    background-color: var(--color-success);
    border-color: var(--color-success);
}

.btn-theme-success {
    background-color: var(--color-green);
    border-color: var(--color-green);
    color: var(--text-on-primary);
}

.btn-theme-success:hover,
.btn-theme-success:active {
    background-color: var(--color-green);
    border-color: var(--color-green);
    color: var(--text-on-primary);
    filter: brightness(1.1);
}

table .btn {
    padding-left: var(--space-sm) !important;
    padding-right: var(--space-sm) !important;
    font-size: 0.8em !important;
}

.btn-theme.active {
    background-color: var(--color-danger-light);
    border-color: var(--color-danger-light);
}

.btn-primary:hover,
.btn-primary:active,
.btn-outline-primary:hover,
.btn-outline-primary:active {
    background-color: var(--color-primary-lighter);
    border-color: var(--color-primary-lighter);
    color: var(--text-on-primary);
}

/* ============================================
   TABLES - compact
   ============================================ */

.list {
    padding: 0;
}

.list table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: white;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}

/* Hide table header when no results */
.list table:not(:has(tbody tr)) thead {
    display: none;
}

.list table thead {
    background: var(--sidebar-submenu-bg);
}

.list table thead th,
.list table thead td {
    padding: var(--space-md) var(--space-lg);
    border-bottom: 2px solid var(--border-light);
    font-size: var(--font-base);
}

.list table tbody tr {
    transition: background-color var(--transition-fast);
}

.list table tbody tr:hover {
    background-color: rgba(var(--color-primary-rgb), 0.03);
}

.list table tbody tr {
    position: relative;
}

.list table tbody tr:not(:last-child)::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: var(--space-2xl);
    right: var(--space-2xl);
    height: 1px;
    background-color: transparent;
}

.list table tbody td {
    padding: var(--space-sm) var(--space-lg);
    vertical-align: top;
    font-size: 0.95rem;
    line-height: 1.6;
}

/* Extra padding on first/last cells for card-like spacing */
.list table thead th:first-child,
.list table thead td:first-child,
.list table tbody td:first-child {
    padding-left: var(--space-2xl);
}

.list table thead th:last-child,
.list table thead td:last-child,
.list table tbody td:last-child {
    padding-right: var(--space-2xl);
}

.list table tbody td ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.list table tbody td ul li {
    padding: 1px 0;
}

/* ---- Icon colors in table ----
   Applies to both the legacy `.list table` container and the newer `.list-section` / `.list-table`. ---- */
.list table .icon-email,
.list-section .icon-email {
    color: var(--text-secondary);
}

.list table .icon-user,
.list-section .icon-user {
    color: var(--color-primary-light);
}

.list table .icon-book,
.list-section .icon-book {
    color: var(--color-primary);
    font-size: 1.15em;
}

.list table .icon-globe,
.list-section .icon-globe {
    color: var(--color-info);
}

.list table .icon-link,
.list-section .icon-link {
    color: var(--color-primary);
    font-size: 16px;
}

.list table .icon-payment,
.list-section .icon-payment {
    color: var(--color-primary);
}

.list table .icon-credit-card,
.list-section .icon-credit-card {
    color: var(--color-secondary);
}

.list table .icon-tag,
.list-section .icon-tag {
    color: var(--color-secondary);
}

.list table .icon-warning,
.list-section .icon-warning {
    color: var(--color-warning);
}

.list table .icon-shield,
.list-section .icon-shield {
    color: var(--color-purple);
}

.list table .icon-db,
.list-section .icon-db {
    color: var(--text-muted);
}

/* ---- SKU link ---- */
.list table .sku-link,
.list-section .sku-link {
    color: var(--color-primary);
    font-weight: 600;
    font-size: 1em;
}

.list table .sku-link:hover,
.list-section .sku-link:hover {
    color: var(--color-primary-light);
}

/* ---- Copy button ---- */
.btn-copy {
    display: inline-block;
    background: none;
    border: none;
    cursor: pointer;
    padding: 2px 4px;
    opacity: 0.7;
    transition: opacity 0.2s;
    vertical-align: middle;
}

.list table .btn-copy .fa,
.list-section .btn-copy .fa,
.btn-copy .fa,
.btn-copy .ph {
    color: var(--color-primary) !important;
    font-size: 0.9em;
    pointer-events: none;
}

.btn-copy:hover {
    opacity: 1;
}

/* ---- Price ---- */
.list table .price,
.list-section .price {
    color: var(--text-primary);
    font-weight: 600;
}

/* ---- Muted info ---- */
.list table .info-muted,
.list-section .info-muted {
    color: var(--text-muted);
    font-size: 0.85em;
}

.list table .info-lang,
.list-section .info-lang {
    font-size: 0.8em;
    color: var(--text-secondary);
}

/* ---- Date ---- */
.list table .info-date {
    color: var(--text-secondary);
    font-size: 0.8em;
    margin-top: 6px;
}

/* ---- Refund date ---- */
.list table .refund-date {
    color: var(--color-danger);
    font-weight: 600;
}

/* ---- Separator ---- */
.separator {
    color: var(--text-muted);
    margin: 0 2px;
}

/* ---- Badges inline ---- */
.badge-status {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.7em;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.badge-status .ph {
    font-size: 1.4em;
    vertical-align: middle;
}

.badge-purchase {
    background-color: rgba(var(--color-primary-rgb), 0.12);
    color: var(--color-primary);
}

.badge-trial {
    background-color: rgba(var(--color-primary-rgb), 0.06);
    color: rgba(var(--color-primary-rgb), 0.6);
}

.badge-active, .badge-completed, .badge-validated {
    background-color: rgba(46, 204, 113, 0.12);
    color: var(--color-green);
}

.badge-revoked, .badge-refunded {
    background-color: rgba(255, 71, 87, 0.1);
    color: var(--color-danger);
}

/* LA SUGGESTION ET LE BOUTON QUI L'APPLIQUE PARTAGENT LEUR COULEUR, et la tiennent d'ici :
   recopier la teinte des deux cotes les laisse diverger a la premiere retouche. La pastille
   est la teinte posee, le bouton la teinte pleine — c'est la meme decision, dite deux fois.
   Rouge parce que la seule suggestion qui AGISSE est une revocation : le bouton doit
   ressembler a ce qu'il fait. */
/* ---- Tons du badge de statut ------------------------------------------------
   Les couleurs etaient recopiees en style inline dans chaque branche de la vue des
   suspects. Elles vivent ici, et `SuspectStatus.tone` designe celle qui s'applique. */
.badge-status--warning {
    background: rgba(var(--color-warning-rgb, 255, 193, 7), 0.12);
    color: var(--color-warning);
}

.badge-status--danger {
    background: rgba(255, 71, 87, 0.12);
    color: var(--color-danger);
}

.badge-status--green {
    background: rgba(46, 204, 113, 0.12);
    color: var(--color-green);
}

.badge-status--muted {
    background: rgba(0, 0, 0, 0.06);
    color: var(--text-muted);
}

.badge-suggest-revoke {
    background-color: rgba(255, 71, 87, 0.12);
    color: var(--color-danger);
}

.btn-suggest-revoke,
.btn-suggest-revoke:hover,
.btn-suggest-revoke:focus {
    background-color: var(--color-danger);
    border-color: var(--color-danger);
    color: #fff;
}

.badge-hacked {
    background-color: #1a1a1a;
    color: #fff;
    font-weight: 600;
}

a.btn-bulk-revoke,
a.btn-bulk-revoke:visited,
a.btn-bulk-revoke:active {
    text-decoration: none;
    cursor: pointer;
    color: #fff !important;
    transition: opacity 0.2s;
}
a.btn-bulk-revoke:hover {
    opacity: 0.75;
    color: #fff !important;
}

.badge-pending, .badge-preparation {
    background-color: rgba(230, 126, 51, 0.12);
    color: var(--color-warning);
}

/* Contenu migré (ressource XML avec oldFtpPath) : déjà transformé, pas de (re)génération */
.badge-migrated {
    background-color: var(--bg-subtle);
    color: var(--text-secondary);
}

/* Colonne « diffusion du catalogue » (Firestore) : teinte info pour la distinguer des
   plateformes de paiement (Google Play / App Store / Stripe). */
.col-catalog {
    background-color: var(--bg-catalog);
}

/* Usage d'un contenu par un article : production (vert) vs test (orange) */
.badge-prod {
    background-color: rgba(46, 204, 113, 0.12);
    color: var(--color-green);
}

.badge-test {
    background-color: rgba(230, 126, 51, 0.12);
    color: var(--color-warning);
}

/* Panneau expliquant pourquoi un contenu brut n'est pas supprimable (au clic sur la corbeille) */
.delete-reason-panel {
    margin-top: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    max-width: 340px;
    background-color: var(--color-error-bg);
    border: 1px solid var(--color-error-border);
    border-radius: var(--radius-md);
    color: var(--color-error-text);
    font-size: var(--font-sm);
    text-align: left;
}

.delete-reason-title {
    font-weight: 600;
    margin-bottom: var(--space-xs);
}

.delete-reason-title .ph {
    vertical-align: middle;
}

.delete-reason-list {
    margin: 0 0 var(--space-xs);
    padding-left: var(--space-lg);
}

.delete-reason-list li {
    margin-bottom: 4px;
}

.delete-reason-hint {
    font-style: italic;
    color: var(--text-secondary);
}

/* ---- Popups du back-office ---------------------------------------------------
   UNE SEULE FACON DE FERMER : la croix en haut a droite. Elle etait jusqu'ici un bouton
   « Fermer » ici, un clic sur le fond la, un lien ailleurs — trois gestes a apprendre pour
   une seule action. `<dialog>` natif : Echap ferme aussi, sans une ligne de script.

   ⚠️ `margin: auto` EST OBLIGATOIRE. Le reset de la page met `margin: 0` sur tout, ce qui
   ecrase la valeur que le navigateur pose sur `dialog:modal` — la bulle s'ancrait alors en
   haut a gauche au lieu d'etre centree. */
.bo-dialog {
    position: fixed;
    /* Un dialogue ouvert depuis une cellule en `nowrap` en hériterait : le texte y va à la ligne. */
    white-space: normal;
    margin: auto;
    max-width: 44em;
    max-height: 85vh;
    overflow-y: auto;
    border: none;
    border-radius: var(--radius-md, 8px);
    padding: var(--space-lg, 1.5rem) var(--space-xl, 2rem) var(--space-lg, 1.5rem);
    color: var(--text-primary);
    background: var(--bg-card, #fff);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
}


/* UN DIALOGUE LARGE, pour ce qui se compare côte à côte. Les 44em du dialogue ordinaire sont
   faits pour un texte qu'on lit ; deux versions de paroles en colonnes ont besoin du double.
   `min()` garde la fenêtre dans l'écran : sur un portable, elle reprend toute la largeur moins
   les marges, et les colonnes s'empilent d'elles-mêmes. */
.bo-dialog.bo-dialog-wide {
    max-width: min(94vw, 72em);
    width: min(94vw, 72em);
}

.bo-dialog::backdrop {
    background: rgba(0, 0, 0, 0.35);
}

.bo-dialog h2 {
    margin: 0 2em 0 0;
}

.bo-dialog-close-form {
    float: right;
    margin: 0;
}

.bo-dialog-close {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--text-muted);
    line-height: 1;
}

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

.bo-dialog-close .ph {
    font-size: 1.5em;
}

/* Un dialogue dont le contenu défile : l'en-tête reste, le corps glisse dessous. La séparation
   se fait par le blanc et le fond, jamais par un trait. */
/* [open] EST OBLIGATOIRE. Un <dialog> ferme est `display: none` par la feuille du navigateur ;
   une regle d'auteur qui pose `display` l'ecrase, et la bulle reste affichee en permanence —
   la croix retire bien `open`, mais plus rien ne le lit. Constate le 10/09/2026 : les mots
   nouveaux s'affichaient sans qu'on ait clique, et ne se fermaient pas. */
.bo-dialog.bo-dialog-scroll[open] {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding-top: 0;
    padding-bottom: 0;
}

.bo-dialog-header {
    display: flex;
    align-items: baseline;
    gap: var(--space-md, 1rem);
    justify-content: space-between;
    position: sticky;
    top: 0;
    z-index: 1;
    padding: var(--space-lg, 1.5rem) 0 var(--space-md, 1rem);
    background: var(--bg-card, #fff);
}

.bo-dialog-header .bo-dialog-close {
    flex: none;
}

.bo-dialog-body {
    overflow-y: auto;
    padding-bottom: var(--space-lg, 1.5rem);
}

/* La phrase qui suffit la plupart du temps : elle se lit avant le reste. */
.bo-dialog-lead {
    margin: var(--space-sm, 0.75rem) 0 var(--space-md, 1rem);
    font-size: 1.05em;
    line-height: 1.5;
    color: var(--text-primary);
}

/* Les cas de figure : l'intitule porte le regard, le texte suit. */
.bo-dialog-points {
    margin: 0 0 var(--space-md, 1rem);
}

.bo-dialog-points dt {
    font-weight: 600;
    color: var(--color-primary);
    margin-top: var(--space-sm, 0.75rem);
}

.bo-dialog-points dd {
    margin: 2px 0 0;
    line-height: 1.45;
    color: var(--text-secondary);
}

/* La seule chose a retenir : ce bouton touche-t-il aux licences ? */
.bo-dialog-note {
    margin: 0;
    padding: var(--space-sm, 0.75rem);
    border-radius: var(--radius-sm, 4px);
    background: rgba(46, 204, 113, 0.1);
    color: var(--color-green);
    font-weight: 600;
    line-height: 1.4;
}

.bo-dialog-note--warning {
    background: rgba(var(--color-warning-rgb, 255, 193, 7), 0.14);
    color: var(--color-warning);
}

/* Le pied d'une popup est CENTRE. La croix en haut a droite ferme toujours ; quand une
   popup offre en plus un bouton en bas — « Fermer », ou « Annuler » a cote de son action —,
   il se place au milieu, et non colle a droite comme le veut Bootstrap. Une seule facon de
   presenter la sortie, quelle que soit la popup. */
.modal-footer,
.bo-dialog-actions {
    justify-content: center;
}

.bo-dialog-actions {
    display: flex;
    gap: var(--space-sm, 0.75rem);
    margin-top: var(--space-md, 1rem);
    /* `clear` a cause de la croix, qui flotte a droite en haut du dialogue : sans lui, la
       rangee du bas peut se retrouver contrainte par le flottant selon la hauteur du contenu. */
    clear: both;
}

/* ---- Aide d'un bouton : le « i » qui ouvre la bulle ---- */
.btn-help {
    background: none;
    border: none;
    padding: 0 0 0 2px;
    cursor: pointer;
    color: var(--text-muted);
    vertical-align: middle;
    line-height: 1;
}

.btn-help:hover {
    color: var(--color-primary);
}

.btn-help .ph {
    font-size: 1.15em;
}

/* ---- Les cartes du moteur ----------------------------------------------------
   Une carte par action, avec SES reglages dedans. Cinq controles alignes devant trois
   boutons laissaient croire qu'ils valaient pour tous : deux n'en lisaient qu'un. */
.engine-card {
    flex: 1 1 20em;
    min-width: 18em;
    border: 1px solid var(--border-color, #e2e8f0);
    border-left-width: 3px;
    border-radius: var(--radius-md, 8px);
    padding: var(--space-md, 1rem);
    background: var(--bg-card, #fff);
}

.engine-card-title {
    font-weight: 600;
    margin-bottom: 4px;
}

/* DEUX TEINTES POUR DEUX NATURES. A gauche ce qui ECRIT dans Firestore, a droite ce qui
   travaille la liste des suspects : la couleur separe les deux d'un coup d'oeil, la ou deux
   cartes blanches se lisaient comme deux variantes d'une meme chose. */
.engine-card--firestore {
    border-color: var(--color-primary);
    background: rgba(var(--color-primary-rgb), 0.05);
}

.engine-card--suspects {
    border-color: var(--color-warning);
    background: rgba(var(--color-warning-rgb, 255, 193, 7), 0.07);
}

/* ---- Les actions d'une section, a droite et HORS du formulaire de filtre ----
   Les deux boutons de scan etaient poses dans le <form> des filtres : ils passaient a la
   ligne au milieu des selects, et se soumettaient dans le meme geste que « Filtrer ».
   Une action n'est pas un critere de recherche. */
.section-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-sm, 0.75rem);
    margin-top: var(--space-sm, 0.75rem);
}

/* ---- Modals ---- */
.modal-body {
    padding: 1.5rem 2rem;
}

/* ---- Info tables (criteria, verification) ---- */
.table-sm td,
.table-sm th {
    border-color: #f0f0f0;
}

/* ---- Revoke button ---- */
.btn-revoke {
    display: inline-block;
    background-color: var(--color-purple) !important;
    color: var(--text-on-primary) !important;
    border: none !important;
    border-radius: var(--radius-sm);
    padding: 4px 10px;
    margin: 6px 0;
    font-size: 0.85em;
    text-decoration: none;
}

.btn-revoke .ph {
    color: var(--text-on-primary) !important;
}

.btn-revoke:hover {
    opacity: 0.85;
}

td.bordered {
    border-left: solid 1px var(--border-light);
    border-right: solid 1px var(--border-light);
    padding-left: var(--space-sm);
    padding-right: var(--space-sm);
}

table.innerTable td {
    line-height: 1.0em;
}

th {
    font-size: var(--font-sm);
    font-weight: 600;
    text-transform: uppercase;
    color: var(--text-secondary);
    letter-spacing: 0.3px;
}

th.sortable a {
    background: url(skin/sorted_asc-d4a12261579f19fd589cc94bdb1756a5.svg) no-repeat right top, url(skin/sorted_desc-282b731c420ec8fedbe9439ce440024c.svg) no-repeat right bottom;
}

th.desc a {
    background-image: url(skin/sorted_asc-d4a12261579f19fd589cc94bdb1756a5.svg);
}

th.asc a {
    background-image: url(skin/sorted_desc-282b731c420ec8fedbe9439ce440024c.svg);
}

/* ---- Details toggle icon ---- */
details summary::-webkit-details-marker {
    display: none;
}

details[open] > summary .content-toggle-icon {
    transform: rotate(90deg);
}

/* ---- Multi-line clamped message cell (max 2 lines + "voir plus" chevron) ---- */
.message-cell {
    max-width: 420px;
    display: flex;
    align-items: flex-start;
    gap: var(--space-xs);
}

.message-cell-text {
    white-space: normal;
    word-break: break-word;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    flex: 1 1 auto;
    line-height: 1.4;
}

.message-cell-expand {
    background: none;
    border: none;
    padding: 2px 4px;
    cursor: pointer;
    color: var(--color-primary);
    font-size: 1.2em;
    line-height: 1;
    flex-shrink: 0;
}

.message-cell-expand:hover {
    color: var(--color-primary-light);
}

/* Generic modal for displaying long content */
.simple-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1050;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-lg);
}

.simple-modal {
    background: var(--card-bg);
    border-radius: var(--radius-lg);
    max-width: 800px;
    width: 100%;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    box-shadow: var(--shadow-md);
    overflow: hidden;
}

.simple-modal-header {
    padding: var(--space-md) var(--space-lg);
    border-bottom: 1px solid var(--border-input);
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-weight: 600;
}

.simple-modal-close {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.4em;
    color: var(--text-secondary);
}

.simple-modal-body {
    padding: var(--space-lg);
    overflow-y: auto;
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 1.05em;
    line-height: 1.5;
    background: var(--bg-subtle);
    color: var(--text-primary);
}

/* ---- Filter badges row (status filters above a list)
   Enlarges default badge-status font and icons so filters are readable. ---- */
.filter-badges .badge-status {
    font-size: 0.85em;
    padding: 8px 16px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.filter-badges .badge-status .ph {
    font-size: 1.6em;
    vertical-align: middle;
}

/* ---- Round icon-only status badges (for table status columns)
   Bigger than stat card icons to be visible in list rows. ---- */
.status-icon-badge {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 !important;
    text-decoration: none;
    flex-shrink: 0;
}

.status-icon-badge .ph {
    font-size: 2.15em;
    vertical-align: middle;
}

/* ---- Generic stat cards (dashboard pastilles) ---- */
.stat-card {
    background: var(--card-bg);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-md);
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    min-width: 140px;
}

.stat-card-icon {
    width: var(--icon-circle-size);
    height: var(--icon-circle-size);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.stat-card-icon .ph {
    font-size: var(--icon-circle-font-size);
}

.stat-card-value {
    font-weight: 500;
    font-size: 1.6em;
    line-height: 1;
}

.stat-card-label {
    color: var(--text-muted);
    font-size: 0.8em;
    margin-top: 2px;
}

/* Auto-upscale existing inline-style pastilles across the app
   (targets any round container with 36px width used by stat cards) */
.list-section .rounded-circle[style*="width: 36px"][style*="height: 36px"] {
    width: var(--icon-circle-size) !important;
    height: var(--icon-circle-size) !important;
}

.list-section .rounded-circle .ph {
    font-size: var(--icon-circle-font-size) !important;
}

/* ---- Generic bulk-action bar (multiselect toolbar) ---- */
.bulk-bar {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--color-error-bg);
    border: 1px solid var(--color-error-border);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-lg);
}

.bulk-bar > .d-flex {
    flex-wrap: wrap;
    gap: var(--space-sm);
}

.bulk-bar-counter {
    font-size: var(--font-md);
}

.bulk-bar-counter strong {
    margin-right: var(--space-xs);
}

.bulk-bar-counter .ph {
    font-size: 1.5em;
    vertical-align: middle;
    margin-left: 2px;
}

.bulk-bar-clear {
    background: var(--card-bg);
    color: var(--text-secondary);
    border: 1px solid var(--border-input);
}

.bulk-bar-clear:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

/* ---- Section card (shared by revenue, lists, forms) ---- */
.list-section {
    background: var(--bg-subtle, #f7f7f7);
    border-radius: var(--radius-lg);
    padding: 24px;
    margin-bottom: var(--space-lg);
    overflow-x: auto; /* responsive: allow inner tables to scroll on narrow screens */
}

/* ---- Table inside a section card ---- */
.list-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 1em;
}

.list-table th {
    text-align: left;
    padding: 10px 12px;
    color: var(--text-secondary, #64748b);
    font-weight: 500;
    border-bottom: 2px solid var(--border-color, #e2e8f0);
    white-space: nowrap;
}

.list-table th.right,
.list-table td.right {
    text-align: right;
}

.list-table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-color, #e2e8f0);
    color: var(--text-primary, #1e293b);
}

.list-table tr:last-child td {
    border-bottom: none;
}

.list-table tr:hover td {
    background: rgba(0, 0, 0, 0.02);
}

/* When table is inside list-section, the section provides the card look */
.list-section table {
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    overflow: visible;
    margin: 0;
}

.list-section .list-table th,
.list-section .list-table td {
    padding: 10px 12px;
}

/* No extra first/last cell indent - section padding handles it */
.list-section .list-table th:first-child,
.list-section .list-table td:first-child {
    padding-left: 12px;
}

.list-section .list-table th:last-child,
.list-section .list-table td:last-child {
    padding-right: 12px;
}

.no-data {
    text-align: center;
    padding: 32px;
    color: var(--text-muted, #94a3b8);
    font-style: italic;
}

/* ---- Légende ---- */
ul.legende {
    display: flex;
    float: none;
    flex-wrap: wrap;
    gap: var(--space-lg);
    list-style: none;
    padding: var(--space-2xl);
    margin: 0 0 var(--space-lg) 0;
    background: white;
    border-radius: var(--radius-lg);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
    font-size: var(--font-sm);
    color: var(--text-primary);
}

/* Inside list-section, the section provides the card look */
.list-section ul.legende {
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    padding: 0;
    margin: 0;
}

ul.legende li {
    display: flex;
    align-items: center;
    gap: 0.4em;
}

ul.legende li.legende-achat i {
    color: var(--color-primary);
}

ul.legende li.legende-trial i {
    color: rgba(var(--color-primary-rgb), 0.6);
}

ul.legende li.legende-check i {
    color: var(--color-purple);
}

/* ============================================
   FORMS - compact
   ============================================ */

.formArea {
    padding: var(--space-md) var(--space-xl);
    border-bottom: solid 1px var(--border-color);
    border-top: solid 1px var(--border-color);
}

.formSearchArea {
    background-color: var(--card-bg);
    margin-bottom: var(--space-lg);
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    padding: var(--space-2xl);
}

/* When formSearchArea is also list-section, list-section provides the card */
.list-section.formSearchArea {
    border: none;
}

.form-floating > .form-control,
.form-floating > .form-select {
    font-size: var(--font-base);
    height: calc(2.8rem + 2px);
    min-height: calc(2.8rem + 2px);
    padding-top: 1.4rem;
    padding-bottom: 0.25rem;
}

.form-floating > label {
    padding-top: 0.55rem;
    padding-bottom: 0.25rem;
    font-size: var(--font-sm);
}

.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label,
.form-floating > .form-select ~ label {
    transform: scale(0.7) translateY(-0.55rem);
    transform-origin: left top;
    opacity: 0.65;
}

/* Force label back inside for empty readonly fields */
.form-floating > .form-control:placeholder-shown:not(:focus) ~ label {
    transform: none;
    opacity: 1;
}

/* --- Multiselect padding --- */
select.form-select[multiple] {
    padding: 10px 14px;
    height: auto !important;
    min-height: auto !important;
}

.form-control:focus {
    border-color: var(--color-primary-light);
    box-shadow: 0 0 0 0.2rem rgba(var(--color-primary-rgb), 0.2);
    background-color: rgba(var(--color-primary-rgb), 0.04);
}

/* ============================================
   PAGE HEADER (title + action buttons)
   ============================================ */

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

.page-header h1 {
    margin: 0;
}

/* Action sidebar (Créer, etc.) inside page-header */
.page-header .sidebar {
    position: static;
    width: auto;
    background: none;
    box-shadow: none;
    padding: 0;
    margin: 0;
}

.page-header .sidebar ul {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    list-style: none;
    padding: 0;
    margin: 0;
}

.page-header .sidebar li .menuSeparator {
    display: none;
}

.page-header .sidebar li a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 20px;
    background: var(--color-primary);
    color: var(--text-on-primary);
    border-radius: var(--radius-pill);
    font-size: var(--font-base);
    font-weight: 500;
    text-decoration: none;
    transition: background 0.2s, box-shadow 0.2s;
}

.page-header .sidebar li a:hover {
    background: var(--color-primary-dark, #1a8a96);
    box-shadow: var(--shadow-sm);
}

/* ============================================
   HEADINGS
   ============================================ */

h1.contenerTitle,
#page-body > h1,
.page-header h1 {
    margin-bottom: var(--space-lg);
    font-weight: 400;
    font-size: 1.8em;
    color: var(--text-primary);
}

h1.contenerTitle .title-action,
#page-body > h1 .title-action,
.page-header h1 .title-action {
    color: var(--color-primary);
}

h1.contenerTitle .title-separator,
#page-body > h1 .title-separator,
.page-header h1 .title-separator {
    color: var(--text-separator, #bababa);
    margin: 0 0.3em;
}

h2, h3 {
    margin-top: 0.8em;
    margin-bottom: 0.3em;
    font-size: var(--font-md);
    text-transform: uppercase;
    color: var(--text-secondary);
    font-weight: 600;
}

h3 {
    font-size: 0.8em;
}

h2.formTitle {
    border-bottom: solid 1px var(--border-color);
}

h3.formSection {
    text-transform: uppercase;
    padding-top: var(--space-lg);
    border-bottom: 1px solid var(--border-color);
    font-weight: normal;
    font-size: var(--font-base);
}

h3.formHeader {
    text-transform: uppercase;
    padding-top: var(--space-xs);
    border-top: solid 1px lightgray;
    border-bottom: solid 1px lightgray;
    padding-bottom: var(--space-xs);
}

p {
    line-height: 1.5;
    margin: 0.25em 0;
}

/* ============================================
   PAGINATION
   ============================================ */

.paginateButtons {
    margin-top: var(--space-xl);
    margin-bottom: var(--space-xl);
    font-size: 0.8em;
    text-align: center;
    width: 100%;
    text-transform: uppercase;
}

.paginateButtons a, .paginateButtons .currentStep {
    margin-right: var(--space-sm);
    background-color: var(--bg-highlight);
    padding: var(--space-xs) 10px;
    border-radius: var(--radius-xs);
}

.paginateButtons .currentStep {
    font-weight: bold;
    background-color: var(--card-bg);
    border: solid 1px var(--color-primary-light);
}

.listIntro {
    padding-bottom: 10px;
}

/* ============================================
   LINKS
   ============================================ */

a {
    text-decoration: none;
}

a:link, a:visited, a:hover {
    color: var(--text-link);
}

.visibleLinks {
    color: var(--text-body);
}

.visibleLinks a:link, .visibleLinks a:visited, .visibleLinks a:active, .visibleLinks a, a.visibleLinks {
    color: var(--text-link-accent);
}

ul.listInMainContent {
    list-style: disc;
    padding-top: 10px;
}

ul.sublist {
    list-style: disc;
    padding: 10px 0 10px var(--space-xl);
}

/* ============================================
   CONTENT AREAS
   ============================================ */

.legende_title {
    text-transform: uppercase;
    font-weight: bold;
    font-size: var(--font-base);
}

.nbResults {
    padding-right: var(--space-lg);
    text-transform: uppercase;
    color: var(--color-primary);
    font-size: var(--font-base);
}

.disabled, a.disabled {
    font-style: italic;
    color: gray !important;
}

.linkList {
    padding-top: var(--space-sm);
    padding-bottom: var(--space-sm);
}

.linkList li {
    padding: var(--space-sm);
}

.linkList li ul {
    padding: var(--space-lg);
    background-color: var(--bg-highlight);
    margin-top: var(--space-sm);
}

.sectionList {
    padding-top: var(--space-sm);
    font-size: var(--font-base);
    color: var(--text-link-accent);
}

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

.smallPadding, .linkList li.smallPadding {
    padding: 2px;
}

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

/* ============================================
   JOBS
   ============================================ */

.jobsArea h3 {
    margin: var(--space-lg) 0 var(--space-xs) 0;
    text-transform: uppercase;
    font-size: var(--font-base);
}

.jobsArea a:link, .jobsArea a:visited, .jobsArea a:active, .jobsArea a, a.jobsArea {
    color: var(--text-link-accent);
}

/* ============================================
   BADGES
   ============================================ */

.badge, .toUpdateBadge, .errorBadge {
    background: var(--color-danger);
    color: var(--text-on-primary);
    padding: 3px var(--space-sm);
    font-size: var(--font-sm);
    text-transform: uppercase;
    border-radius: var(--radius-pill);
    margin-left: var(--space-sm);
}

.badgePositive {
    background: var(--color-success);
}

.badgeFailure {
    background: grey;
}

.badgeHacked {
    background: black;
}

.toUpdateBadge {
    background: var(--color-purple);
    font-size: var(--font-base);
}

.errorBadge {
    background: #000;
    font-size: var(--font-base);
}

.processingBadge {
    background: var(--color-warning);
    font-size: var(--font-base);
}

.count {
    width: 35px;
    display: inline-block;
    text-align: right;
    padding-right: var(--space-sm);
}

.lightLabel {
    color: gray;
}

.smallLightLabel {
    color: gray;
    font-size: 0.8em;
}

.deactivated {
    text-decoration: line-through;
}

.false {
    text-decoration: line-through;
}

/* ============================================
   DASHBOARD
   ============================================ */

.dashboard-cards {
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    margin-top: 24px;
}

.dashboard-card {
    flex: 1;
    min-width: 200px;
    background: var(--bg-subtle, #f7f7f7);
    border-radius: 12px;
    padding: 32px 24px;
    text-align: center;
}

.dashboard-card .card-icon {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 16px;
}

.dashboard-card .card-icon .ph {
    font-size: 2em;
    color: var(--text-on-primary);
}

.dashboard-card .card-value {
    font-size: 1.8em;
    font-weight: 600;
    color: var(--text-primary, #1e293b);
    margin-bottom: 4px;
}

.dashboard-card .card-label {
    font-size: 0.9em;
    color: var(--text-secondary, #64748b);
}

.dashboard-card .card-refund {
    font-size: 0.8em;
    color: var(--color-danger);
    margin-top: 4px;
}

.dashboard-card .card-previous {
    font-size: 0.95em;
    color: var(--text-primary, #1e293b);
    margin-top: 6px;
}

.dashboard-card .card-platform {
    font-size: 0.85em;
    color: var(--text-muted, #94a3b8);
    margin-top: 6px;
}

/* ---- Chart section ---- */
.dashboard-chart {
    background: var(--bg-subtle, #f7f7f7);
    border-radius: 12px;
    padding: 24px 28px;
    margin-top: 24px;
}

.dashboard-chart .chart-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.dashboard-chart .chart-title {
    font-size: 1.3em;
    font-weight: 400;
    color: var(--text-primary, #1e293b);
    display: flex;
    align-items: center;
    gap: 10px;
}

.year-nav {
    cursor: pointer;
    font-size: 0.85em;
    color: var(--text-muted, #94a3b8);
    padding: 2px 6px;
    border-radius: 4px;
    user-select: none;
    transition: color 0.2s;
}

.year-nav:hover {
    color: var(--color-primary, #3ab3ff);
}

.dashboard-chart .chart-legend {
    display: flex;
    gap: 20px;
    font-size: 0.85em;
    color: var(--text-secondary, #64748b);
}

.dashboard-chart .chart-legend span {
    display: flex;
    align-items: center;
    gap: 6px;
}

.dashboard-chart .chart-legend .dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: inline-block;
}

/* ---- Chart toggle ---- */
.chart-toggle {
    display: flex;
    background: var(--bg-surface, #e8e8e8);
    border-radius: 6px;
    overflow: hidden;
    font-size: 0.82em;
}

.chart-toggle button,
.chart-toggle a {
    border: none;
    background: transparent;
    padding: 5px 14px;
    cursor: pointer;
    color: var(--text-secondary, #64748b);
    transition: all 0.2s;
    font-family: inherit;
    font-size: inherit;
    text-decoration: none;
}

.chart-toggle button.active,
.chart-toggle a.active {
    background: var(--color-primary, #3ab3ff);
    color: var(--text-on-primary);
    border-radius: 6px;
}

/* ============================================
   MISC UTILITIES
   ============================================ */

#messageArea {
    padding: 0 var(--space-xl);
}

#page-body {
    margin: 1.5em 1em;
}

#controller-list ul {
    list-style-position: inside;
}

#controller-list li {
    line-height: 1.3;
    list-style-position: inside;
    margin: 0.25em 0;
}

.strong {
    font-weight: bold;
}

.tradItem {
    margin-bottom: var(--space-xs);
    text-transform: uppercase;
    font-size: smaller;
    color: white;
    width: 80px;
}

.tradItem input, .tradItem span a, .tradItem span a:link {
    padding: 2px 6px;
    color: white;
    border: none;
    text-transform: uppercase;
}

.tradItem input.done, .tradItem span.done a:link {
    background-color: var(--color-success);
    padding: 2px 6px;
}

.tradItem input.todo, .tradItem span.todo a:link {
    background-color: var(--color-danger);
    padding: 2px 6px;
}

.tradReferenceForm {
    margin-top: 6px;
    background-color: var(--bg-muted);
    padding: 10px;
    margin-bottom: 14px;
}

.reference h3.formSection {
    padding-top: 0;
}

.lastUpdate {
    border: solid 1px var(--border-color);
    float: right;
    padding: var(--space-sm);
    text-transform: uppercase;
    font-size: smaller;
    border-radius: var(--radius-sm);
    background: var(--card-bg);
}

.lastUpdate span {
    font-weight: 600;
}

.tradOtherForm {
    border: solid 1px lightgray;
    padding: 10px;
}

.tradOtherForm .existingTranslation h3 {
    text-transform: uppercase;
}

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

.smaller {
    font-size: var(--font-base);
}

.btn-link {
    background-color: black;
    color: white;
    padding: var(--space-xs) 10px;
    border-radius: var(--radius-pill);
}

a.btn-link:link, .btn-link, a.btn-link:visited, a.btn-link hover {
    color: white;
    font-size: var(--font-xs);
    margin-left: 0;
}

.explanation {
    font-size: var(--font-base);
    margin-bottom: var(--space-sm);
    margin-top: var(--space-xs);
}

.importantDate {
    font-weight: bold;
    padding: 0 0 0 var(--space-sm);
}

.separator {
    padding: 0 1px;
}

.tagsList {
    display: inline-block;
    margin-bottom: var(--space-sm);
    font-size: 0.8em;
    background: var(--card-bg);
    border: solid black 1px;
    color: black;
}

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

.weekDay .zoneId {
    font-size: 0.8em;
    text-transform: uppercase;
}

.zoneId {
    margin-left: var(--space-xs);
}

.global_btns {
    text-transform: uppercase;
    font-size: var(--font-base);
}

.global_btns a {
    font-size: 0.8em;
}

/* ============================================
   TOOLTIPS
   ============================================ */

.tooltip {
    position: relative;
    display: inline-block;
    border-bottom: 1px dotted var(--color-primary);
    border-top: 1px dotted var(--color-primary);
}

.tooltip .tooltipText {
    visibility: hidden;
    width: auto;
    background-color: black;
    color: var(--text-on-primary);
    text-align: center;
    padding: 5px 10px;
    border-radius: var(--radius-xs);
    position: absolute;
    z-index: 1;
    top: -30px;
    right: 50%;
}

.tooltip:hover .tooltipText {
    visibility: visible;
}

/* ============================================
   POPUP LIST (autocomplete)
   ============================================ */

.popup-list {
    list-style: none;
    margin: 0;
    padding: 0;
    position: absolute;
    z-index: 1000;
    background-color: var(--card-bg);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    min-width: 300px;
    max-height: 250px;
    overflow-y: auto;
    border: 1px solid var(--border-input);
}

.popup-list li {
    padding: var(--space-sm) var(--space-lg);
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.popup-list li:hover {
    background-color: var(--bg-subtle);
}

/* ============================================
   DATE PICKERS
   ============================================ */

.input-group .input-group-addon select#start_day,
.input-group .input-group-addon select#end_day,
.input-group .input-group-addon select#start_month,
.input-group .input-group-addon select#end_month,
.input-group .input-group-addon select#start_year,
.input-group .input-group-addon select#end_year {
    padding: 0.35em 0.8em;
    border: 1px solid var(--border-input);
    border-radius: var(--radius-pill);
    font-size: var(--font-sm);
    background-color: var(--card-bg);
    color: var(--text-body);
    appearance: none;
    -webkit-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='%23999' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.5em center;
    padding-right: 1.8em;
    cursor: pointer;
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.input-group .input-group-addon select:hover {
    border-color: var(--color-primary-light);
}

.input-group .input-group-addon select:focus {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-focus);
    outline: none;
}

/* Round toggle switches for checkboxes */
.form-check {
    padding-left: 3em;
    min-height: 1.6em;
    overflow: visible;
}

.form-check .form-check-input {
    width: 2.4em;
    height: 1.4em;
    border-radius: 0.7em;
    appearance: none;
    -webkit-appearance: none;
    background-color: var(--text-muted);
    border: none;
    cursor: pointer;
    position: relative;
    transition: background-color var(--transition-fast);
    vertical-align: middle;
    flex-shrink: 0;
    margin-left: -3em;
    margin-top: 0;
    background-position: left center;
    background-size: 1em;
}

.form-check .form-check-input::before {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: calc(1.4em - 6px);
    height: calc(1.4em - 6px);
    border-radius: 50%;
    background-color: white;
    transition: transform var(--transition-fast);
}

.form-check .form-check-input:checked {
    background-color: var(--color-primary);
    background-position: 2px center;
    background-size: 1em;
}

.form-check .form-check-input:checked::before {
    transform: translateX(1em);
}

/* ============================================
   IMPORTANT INFO, OPTIONS
   ============================================ */

.paletteColorsInForm {
    margin-left: 294px;
    padding-top: var(--space-lg);
}

.btn_form {
    width: 24px;
    margin-left: var(--space-sm);
    font-weight: bold;
}

.reporting li {
    margin-top: var(--space-sm);
    margin-bottom: var(--space-sm);
}

.importantInfo {
    border: solid 1px var(--border-color);
    padding: 10px;
    margin-bottom: var(--space-lg);
    border-radius: var(--radius-sm);
    background: var(--card-bg);
}

.importantInfo ul {
    padding: var(--space-sm);
    list-style: disc;
    list-style-position: inside;
}

.importantInfo ul li {
    list-style: disc;
    list-style-position: inside;
    padding-top: var(--space-xs);
}

.optionalSection {
    background-color: var(--bg-muted);
    padding: var(--space-lg);
    padding-top: 6px;
    margin-bottom: var(--space-sm);
    margin-top: var(--space-sm);
    border-radius: var(--radius-sm);
}

.versionOption {
    font-variant: small-caps;
    color: var(--color-danger);
}

.commonOption {
    font-variant: small-caps;
    color: var(--text-primary);
    font-weight: 600;
}

.summary-table {
    margin-bottom: var(--space-xl);
    border-bottom: solid lightgrey 1px;
}

.summary-table th {
    font-weight: bold;
    text-align: center;
}

.summary-table-main th {
    background-color: var(--bg-purple-light);
}

ol, ul {
    list-style: none;
    color: var(--text-body);
}

.menuSeparator {
    margin-right: 5px;
    margin-left: 5px;
    color: lightgray;
}

/* Bouton d'identifiant d'une publication (articles et abonnements) — voir
   /common/templates/_publication_id_button.gsp */
.publication-id-button {
    background: var(--text-secondary);
    color: var(--card-bg);
}

.publication-id-button-small {
    font-size: var(--font-xs);
    padding: 2px 8px;
}

/* ---- Bloc repliable natif (<details>) avec le chevron Phosphor à DROITE, comme partout dans
   nos applications. Le triangle du navigateur est masqué deux fois : `list-style` pour
   Firefox, le pseudo-élément pour WebKit — sans les deux, il en reste un. Usage :
   <details class="bo-details"><summary><span>…</span><i class="ph ph-caret-down chevron"></i></summary>…</details> */
.bo-details > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    cursor: pointer;
    list-style: none;
}

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

.bo-details > summary .chevron {
    flex: none;
    transition: transform 0.15s ease;
}

.bo-details[open] > summary .chevron {
    transform: rotate(180deg);
}

/* Ce qui ne se lit que replié : le résumé d'un bloc dont le contenu déplié le répète. */
.bo-details[open] > summary .when-closed {
    display: none;
}



/* LES RÉGLAGES QUI ACCOMPAGNENT TOUS LES GENRES. Une carte, et dedans autant de colonnes que
   l'écran en porte : `auto-fit` avec une largeur minimale, donc trois colonnes sur un écran large,
   une seule sur un téléphone, sans qu'aucun seuil soit écrit à la main.

   C'est un bloc de RÉFÉRENCE : on le parcourt en diagonale pour trouver la ligne qui contredit
   le style qu'on règle. Neuf réglages en une colonne faisaient une page qu'on fait défiler. */
.global-directions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-sm) var(--space-lg);
    margin: var(--space-md) 0;
    padding: var(--space-md) var(--space-lg);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-lg);
    background: var(--bg-subtle);
    font-size: var(--font-xs);
}

.global-directions .direction {
    display: flex;
    align-items: flex-start;
    gap: 6px;
}

/* L'icône dit la NATURE du réglage, sa couleur dit s'il demande ou s'il refuse. C'est la seule
   chose qu'on doit voir sans lire : un refus mal placé est l'erreur qui a coûté le plus cher. */
.global-directions .direction-icon {
    flex: none;
    margin-top: 1px;
    color: var(--color-primary);
    font-size: 1.15em;
    cursor: help;
}

.global-directions .direction-icon--no {
    color: var(--color-danger);
}

.global-directions .direction-value {
    color: var(--text-secondary);
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
   FORMULAIRES : L'AIDE DERRIÈRE UN « i »
   Un champ et son explication, côte à côte. Le « i » ne peut pas vivre DANS un
   label flottant — Bootstrap le rapetisse avec le label — il se tient donc à
   droite du champ, aligné sur sa première ligne.
   --------------------------------------------------------------------------- */
.field-with-help {
    display: flex;
    align-items: flex-start;
    gap: 4px;
    min-width: 0;
}

.field-with-help > .form-floating {
    flex: 1;
    min-width: 0;
}

.field-help {
    flex: none;
    margin-top: 10px;
    padding: 0;
    width: 22px;
    height: 22px;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--color-primary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.field-help:hover {
    background: rgba(var(--color-primary-rgb), 0.12);
}

.field-help .ph {
    font-size: 1.1em;
}

/* Les drapeaux d'un formulaire : une case, son mot, son aide — sur une seule ligne.
   `flex: 0 1 auto` : ils prennent la place de leur texte et passent à la ligne
   ensemble quand l'écran se resserre. */
.flag-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 1 auto;
    font-size: var(--font-sm);
    cursor: pointer;
}

.flag-label .field-help {
    margin-top: 0;
}


/* LE CHOIX DES PAROLES À LA RÉPARATION : deux versions côte à côte tant que l'écran en porte
   deux, empilées sinon. Comparer suppose de voir les deux d'un coup — l'une sous l'autre, il
   faut faire défiler et se souvenir. */
.repair-choice {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-lg);
    margin-top: var(--space-md);
}

/* LE TEMPS QUI SERA RECHANTÉ, encadré dans les deux versions : c'est lui qu'on compare, le
   reste n'est là que pour le situer. */
.marked-text .marked-here {
    background: rgba(var(--color-primary-rgb), 0.10);
    border-left: 3px solid var(--color-primary);
    border-radius: var(--radius-sm);
    padding: var(--space-xs) var(--space-sm);
    margin-left: -3px;
}


/* LES PRISES D'UNE CHANSON, sur leur propre carte. Dépliées, elles s'écoulaient dans la colonne
   sans bord, et l'œil ne voyait plus où la liste d'une chanson finissait ni où commençait la
   ligne suivante. Le fond gris les tient ensemble ; un filet sépare chaque prise de la
   précédente, sauf la première. */
.takes-card {
    margin-top: 6px;
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-lg);
    background: var(--bg-subtle);
}

.takes-card .take + .take {
    margin-top: var(--space-sm);
    padding-top: var(--space-sm);
    border-top: 1px solid var(--border-input);
}


/* LA PRISE QU'ON ENTEND, en noir au milieu des grises. Une liste de prises se ressemble — même
   style, mêmes durées, parfois la même graine — et la première question qu'on se pose est
   « laquelle est en place ? ». Le filet à gauche la désigne sans ajouter un mot. */
.takes-card .take-current > span:first-child,
.takes-card .take-current .separator {
    color: var(--text-primary) !important;
    font-weight: 600;
}

.takes-card .take-current {
    border-left: 3px solid var(--color-audio);
    padding-left: var(--space-sm);
    margin-left: -3px;
}

/* LE TITRE NE BOUGE PAS QUAND ON DÉPLIE. Le résumé d'un bloc replié disparaît d'ordinaire à
   l'ouverture, parce que le texte déplié le répète ; celui-là EST le texte entier, et le faire
   disparaître pour le réafficher plus bas le faisait sauter d'une ligne à chaque clic. */
.bo-details.field-single[open] > summary .when-closed {
    display: block;
}

/* ---- Immersion+ > Dictées : la liste des leçons d'un article. Pleine largeur, colonnes
   dimensionnées par leur contenu (mise en page automatique), texte à la ligne sans couper les
   mots ; sous 1024 px, mobile.css empile chaque dictée en fiche. */
.immersion-lessons {
    width: 100%;
    table-layout: auto;
}

.immersion-lessons td {
    vertical-align: top;
    overflow-wrap: break-word;
}

/* Les trois colonnes de texte se partagent la largeur à parts égales, et la gardent quand un
   texte laisse la place à son formulaire : sans ces largeurs, la colonne en édition se
   resserrait sur le champ de saisie. */
.immersion-lessons th.text {
    width: 26%;
}

/* LES COLONNES DE PASTILLES SE SERRENT SUR LEUR CONTENU. `width: 1%` avec une mise en page
   automatique veut dire « le minimum » : la largeur qu'elles n'occupent pas va à la colonne de
   texte la plus longue — les paroles — au lieu d'être partagée entre quatre colonnes dont deux
   ne portent que deux boutons. */
.immersion-lessons th.buttons {
    width: 1%;
    white-space: nowrap;
}

/* Leçon et personnage sur une ligne, jamais coupés ; le sujet, dessous, passe à la ligne. */
.immersion-lessons .lesson {
    width: 14%;
    white-space: nowrap;
}

/* Le sujet, dessous, passe à la ligne dans une colonne étroite. */
.immersion-lessons .lesson .topic {
    white-space: normal;
    max-width: 11em;
    margin-top: 4px;
    font-size: var(--font-xs);
}

/* Le bouton des mots nouveaux, sous le sujet ; la liste elle-même s'ouvre en dialogue. */
/* Les mots nouveaux suivent la phrase du sujet sans aller à la ligne : une pastille discrète,
   plus petite que les boutons d'action. */
.immersion-lessons .lesson .new-words {
    width: 22px;
    height: 22px;
    margin-left: 4px;
    vertical-align: middle;
    background-color: var(--color-neutral-strong) !important;
    border: none !important;
    color: var(--text-on-primary) !important;
}

.immersion-lessons .lesson .new-words .ph {
    font-size: 0.9em;
}

/* Écouter, télécharger, refaire, retoucher : des pastilles de la taille des mots nouveaux. Le
   crayon valait 42 px comme les boutons d'action — il recouvrait le titre qu'il sert à modifier,
   et sur un téléphone il en mangeait le quart. Ce sont des gestes de LIGNE, pas des gestes de
   contenu : ils se rangent avec le lecteur, pas avec la validation.

   UNE SEULE CONSTANTE POUR TOUS : le crayon et les boutons du son se tiennent côte à côte dans
   la même colonne, et deux tailles réglées séparément divergent au premier ajustement. Le
   padding écarte l'icône du bord — collée, elle se lit comme une tache. */
.immersion-lessons {
    --line-btn-size: 26px;
    --line-btn-icon: 0.95em;
}

.immersion-lessons .line-actions .btn.icon-btn,
.immersion-lessons .btn.immersion-play,
.immersion-lessons .btn.immersion-download,
.immersion-lessons .btn.audio-make--same,
.immersion-lessons .btn.audio-remake,
.immersion-lessons .btn.field-action {
    width: var(--line-btn-size);
    height: var(--line-btn-size);
    padding: 3px !important;
    margin-left: 6px;
    vertical-align: middle;
}

.immersion-lessons .line-actions .btn.icon-btn .ph,
.immersion-lessons .btn.immersion-play .ph,
.immersion-lessons .btn.immersion-download .ph,
.immersion-lessons .btn.audio-make--same .ph,
.immersion-lessons .btn.audio-remake .ph,
.immersion-lessons .btn.field-action .ph {
    font-size: var(--line-btn-icon);
}

/* Les trois gestes du son — le produire, l'écouter, le garder — portent la couleur du son. Un
   geste hors d'atteinte reste neutre : la couleur dit ce qui est possible.
   `!important` et le sélecteur multiple : Bootstrap pose `.btn { background-color: transparent }`
   et sa feuille est chargée après la nôtre ; à poids égal, c'est elle qui gagnerait.
   ⚠️ SANS VARIANTE, UN BOUTON EST INVISIBLE : `.btn` porte `color: var(--text-on-primary)`, donc
   du blanc, et le fond ne vient que d'ici. Le téléchargement d'une chanson est resté blanc sur
   blanc — présent, cliquable, introuvable — jusqu'au 12/09/2026. */
.btn.audio-action {
    background-color: var(--color-audio) !important;
    border: none !important;
    color: var(--text-on-primary) !important;
}

/* ÉCOUTER, LE GESTE LE PLUS FRÉQUENT DE LA PAGE : le bleu du thème, celui qu'on cherche des yeux
   sur tous les écrans. Il était de la couleur du son, partagée avec trois autres boutons — la
   couleur d'un DOMAINE ne distingue pas les gestes à l'intérieur de ce domaine. */
.btn.immersion-play {
    background-color: var(--color-primary) !important;
    border: none !important;
    color: var(--text-on-primary) !important;
}

/* EMPORTER LE FICHIER NE TOUCHE À RIEN : ni au texte, ni à la piste, ni à ce que l'apprenant
   recevra. C'est le geste le plus neutre de la ligne, et il porte le gris des mots nouveaux —
   la couleur de ce qui se consulte. Il était de la couleur du son, où il se confondait avec
   « écouter », qui est le geste qu'on cherche dix fois plus souvent. */
.btn.immersion-download {
    background-color: var(--color-neutral-strong) !important;
    border: none !important;
    color: var(--text-on-primary) !important;
}

/* REFAIRE L'AUDIO, LE GESTE LE PLUS FORT DE LA LIGNE. Un tirage neuf n'est pas une variante :
   c'est une autre chanson, et celle qu'on écoutait ne reviendra pas — on ne retrouve une
   interprétation que par sa graine, et un tirage neuf en prend une autre. Corail plutôt que rouge :
   c'est un geste normal du travail, pas une suppression. Le même signe partout, dictée comprise,
   parce que c'est le même acte. */
.btn.audio-remake {
    background-color: var(--color-coral) !important;
    border: none !important;
    color: var(--text-on-primary) !important;
}

.btn.audio-action:hover,
.btn.immersion-play:hover,

/* LE REFRAIN, PLUS SOUTENU QUE LES COUPLETS. C'est le temps qu'on refait le plus — il porte les
   mots nouveaux et revient trois fois dans la liste — et le retrouver d'un coup d'œil vaut mieux
   que lire six libellés. Même couleur, deux fois plus dense. */


/* EFFACER UNE PRISE : rouge, mais pâle. C'est une destruction, donc elle se signale ; c'est une
   prise et non une chanson, donc elle ne crie pas comme la corbeille de la ligne. */
.immersion-lessons .btn.take-delete {
    background-color: rgba(255, 71, 87, 0.12) !important;
    color: var(--color-danger) !important;
    border: none !important;
}


/* L'ENTRÉE ET LA SORTIE sont des bornes, pas des temps : contour seul, sur le fond de la carte.
   Elles encadrent la chanson au lieu de s'aligner avec ses couplets. */
.immersion-lessons .btn.audio-make--edge {
    background-color: transparent !important;
    color: var(--color-audio-make) !important;
    border: 1px solid rgba(var(--color-audio-make-rgb), 0.45) !important;
}


/* LES BOUTONS D'UN TEMPS : la forme ici, la couleur dans l'énumération. Elle y est déjà — le
   violet des paroles pour ce qui se chante, le jaune d'un interlude, l'orange d'une vocalise —
   et la recopier dans six règles la ferait diverger au premier temps ajouté. */
.immersion-lessons .btn.section-btn {
    font-weight: 500;
}

/* UN TEMPS QUI NE SE CHANTE PAS — interlude, vocalise — plus pâle que les couplets : on le
   rechante rarement, et il ne porte aucun texte à corriger. */
.immersion-lessons .btn.audio-make--patch-light {
    background-color: rgba(var(--color-audio-make-rgb), 0.07) !important;
    color: var(--color-audio-make) !important;
    border: 1px dashed rgba(var(--color-audio-make-rgb), 0.35) !important;
}

.immersion-lessons .btn.audio-make--patch-strong {
    background-color: rgba(var(--color-audio-make-rgb), 0.30) !important;
    color: var(--color-audio-make) !important;
    border: 1px solid rgba(var(--color-audio-make-rgb), 0.65) !important;
    font-weight: 600;
}

.btn.audio-make--same:hover,
.btn.audio-remake:hover {
    filter: brightness(1.1);
}

.btn.immersion-download:hover {
    filter: brightness(0.95);
}

/* LE CRAYON NE SORT QUE DÉPLIÉ. Replié, la ligne d'une chanson ne montre que son titre et le
   chevron : un seul geste possible, aucune hésitation. Le crayon reparaît avec le texte qu'il
   sert à retoucher — le titre d'abord, puis celui des paroles, chacun à côté du sien.

   Ailleurs il reste visible replié : sur une dictée, retoucher un temps sans l'ouvrir d'abord
   est le geste courant, et il y en a trois par ligne. */
.immersion-lessons .song-text .bo-details:not([open]) ~ .field-action {
    display: none;
}

/* UN TEXTE MARQUÉ : les temps séparés par un blanc, le refrain en gras. L'en-tête entre crochets
   ne s'affiche plus — il reste dans le texte, que le moteur de musique lit ainsi. */
/* ⚠️ `pre-line` SUR LES VERS, JAMAIS SUR LE BLOC QUI LES PORTE. Il conserve les retours à la
   ligne — c'est pour cela qu'on le met — et le gabarit qui rend les temps écrit un retour et une
   indentation ENTRE chaque `<div>` : posé sur le bloc, il rendait ces retours-là aussi, un par
   ligne de source, d'où les grands blancs au-dessus du titre et entre les couplets. Sur les vers
   seuls, l'espace qui sépare deux blocs redevient de l'espace de balisage, et disparaît. */
.marked-text > div {
    white-space: pre-line;
}

/* AUCUN BLANC ENTRE LES TEMPS : le gras du refrain les sépare déjà, et une chanson lue d'un
   seul tenant se parcourt plus vite qu'une chanson en six morceaux. */
.marked-text > div + div {
    margin-top: 0;
}

/* LE TEXTE DÉPLIÉ SUR UNE CARTE : les jetons de `.info-card`, puisque c'est la même idée — un
   bloc qui se détache de la colonne qui le porte. */
.field-card {
    border: 1px solid var(--border-input);
    border-radius: var(--radius-lg);
    padding: var(--space-md) var(--space-lg);
    background: var(--bg-subtle);
    box-shadow: var(--shadow-sm);
}

/* LES DEUX MENUS DE LA COLONNE STYLE : le genre, puis la voix. Une police plus petite que celle
   du texte — « Salsa portoricaine » et « Ranchera mexicaine » sont longs, et deux menus à la
   taille normale imposaient à la colonne une largeur que l'écran n'a pas toujours. Le style et
   l'écriture en dur dans la vue se recopiaient d'un menu à l'autre. */
.immersion-lessons .line-select {
    font-size: var(--font-xs);
    max-width: 100%;
}

/* ⚠️ LA HAUTEUR SUIT LE NOMBRE DE LIGNES DEMANDÉ. `main.css` pose `textarea { height: 120px }`
   pour toute la maison : un champ de titre déclaré à deux lignes en occupait six, au milieu
   d'une colonne où chaque ligne compte. `auto` rend la main à l'attribut `rows`. */
.immersion-lessons textarea {
    height: auto;
}

.marked-text .marked-refrain {
    font-weight: 600;
}

/* LA TRADUCTION DERRIÈRE UN BOUTON : elle sert la relecture, pas la lecture. Le bouton est une
   pastille violette — la couleur de ce qui s'adresse au relecteur et jamais à l'apprenant, comme
   la consigne de jeu d'une dictée — et il porte LE MÊME CHEVRON que les blocs qui déplient le
   titre et les paroles, en plus petit : un même geste se signale partout de la même façon.

   `bo-details` fait le reste — marqueur natif masqué des deux côtés, chevron qui pivote à
   l'ouverture. Seul le placement change : ici le chevron colle au bouton au lieu de filer à la
   ligne, parce qu'il n'y a pas de résumé à sa gauche. */
.bo-details.field-translation > summary {
    display: inline-flex;
    justify-content: flex-start;
    align-items: flex-start;
    gap: 2px;
    margin-top: 4px;
}

.field-translation-badge {
    width: var(--line-btn-size, 26px);
    height: var(--line-btn-size, 26px);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--color-purple);
    color: var(--text-on-primary);
}

.field-translation-badge .ph {
    font-size: var(--line-btn-icon, 0.95em);
}

.field-translation > summary .chevron {
    font-size: 0.7em;
    color: var(--text-muted);
}

.field-translation .marked-text {
    color: var(--text-muted);
    margin-top: 4px;
}

/* REFAIRE LA TRADUCTION : le violet du relecteur, en plus discret que sa pastille — c'est un
   geste rare, à côté d'un bouton qui, lui, sert à chaque relecture. */
.immersion-lessons .btn.field-translation-refresh {
    background-color: rgba(205, 29, 255, 0.12) !important;
    color: var(--color-purple) !important;
    border: none !important;
}


/* TROIS PROFONDEURS DE CHANGEMENT, UNE SEULE COULEUR. Plus le fond est plein, plus ce qui est
   déjà entendu disparaît : retoucher un temps laisse la chanson autour intacte, rejouer la graine
   la refait à l'identique aux consignes près, un tirage neuf en fait une autre. La profondeur se
   voit donc avant l'infobulle, et sans avoir à lire quatre libellés.

   ⚠️ PÂLE N'EST PAS ÉTEINT : l'icône garde sa pleine force et prend la couleur du fond plein, et
   un contour la tient. Un bouton désactivé, lui, baisse l'OPACITÉ de tout — c'est la différence
   qu'il faut pouvoir lire d'un coup d'œil. */
/* REJOUER LA MÊME PRISE : la couleur du son, pleine. C'est le geste voisin d'écouter — il rend
   la même interprétation — et il ne coûte que le temps de la refaire. Le tirage neuf, lui, est
   corail : celui-là ne rend pas la même chanson. */
.btn.audio-make--same {
    background-color: var(--color-audio) !important;
    color: var(--text-on-primary) !important;
    border: none !important;
}

.btn.audio-make--patch {
    background-color: rgba(var(--color-audio-make-rgb), 0.14) !important;
    color: var(--color-audio-make) !important;
    border: 1px solid rgba(var(--color-audio-make-rgb), 0.45) !important;
}

.btn.audio-make--same:hover,
.btn.audio-make--patch:hover {
    filter: brightness(0.95);
}

.btn.audio-action--waiting {
    background-color: var(--color-neutral) !important;
}

/* UN BOUTON ÉTEINT SE VOIT ÉTEINT. Valider est la seule action qui se désactive une fois faite ;
   sans cette règle elle gardait sa couleur pleine et son curseur de main, et rien ne disait que
   le clic ne partirait pas. */
.immersion-lessons .btn:disabled,
.immersion-lessons .btn[disabled] {
    opacity: 0.35;
    cursor: default;
    filter: none !important;
}

/* Le débit de la voix : vert s'il suit celui de la méthode, orange s'il file, bleu s'il traîne.
   La couleur porte l'information, le nombre la précise. */
/* Les ressources qui viennent du groupe de méthodes, et non de la méthode elle-même : un aplat
   discret les rassemble. Pas de contour — le thème neutralise les bordures, on sépare par le
   fond et l'espace. */
.group-resources {
    background: var(--bg-subtle);
    border-radius: 6px;
    padding: 4px 8px;
    margin-top: 4px;
}

.group-resources ul {
    margin: 0;
}

.audio-rate {
    margin-left: 6px;
    font-size: var(--font-xs);
    white-space: nowrap;
}

.audio-rate--coherent {
    color: var(--color-green);
}

.audio-rate--rapide {
    color: var(--color-warning);
}

.audio-rate--lent {
    color: var(--color-info);
}

/* La liste des mots nouveaux : beaucoup de mots, une police plus petite qu'un texte suivi. */
/* Les mots nouveaux en deux colonnes : le numéro de leçon dans la marge, les mots sur toute la
   largeur restante. Une ligne par leçon plutôt que deux, et des numéros alignés que l'œil suit. */
.new-words-list {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--space-sm, 0.75rem);
    row-gap: 4px;
    align-items: baseline;
}

.new-words-list,
.new-words-list dt {
    font-size: var(--font-sm);
}

.new-words-list dt,
.new-words-list dd {
    margin: 0;
    white-space: nowrap;
}

.new-words-list dd {
    white-space: normal;
}

.immersion-lessons .actions {
    width: 1%;
    text-align: right;
    white-space: nowrap;
}

/* Les gestes d'une dictée sur deux lignes : relire, refaire, effacer ; la voix et la
   publication dessous. */
.immersion-lessons .actions .action-row {
    display: flex;
    justify-content: flex-end;
    gap: 4px;
}

.immersion-lessons .actions .action-row + .action-row {
    margin-top: 4px;
}

/* La consigne de jeu de la voix, sous chaque temps : une couleur à elle, ni le rouge des
   contrôles ni le gris des emprunts. */
.voice-prompt {
    margin-bottom: 4px;
    font-size: var(--font-xs);
    color: var(--color-purple);
}

/* La colonne des contenus et celle des actions, posees en classes plutot qu'en style inline :
   une regle media ne peut rien contre un attribut `style`. */
.immersion-groups .group-contents {
    vertical-align: top;
}

.immersion-groups .group-actions {
    text-align: right;
}

/* La ligne qui porte la table des lecons : elle occupe toute la largeur, legerement en retrait
   pour qu'on voie qu'elle appartient au groupe au-dessus. */
.immersion-groups .group-lessons {
    padding: 0 0 var(--space-md) var(--space-md);
}

/* ============================================
   RESPONSIVE — SIDEBAR LAYOUT
   ============================================ */

/* Tablet: keep collapsed sidebar */
@media screen and (max-width: 1024px) {
    :root {
        --sidebar-width: 200px;
    }
}

/* Mobile: sidebar off-canvas */
@media screen and (max-width: 768px) {

    /* Sidebar hidden by default, slides in — override collapsed state */
    .app-sidebar,
    .app-sidebar.collapsed {
        transform: translateX(-100%);
        width: 260px;
    }

    .app-sidebar.open {
        transform: translateX(0);
    }

    /* Main content takes full width */
    .main-wrapper,
    .main-wrapper.sidebar-collapsed {
        margin-left: 0;
    }

    /* Show hamburger button */
    .sidebar-toggle-btn {
        display: inline-flex;
    }

    /* Show logo in top header on mobile */
    .top-header-logo {
        display: flex;
    }

    .top-header {
        padding: 0 12px;
    }

    /* Page content less padding */
    .page-content {
        padding: 12px;
    }

    /* Nav adjustments */
    .nav {
        padding: 0.3em;
    }

    .nav li {
        margin: 0 0.4em 0 0;
        padding: 0.2em;
    }

    /* Hide individual steps in pagination */
    .pagination .step, .pagination .currentStep {
        display: none;
    }

    .pagination .prevLink {
        float: left;
    }

    .pagination .nextLink {
        float: right;
    }

    .pagination {
        overflow: hidden;
    }

    /* Forms compact */
    fieldset,
    .property-list {
        padding: 0.3em 0.6em 0.8em;
    }

    input, textarea {
        width: 100%;
        box-sizing: border-box;
    }

    select, input[type=checkbox], input[type=radio], input[type=submit], input[type=button], input[type=reset] {
        width: auto;
    }

    /* Stack form fields */
    .fieldcontain {
        margin-top: 0.5em;
    }

    .fieldcontain label,
    .fieldcontain .property-label,
    .fieldcontain .property-value {
        display: block;
        float: none;
        margin: 0 0 0.2em 0;
        text-align: left;
        width: auto;
    }

    .errors ul,
    .message p {
        margin: 0.5em;
    }

    .error ul {
        margin-left: 0;
    }

    /* Logo smaller on mobile */
    .sidebar-header img {
        height: 24px;
    }

    /* Hide all but first column on very small screens */
    .scaffold-list td:not(:first-child),
    .scaffold-list th:not(:first-child) {
        display: none;
    }

    .scaffold-list thead th {
        text-align: center;
    }

    /* Hide header user info on very small screens */
    .headerUserInfo {
        display: none;
    }

    /* formBtnArea */
    .formBtnArea {
        float: none;
        padding-right: 0;
        padding-bottom: 12px;
        text-align: center;
    }

    /* Legende */
    .legende {
        float: none;
        margin-right: 0;
        margin-bottom: 12px;
    }

    /* lastUpdate */
    .lastUpdate {
        float: none;
        margin-bottom: 8px;
    }
}

/* Very small screens */
@media screen and (max-width: 480px) {
    #page-body {
        margin: 0.8em;
    }

    #page-body h1 {
        margin-top: 0;
    }

    .top-header-user {
        gap: 6px;
    }

    .header-logout-btn {
        padding: 3px 6px;
        font-size: 0.7rem;
    }
}

/* Immersion+ > Dictées : sous 1024 px, une dictée devient une fiche, ses temps empilés avec
   leur intitulé (porté par data-label), au lieu de six colonnes qui ne tiennent pas. */
@media screen and (max-width: 1024px) {
    .immersion-lessons thead {
        display: none;
    }

    .immersion-lessons,
    .immersion-lessons tbody,
    .immersion-lessons tr,
    .immersion-lessons td {
        display: block;
        width: 100%;
        box-sizing: border-box;
    }

    .immersion-lessons tr {
        padding: 8px 0;
        border-bottom: 1px solid var(--border-input);
    }

    .immersion-lessons td {
        padding: 4px 0;
    }

    .immersion-lessons .actions {
        text-align: left;
        white-space: normal;
    }

    .immersion-lessons td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: var(--font-xs);
        color: var(--text-muted);
        text-transform: uppercase;
        margin-bottom: 2px;
    }
}

/* Immersion+ : la table des GROUPES s'empile elle aussi. Sa soeur interieure — les lecons — le
   faisait depuis les dictees, mais celle-ci gardait ses trois colonnes a toutes les largeurs :
   nom du groupe et adaptations, pastille et pli, bouton de lot. Sur un telephone, elles se
   serrent jusqu'a l'illisible et la page deborde en largeur.

   Le retrait de la ligne des lecons disparait ici : sur 375 px, seize pixels rendus a la
   lecture valent mieux qu'une indentation decorative. */
@media screen and (max-width: 1024px) {
    .immersion-groups thead {
        display: none;
    }

    .immersion-groups,
    .immersion-groups tbody,
    .immersion-groups tr,
    .immersion-groups td {
        display: block;
        width: 100%;
        box-sizing: border-box;
    }

    .immersion-groups > tbody > tr {
        padding: var(--space-sm) 0;
        border-bottom: 1px solid var(--border-input);
    }

    .immersion-groups .group-actions {
        text-align: left;
    }

    .immersion-groups .group-lessons {
        padding: 0 0 var(--space-md) 0;
    }

    .immersion-groups > tbody > tr > td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: var(--font-xs);
        color: var(--text-muted);
        text-transform: uppercase;
        margin-bottom: 2px;
    }

    /* Ce qui se saisit prend toute la largeur : un textarea de paroles ou un menu de style
       calibres pour une colonne de bureau depassent sinon du telephone. */
    .immersion-lessons textarea,
    .immersion-lessons select,
    .immersion-lessons input[type="text"] {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }

    /* ⚠️ SPÉCIFICITÉ : les largeurs de bureau sont posées sur `.immersion-lessons .lesson` et
       `.immersion-lessons th.text` — deux classes —, alors que l'empilement les remettait à 100 %
       sur `.immersion-lessons td`, une classe et un élément. Moins spécifique, donc perdant : la
       colonne des leçons gardait ses 14 %, une cinquantaine de pixels sur un téléphone, et le
       sujet s'y cassait LETTRE PAR LETTRE. Ces règles doivent donc viser les mêmes sélecteurs,
       pas leur parent. */
    .immersion-lessons .lesson,
    .immersion-lessons th.text,
    .immersion-lessons .actions {
        width: 100%;
        max-width: none;
        white-space: normal;
    }

    .immersion-lessons .lesson .topic {
        max-width: none;
    }
}

/* ---------------------------------------------------------------------------
   UNE TABLE QUI S'EMPILE EN FICHES — la regle generique, et la troisieme demande
   l'a rendue necessaire. Les tables d'Immersion+ portaient chacune la sienne ;
   celle-ci vaut pour toute liste qui ne tient pas en largeur.

   Poser `stacked` sur la table, et `data-label` sur les cellules qui doivent
   annoncer leur colonne. Le reste suit.

   ⚠️ SPECIFICITE : une largeur de bureau posee sur `.ma-table .ma-colonne` — deux
   classes — bat un `width: 100%` ecrit sur `.stacked td`, une classe et un
   element. La colonne garde alors sa largeur de bureau et son contenu se casse
   lettre par lettre. C'est arrive le 13/09/2026 : viser les memes selecteurs.
   --------------------------------------------------------------------------- */
@media screen and (max-width: 1024px) {
    table.stacked thead {
        display: none;
    }

    table.stacked,
    table.stacked tbody,
    table.stacked tr,
    table.stacked td {
        display: block;
        width: 100%;
        max-width: none;
        box-sizing: border-box;
        white-space: normal;
    }

    table.stacked > tbody > tr {
        padding: var(--space-sm) 0;
        border-bottom: 1px solid var(--border-input);
    }

    table.stacked > tbody > tr > td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: var(--font-xs);
        color: var(--text-muted);
        text-transform: uppercase;
        margin-bottom: 2px;
    }

    table.stacked .actions {
        text-align: left;
    }
}

/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS file within this directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require theme
*= require main
*= require themes/ui-lightness/jquery-ui-1.10.4.custom.min
*= require errors
*= require style
*= require mobile
*/

