/**
 * OD Connect — thème mini-apps par défaut.
 *
 * Palette + identité visuelle alignées 1:1 sur `miniapps/app_main/assets/style.css`
 * (référence historique). Toutes les classes du framework sont préfixées
 * `.miniapp-*` pour éviter les collisions avec d'autres bundles, mais
 * suivent la structure BEM d'app_main (`__sub-element`, `--modifier`).
 *
 * Cf. §1.3 + §7.2 du doc proposition.
 *
 * Note typo : fonts Rajdhani/Nunito référencées mais non bundlées (anti-CDN
 * §1.2.1). Fallback `system-ui` couvre l'essentiel. Pour rendu strict,
 * self-host les woff2 via `config/miniapp/theme/fonts/`.
 */

:root {
    /* ════════ Palette OD Connect ════════ */
    --clr-bg:           #f5f7fa;
    --clr-surface:      #ffffff;
    --clr-surface-alt:  #f8f9fb;
    --clr-border:       #e2e6ec;
    --clr-border-light: #edf0f4;

    --clr-navy:         #1b2a4a;
    --clr-navy-light:   #263c66;
    --clr-navy-dark:    #111d36;
    --clr-navy-deep:    #0c1528;

    --clr-blue-mid:     #2e6daa;
    --clr-blue-light:   #4a8cc8;
    --clr-blue-pale:    #d6e6f5;

    --clr-teal:         #3ab5b0;
    --clr-teal-light:   #5ccec9;
    --clr-teal-pale:    #e6f7f6;

    --clr-pink:         #e84393;
    --clr-pink-pale:    #fde8f2;
    --clr-orange:       #f5a623;
    --clr-orange-pale:  #fef5e0;

    --clr-danger:       #d44040;
    --clr-text:         #1b2a4a;
    --clr-text-2:       #4a5b72;
    --clr-text-3:       #8e97a6;

    /* ════════ Typo ════════ */
    --ff-display: 'Rajdhani', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --ff-body:    'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;

    /* ════════ Tokens divers ════════ */
    --radius:     6px;
    --radius-lg:  10px;

    --shadow-sm:  0 2px 8px rgba(27, 42, 74, .06);
    --shadow-md:  0 6px 24px rgba(27, 42, 74, .10);

    --sidebar-w:  260px;
    --topbar-h:   60px;
    --transition: .22s cubic-bezier(.4, 0, .2, 1);

    /* ════════ Surcharge Bootstrap 5 ════════ */
    --bs-primary:                 var(--clr-navy);
    --bs-primary-rgb:             27, 42, 74;
    --bs-secondary:               var(--clr-blue-mid);
    --bs-secondary-rgb:           46, 109, 170;
    --bs-info:                    var(--clr-teal);
    --bs-info-rgb:                58, 181, 176;
    --bs-warning:                 var(--clr-orange);
    --bs-warning-rgb:             245, 166, 35;
    --bs-danger:                  var(--clr-danger);
    --bs-danger-rgb:              212, 64, 64;
    --bs-success:                 var(--clr-teal);
    --bs-success-rgb:             58, 181, 176;

    --bs-link-color:              var(--clr-blue-mid);
    --bs-link-color-rgb:          46, 109, 170;
    --bs-link-hover-color:        var(--clr-teal);
    --bs-link-hover-color-rgb:    58, 181, 176;

    --bs-body-color:              var(--clr-text);
    --bs-body-bg:                 var(--clr-bg);
    --bs-body-font-family:        var(--ff-body);
    --bs-body-font-size:          0.95rem;
    --bs-body-line-height:        1.6;

    --bs-border-color:            var(--clr-border);
    --bs-border-radius:           var(--radius);
    --bs-border-radius-lg:        var(--radius-lg);
}

* { box-sizing: border-box; }

/* ════════ Form controls — fond blanc explicite ════════ */

/* Bootstrap dérive `--bs-form-control-bg` de `--bs-body-bg` ; comme notre
   theme met `--bs-body-bg` à `--clr-bg` (gris pâle de fond d'app), tous
   les inputs héritent de ce gris — ce qui crée une confusion avec l'état
   disabled/readonly. On force le fond blanc sur les inputs *actifs*, et
   on garde un gris distinct pour disabled/readonly. */
.form-control,
.form-select,
.input-group-text {
    background-color: #fff;
}

.form-control:disabled,
.form-control[readonly],
.form-select:disabled {
    background-color: var(--clr-surface-alt);
}

/* Champs `widget: month` (sélecteur de mois, type=month) : on déplace l'icône
   d'ouverture du calendrier à GAUCHE du champ. Présentation pure → CSS, pas de
   JS (cf. règle de moindre puissance). On réserve la place à gauche via
   padding-left et on positionne le pseudo-élément natif en absolu dans ce gap.
   WebKit/Blink uniquement (Chrome, Edge, Safari) — Firefox dégrade type=month
   en champ texte sans icône, donc la règle y est simplement sans effet. */
.form-control[type="month"] {
    position: relative;
    padding-left: 2.25rem;
}

.form-control[type="month"]::-webkit-calendar-picker-indicator {
    position: absolute;
    left: 0.75rem;
    margin: 0;
}

/* ════════ Layout shell ════════ */
body.miniapp-shell {
    margin: 0;
    min-height: 100vh;
    background: var(--clr-bg);
    color: var(--clr-text);
    font-family: var(--ff-body);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    /* Garde-fou contre tout débordement résiduel sur petits écrans (mots
       longs non wrap, sidebar translateX caché, etc.). Ne masque rien de
       fonctionnel — un vrai overflow vertical reste géré normalement. */
    overflow-x: hidden;
}

.miniapp-layout {
    display: flex;
    min-height: 100vh;
}

.miniapp-layout__main {
    flex: 1;
    margin-left: var(--sidebar-w);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    /* `min-width: 0` requis sur un flex child pour qu'il puisse rétrécir
       en-dessous de son contenu intrinsèque — sans ça, flex-shrink est
       inerte et le contenu déborde latéralement (cause des scrollbars
       horizontaux résiduels sur mobile). */
    min-width: 0;
}

/* ════════ SIDEBAR — Dégradé navy diagonal + tricolore haut ════════ */
.miniapp-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--sidebar-w);
    height: 100vh;
    background: linear-gradient(160deg, var(--clr-navy-deep) 0%, var(--clr-navy) 35%, var(--clr-blue-mid) 100%);
    color: #fff;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    z-index: 100;
}

.miniapp-sidebar::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--clr-teal), var(--clr-pink), var(--clr-orange));
}

.miniapp-sidebar__brand {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 24px 20px 20px;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.miniapp-sidebar__logo {
    width: 42px;
    height: 42px;
    border: 2px solid rgba(255, 255, 255, .3);
    border-radius: var(--radius);
    background: rgba(255, 255, 255, .08);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--ff-display);
    font-size: 13px;
    font-weight: 800;
    letter-spacing: .04em;
    color: #fff;
    position: relative;
    flex-shrink: 0;
}

.miniapp-sidebar__logo::after {
    content: '';
    position: absolute;
    top: -2px;
    right: -2px;
    width: 10px;
    height: 10px;
    border-top: 2px solid var(--clr-teal-light);
    border-right: 2px solid var(--clr-teal-light);
}

.miniapp-sidebar__brand-text {
    font-family: var(--ff-display);
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    line-height: 1.2;
}

.miniapp-sidebar__brand-text small {
    display: block;
    font-family: var(--ff-body);
    font-size: .6rem;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: .1em;
    opacity: .4;
    margin-top: 2px;
}

.miniapp-sidebar__nav {
    flex: 1;
    padding: 8px 10px;
}

.miniapp-sidebar__section {
    margin-bottom: 4px;
}

.miniapp-sidebar__section-title {
    font-family: var(--ff-display);
    font-size: .65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: rgba(255, 255, 255, .4);
    padding: 16px 14px 6px;
}

.miniapp-sidebar__link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-radius: var(--radius);
    color: rgba(255, 255, 255, .55);
    font-family: var(--ff-body);
    font-size: .87rem;
    font-weight: 600;
    text-decoration: none;
    border-left: 2px solid transparent;
    transition: all var(--transition);
}

.miniapp-sidebar__link:hover {
    color: #fff;
    background: rgba(255, 255, 255, .08);
    border-left-color: rgba(255, 255, 255, .3);
}

.miniapp-sidebar__link--active {
    color: #fff;
    background: rgba(255, 255, 255, .12);
    border-left-color: var(--clr-orange);
    font-weight: 700;
}

.miniapp-sidebar__link i {
    opacity: .5;
    flex-shrink: 0;
    font-size: 1.05rem;
}

.miniapp-sidebar__link:hover i {
    opacity: 1;
    color: var(--clr-teal-light);
}

.miniapp-sidebar__link--active i {
    opacity: 1;
    color: var(--clr-orange);
}

/* ════════ TOPBAR ════════ */
.miniapp-topbar {
    height: var(--topbar-h);
    background: var(--clr-surface);
    border-bottom: 1px solid var(--clr-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 28px;
    position: sticky;
    top: 0;
    z-index: 50;
}

.miniapp-topbar__left,
.miniapp-topbar__right {
    display: flex;
    align-items: center;
    gap: 10px;
}

.miniapp-topbar__menu-btn {
    /* Toujours visible (desktop + mobile) : desktop il déclenche le collapse
       icons-only, mobile il ouvre le drawer off-canvas. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: none;
    background: none;
    cursor: pointer;
    color: var(--clr-navy);
    border-radius: var(--radius);
}

.miniapp-topbar__menu-btn:hover {
    background: var(--clr-bg);
}

/* Logo OD Connect dans la topbar — cliquable vers le dashboard. */
.miniapp-topbar__logo {
    display: inline-flex;
    align-items: center;
}

.miniapp-topbar__logo img {
    height: 36px;
    width: auto;
    display: block;
}

/* Dropdown trigger (lang + user). */
.miniapp-dropdown {
    position: relative;
}

.miniapp-dropdown__trigger {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--clr-border);
    border-radius: var(--radius);
    background: var(--clr-surface);
    cursor: pointer;
    font-family: var(--ff-body);
    font-size: .82rem;
    font-weight: 700;
    color: var(--clr-navy);
    text-decoration: none;
    transition: all var(--transition);
}

.miniapp-dropdown__trigger:hover {
    border-color: var(--clr-blue-mid);
    color: var(--clr-blue-mid);
}

/* User badge pill avec avatar circulaire. */
.miniapp-topbar__user {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 12px 5px 5px;
    border-radius: 30px;
    background: var(--clr-surface-alt);
    border: 1px solid var(--clr-border);
    color: var(--clr-navy);
    text-decoration: none;
}

.miniapp-topbar__user:hover {
    border-color: var(--clr-blue-mid);
    color: var(--clr-navy);
}

.miniapp-topbar__avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--clr-navy), var(--clr-blue-mid));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--ff-display);
    font-size: .75rem;
    font-weight: 800;
    flex-shrink: 0;
    letter-spacing: .02em;
}

.miniapp-topbar__username {
    font-size: .85rem;
    font-weight: 700;
    color: var(--clr-navy);
}

/* Logout link with icon (separate from user dropdown). */
.miniapp-topbar__logout {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border-radius: var(--radius);
    color: var(--clr-text-3);
    font-size: .82rem;
    font-weight: 600;
    text-decoration: none;
    transition: all var(--transition);
}

.miniapp-topbar__logout:hover {
    color: var(--clr-pink);
    background: var(--clr-pink-pale);
}

/* ════════ Main content ════════ */
.miniapp-content {
    flex: 1;
    padding: 30px 32px;
    background: var(--clr-surface);
}

/* F6 (POC SupplierProfile, 2026-05-27) : en mode dev, la Symfony Web
   Debug Toolbar (`.sf-toolbar`, position fixed bottom) recouvre les
   30-40 px les plus bas de la page — y compris le bouton « Enregistrer »
   ou les actions du footer. On réserve l'espace via :has() (supporté
   par tous les navigateurs cibles depuis fin 2023). Coût en prod :
   nul — la règle ne s'applique que si la toolbar est présente. */
body:has(.sf-toolbar) .miniapp-layout__main {
    padding-bottom: 48px;
}

.miniapp-page-header {
    margin-bottom: 28px;
}

.miniapp-page-header__title {
    font-family: var(--ff-display);
    font-size: 1.6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--clr-navy);
    line-height: 1.2;
    margin: 0;
}

.miniapp-page-header__sub {
    font-size: .88rem;
    color: var(--clr-text-2);
    margin-top: 4px;
    font-weight: 400;
}

/* Lien « Retour à la liste » en haut des pages view/edit/new — style
   discret mais distinct (pas un simple lien bleu) avec hover marqué. */
.miniapp-page-header__sub a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 14px;
    border-radius: 999px;
    background: var(--clr-blue-pale);
    color: var(--clr-blue-mid);
    font-weight: 500;
    font-size: .82rem;
    transition: background var(--transition), color var(--transition);
}

.miniapp-page-header__sub a:hover {
    background: var(--clr-navy);
    color: #fff;
    text-decoration: none;
}

.miniapp-page-header__sub a i {
    font-size: .85rem;
}

/* ════════ Onglets nav-tabs modernisés ════════ */

.miniapp-content .nav-tabs {
    border-bottom: 1px solid var(--clr-border);
    gap: 4px;
}

.miniapp-content .nav-tabs .nav-link {
    border: 0;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    padding: 10px 16px;
    color: var(--clr-text-3);
    font-weight: 500;
    background: transparent;
    transition: color var(--transition), border-color var(--transition);
}

.miniapp-content .nav-tabs .nav-link:hover {
    color: var(--clr-navy);
    border-bottom-color: var(--clr-border);
}

.miniapp-content .nav-tabs .nav-link.active {
    color: var(--clr-navy);
    background: transparent;
    border-bottom-color: var(--clr-teal);
    font-weight: 600;
}

/* Headings dans le contenu. */
.miniapp-content h1,
.miniapp-content h2,
.miniapp-content h3,
.miniapp-content h4 {
    font-family: var(--ff-display);
    color: var(--clr-navy);
    font-weight: 700;
}

.miniapp-content h1 {
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* SDK / info banner. */
.miniapp-banner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    background: var(--clr-blue-pale);
    border-left: 3px solid var(--clr-blue-mid);
    border-radius: 0;
    font-size: .84rem;
    color: var(--clr-navy);
    margin-bottom: 28px;
}

.miniapp-banner code {
    font-family: 'Courier New', monospace;
    font-size: .8rem;
    background: rgba(46, 109, 170, .12);
    color: var(--clr-blue-mid);
    padding: 1px 6px;
    border-radius: 3px;
}

/* ════════ Boutons primaires ════════ */
.btn-primary {
    --bs-btn-bg:                 var(--clr-navy);
    --bs-btn-border-color:       var(--clr-navy);
    --bs-btn-hover-bg:           var(--clr-navy-light);
    --bs-btn-hover-border-color: var(--clr-navy-light);
    --bs-btn-active-bg:          var(--clr-navy-dark);
    --bs-btn-active-border-color: var(--clr-navy-dark);
    --bs-btn-disabled-bg:        var(--clr-navy);
    --bs-btn-disabled-border-color: var(--clr-navy);
    font-family: var(--ff-body);
    font-weight: 700;
}

.btn-outline-secondary {
    --bs-btn-color:              var(--clr-navy);
    --bs-btn-border-color:       var(--clr-border);
    --bs-btn-hover-bg:           var(--clr-surface);
    --bs-btn-hover-border-color: var(--clr-blue-mid);
    --bs-btn-hover-color:        var(--clr-blue-mid);
}

/* ════════ Dashboard cards — header coloré + body navy ════════ */
/* La carte est un <div> wrapper autour d'un <a class="miniapp-card__link">.
   Cette séparation permet à SortableJS d'attacher un handle (le grip) hors
   du <a> sans subir le drag-link natif du navigateur. */
.miniapp-card {
    display: flex;
    flex-direction: column;
    background: var(--clr-surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: all var(--transition);
    position: relative;
    /* Bootstrap `.row` étire les `.col-*` à la hauteur de la ligne via
       `align-items: stretch` (défaut flex). On force la carte à remplir
       cette hauteur, sinon les descriptions de longueurs différentes
       (« Annuaire CRM unifié — personnes et organisations. » vs
       « Gestion des comptes utilisateurs OD Connect. ») cassent l'alignement. */
    height: 100%;
}

.miniapp-card__link {
    display: flex;
    flex-direction: column;
    color: var(--clr-text);
    cursor: pointer;
    text-decoration: none;
    /* Le lien interne doit lui aussi occuper toute la carte pour que
       `.miniapp-card__body { flex: 1 }` ait un parent à étirer. */
    flex: 1;
}

.miniapp-card__link:hover {
    color: var(--clr-text);
}

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

/* Handle drag-and-drop — visible au hover du wrapper, ou en permanence sur
   touch (pas de hover). Position absolue pour ne pas perturber le layout
   interne de la carte. */
.miniapp-card__grip {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.85);
    color: var(--clr-text-muted, #6c757d);
    cursor: grab;
    opacity: 0;
    transition: opacity var(--transition);
    user-select: none;
}

.miniapp-card__grip:active {
    cursor: grabbing;
}

.miniapp-card:hover .miniapp-card__grip {
    opacity: 1;
}

/* Touch devices : grip toujours visible (pas de hover). */
@media (hover: none) {
    .miniapp-card__grip {
        opacity: 0.6;
    }
}

.miniapp-card__icon {
    width: 100%;
    height: 100px;
    background: var(--card-bg, var(--clr-blue-pale));
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--card-color, var(--clr-navy));
    transition: transform var(--transition);
    position: relative;
}

.miniapp-card__icon i {
    font-size: 2.25rem;
}

.miniapp-card__icon::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    right: 0;
    height: 22px;
    background: var(--clr-navy);
    clip-path: polygon(0 100%, 100% 100%, 100% 0, 50% 70%, 0 0);
}

.miniapp-card__body {
    background: var(--clr-navy);
    color: #fff;
    padding: 18px 20px 20px;
    flex: 1;
    position: relative;
}

.miniapp-card__title {
    font-family: var(--ff-display);
    font-size: 1rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    margin: 0 0 6px;
    color: #fff;
}

.miniapp-card__desc {
    font-size: .78rem;
    color: rgba(255, 255, 255, .55);
    line-height: 1.45;
    margin: 0;
}

.miniapp-card:hover .miniapp-card__icon {
    transform: scale(1.04);
}

/* ════════ FOOTER Odontolia ════════ */
.miniapp-footer {
    background: var(--clr-navy);
    color: rgba(255, 255, 255, .7);
    margin-top: auto;
    position: relative;
}

.miniapp-footer::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--clr-teal), var(--clr-pink), var(--clr-orange), transparent 80%);
}

.miniapp-footer__inner {
    display: grid;
    grid-template-columns: 1.4fr 0.6fr 1fr 1fr;
    gap: 32px;
    padding: 36px 32px 28px;
    align-items: start;
}

.miniapp-footer__logo {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 18px;
}

/* Plaque blanche : le logo Odontolia est en marine sur transparent, illisible
   directement sur le footer marine — la plaque garantit le contraste tout en
   préservant les couleurs de marque. */
.miniapp-footer__logo-chip {
    display: inline-flex;
    align-items: center;
    background: #fff;
    padding: 8px 14px;
    border-radius: var(--radius);
}

.miniapp-footer__logo-chip img,
.miniapp-footer__logo-chip svg {
    height: 40px;
    width: auto;
    display: block;
}

.miniapp-footer__brand-name {
    font-family: var(--ff-display);
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: .08em;
    color: #fff;
}

.miniapp-footer__legal {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.miniapp-footer__legal a {
    font-size: .78rem;
    color: rgba(255, 255, 255, .4);
    text-decoration: none;
    transition: color var(--transition);
}

.miniapp-footer__legal a:hover {
    color: var(--clr-teal-light);
}

.miniapp-footer__col--social {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 4px;
}

.miniapp-footer__social-link {
    width: 36px;
    height: 36px;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, .4);
    text-decoration: none;
    transition: all var(--transition);
}

.miniapp-footer__social-link:hover {
    border-color: var(--clr-pink);
    color: var(--clr-pink);
    background: rgba(232, 67, 147, .08);
}

.miniapp-footer__col--contact {
    font-size: .84rem;
    line-height: 1.7;
    padding-top: 4px;
}

.miniapp-footer__col--contact p {
    margin: 0;
    color: rgba(255, 255, 255, .6);
}

.miniapp-footer__email {
    color: var(--clr-teal-light) !important;
    margin-top: 6px !important;
    display: block;
    text-decoration: none;
}

.miniapp-footer__col--cta {
    font-size: .82rem;
    padding-top: 4px;
    color: rgba(255, 255, 255, .5);
}

.miniapp-footer__copy {
    display: block;
    margin-top: 12px;
    font-size: .72rem;
    color: rgba(255, 255, 255, .25);
}

/* ════════ Bootstrap alerts — accent OD ════════ */
.alert-warning {
    background: var(--clr-orange-pale);
    border-color: var(--clr-orange);
    color: var(--clr-text);
}

.alert-info {
    background: var(--clr-blue-pale);
    border-left: 3px solid var(--clr-blue-mid);
    border-radius: 0;
    color: var(--clr-navy);
}

/* ════════ Dropdowns ════════ */
.dropdown-menu {
    border-color: var(--clr-border);
    box-shadow: var(--shadow-md);
    font-family: var(--ff-body);
}

.dropdown-item:hover {
    background: var(--clr-blue-pale);
    color: var(--clr-blue-mid);
}

.dropdown-item.active {
    background: var(--clr-blue-pale);
    color: var(--clr-navy);
    font-weight: 700;
}

code {
    font-family: 'Courier New', monospace;
    background: rgba(46, 109, 170, .08);
    color: var(--clr-blue-mid);
    padding: 1px 6px;
    border-radius: 3px;
    font-size: .85em;
}

/* ════════ CRUD list — table dense avec thead sombre ════════ */

/* Le card englobant : fond blanc explicite (notre theme override le
   --bs-card-bg par var(--clr-bg) gris pâle) + overflow hidden pour clipper
   les coins. Retrait de la bordure Bootstrap par défaut (`rgba(0,0,0,.176)`)
   au profit d'une box-shadow plus douce — pas de cadre visible mais une
   délimitation visuelle légère. NB : `.table-responsive` (overflow-x: auto)
   à l'intérieur casse le clipping du card, c'est pour ça qu'on pose aussi
   le radius directement sur le premier/dernier `th` du thead — voir plus bas. */
.miniapp-content .card {
    background-color: #fff;
    border: 0;
    /* Pas d'overflow:hidden : sinon les popovers des pills cliquables
       sont clippés en bas du tableau. Les coins arrondis du thead sont
       préservés via les `border-top-{left,right}-radius` directs sur
       les `<th>` de coin (cf. règles ci-dessous). */
    overflow: visible;
    border-radius: 6px;
}

/* Workaround pour table-responsive qui casse le clipping du card englobant :
   on arrondit explicitement les coins supérieurs des cellules `th` de coin
   du thead. Cela donne un thead visuellement clipé même quand le card ne
   peut plus clipper son contenu. */
.miniapp-content .card > .card-body > .table-responsive > .table > thead > tr > th:first-child {
    border-top-left-radius: 6px;
}

.miniapp-content .card > .card-body > .table-responsive > .table > thead > tr > th:last-child {
    border-top-right-radius: 6px;
}

/* Cibler la table CRUD via la card englobante évite d'impacter d'éventuelles
   tables Bootstrap utilisées ailleurs (e.g. dashboard ou formulaires). */
.miniapp-content .card > .card-body > .table-responsive > .table {
    margin-bottom: 0;
}

/* `.table-responsive` Bootstrap pose `overflow: auto` qui clip les
   popovers des pills cliquables et déclenche des scrollbars verticaux
   quand le popover dépasse le bas du tableau. On force `visible` ici
   car les listes CRUD ont des colonnes compactes (pas de besoin de
   scroll horizontal). Les mini-apps avec table très large peuvent
   surcharger localement. */
/* `overflow-x: auto` (vs `visible` historique) : on accepte que les pill
   popovers (cf. preview clinics dans dentists) soient clippés horizontalement
   sur écrans étroits — en échange, les tables larges (ex. `_audit_logs` avec
   8 colonnes) ne forcent plus l'élargissement du document entier.
   `overflow-y: visible` préserve quand même la possibilité de débordement
   vertical (pour les popovers above/below qui restent utiles). */
.miniapp-content .card > .card-body > .table-responsive {
    overflow-x: auto;
    overflow-y: visible;
}

/* Pas de séparateur visible entre filter bar et thead — la transition
   du blanc vers le navy du thead est suffisamment marquée. */

.miniapp-content .card > .card-body > .table-responsive > .table > thead > tr > th {
    background: var(--clr-navy);
    color: #fff;
    font-weight: 600;
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 10px 12px;
    border-bottom: 0;
    white-space: nowrap;
}

.miniapp-content .card > .card-body > .table-responsive > .table > thead > tr > th a {
    color: #fff !important;
}

.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr > td {
    padding: 8px 12px;
    vertical-align: middle;
    font-size: .9rem;
    border-color: var(--clr-border-light);
}

/* ════════ Résultats du search global (Mode B) ════════ */

.miniapp-search-result {
    padding: 8px 12px;
    white-space: normal;
    line-height: 1.3;
}

.miniapp-search-result__key {
    font-weight: 600;
    color: var(--clr-navy);
    font-size: .85rem;
}

.miniapp-search-result__label {
    font-size: .78rem;
    color: var(--clr-text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 2px;
}

/* ════════ Filtres list (input-group inline) ════════ */

/* Label uppercase compact au préfixe des selects de filtres (« STATUT »). */
.miniapp-filters__label {
    background: #fff;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .72rem;
    font-weight: 600;
    color: var(--clr-text-2);
}

/* ════════ Pills (cellules badges réutilisables) ════════ */

/* Émise par `formatListRow()` des mini-apps (ex. DentistsMiniapp pour
   `inami` et `clinics`). Style commun pour rester cohérent à travers le bundle. */
.miniapp-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--clr-blue-pale);
    color: var(--clr-navy);
    font-size: .8rem;
    font-weight: 500;
    line-height: 1.4;
}

.miniapp-pill + .miniapp-pill {
    margin-left: 4px;
}

.miniapp-pill--mono {
    font-family: ui-monospace, 'SF Mono', Menlo, monospace;
    letter-spacing: .02em;
}

/* Marqueur de rôle DANS une pill (« Chef de clinique », 2026-09-02).
   Le sélecteur ENFANT DIRECT est délibéré : le `<i>` du lien « Consulter » du
   popover vit lui aussi sous `.miniapp-pill`, mais deux niveaux plus bas — un
   sélecteur descendant le rapetisserait au passage. */
.miniapp-pill > i {
    font-size: .85em;
    opacity: .8;
}

/* Pill cliquable (avec data-miniapp-preview) : cursor + hover marqué.
   Z-index élevé seulement quand le popover est ouvert pour passer
   au-dessus des pills voisines (chaque pill crée son propre stacking
   context via position:relative, donc le z-index du popover seul ne
   suffit pas). */
.miniapp-pill--clickable {
    cursor: pointer;
    position: relative;
    transition: filter var(--transition);
}

.miniapp-pill--clickable.miniapp-pill--open {
    z-index: 1080;
}

.miniapp-pill--clickable:hover {
    filter: brightness(.92);
}

.miniapp-pill--clickable:focus-visible {
    outline: 2px solid var(--clr-blue-mid);
    outline-offset: 2px;
}

/* Popover affiché au hover/click d'une pill cliquable. Position absolue
   par rapport à la pill (qui est `position: relative`). Alpine pilote la
   visibilité via `x-show` (display none/block). */
.miniapp-pill-preview {
    display: block;
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    min-width: 240px;
    max-width: 320px;
    background: #fff;
    color: var(--clr-text);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(27, 42, 74, .15);
    padding: 0;
    z-index: 1080;
    text-align: left;
    font-weight: 400;
    font-size: .85rem;
    line-height: 1.5;
    text-decoration: none;
    text-transform: none;
    letter-spacing: normal;
    cursor: default;
}

[x-cloak] { display: none !important; }

.miniapp-pill-preview__loading,
.miniapp-pill-preview__error {
    padding: 12px 16px;
    color: var(--clr-text-3);
    text-align: center;
}

.miniapp-pill-preview__error {
    color: var(--clr-danger);
}

/* Contenu de la card preview (rendu par `crud/preview.html.twig`). */
.miniapp-preview-card {
    overflow: hidden;
}

.miniapp-preview-card--inactive {
    opacity: .9;
}

.miniapp-preview-card__header {
    padding: 10px 14px;
    background: var(--clr-navy);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.miniapp-preview-card__header strong {
    font-weight: 600;
    font-size: .9rem;
}

.miniapp-preview-card__badge {
    font-size: .65rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 2px 6px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .2);
    color: #fff;
    font-weight: 600;
}

.miniapp-preview-card__fields {
    margin: 0;
    padding: 12px 14px;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 12px;
}

/* Variantes <dt>/<dd> (template Twig serveur) OU <span>/<span> avec
   classes explicites (renderStaticPopover PHP). Les deux supportés. */
.miniapp-preview-card__fields dt,
.miniapp-preview-card__label {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--clr-text-3);
    font-weight: 600;
    margin: 0;
}

.miniapp-preview-card__fields dd,
.miniapp-preview-card__value {
    margin: 0;
    color: var(--clr-text);
    font-size: .85rem;
}

.miniapp-preview-card__footer {
    padding: 8px 14px;
    border-top: 1px solid var(--clr-border-light);
    background: var(--clr-surface-alt);
}

.miniapp-preview-card__link {
    color: var(--clr-blue-mid);
    font-weight: 500;
    font-size: .82rem;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.miniapp-preview-card__link:hover {
    color: var(--clr-navy);
}

/* ⚠️ Le texte était en `var(--clr-teal)` sur fond pâle : 2,26:1 MESURÉ, très en
   dessous du seuil AA de 4,5:1. Et ce n'était pas théorique — cette variante
   porte la pill « Provisoire » de la colonne INAMI et le code de clinique à
   acronyme provisoire, c'est-à-dire très exactement ce que les bascules
   « INAMI provisoire » et « Acronyme provisoire » servent à isoler : un lecteur
   malvoyant filtrait pour obtenir une liste dont le marqueur justifiant le
   filtrage était le moins lisible de l'écran.
   Le signal porte désormais le FOND, le texte reste navy (~13:1) — même
   arbitrage que `--amber`, dont le contraste a été mesuré à 13,1:1. */
.miniapp-pill--teal {
    background: var(--clr-teal-pale);
    color: var(--clr-navy);
}

/* Clinique DIRIGÉE sans affectation active (« Chef de clinique », 2026-09-09).
   ⚠️ Volontairement PAS un décalque de `--teal`, qui fait `color: var(--clr-teal)`
   sur fond pâle — environ 2,3:1, déjà sous le seuil WCAG AA de 4,5:1. Décalqué
   en orange ce serait ~1,9:1, l'orange étant bien plus clair que le teal.
   La couleur vit donc dans le FOND, qui porte tout le signal, et le texte reste
   en navy : ~12:1. (Le contraste de `--teal` est un défaut préexistant, hors
   périmètre de cette salve — ne pas le « corriger » au passage.) */
.miniapp-pill--amber {
    background: var(--clr-orange-pale);
    color: var(--clr-navy);
    /* ⚠️ La police monospace de `--mono` est REPRISE ici, et ce n'est pas une
       coquetterie : la pill ambre porte exactement la même donnée que ses
       voisines — un code court de clinique — et une variante ne peut pas en
       changer la typographie sans donner à lire deux natures différentes.
       Constaté au navigateur le 2026-09-09 : `31_TUBIZ` en proportionnelle à
       côté de `30_WAROC` en chasse fixe, sur la même ligne. */
    font-family: ui-monospace, 'SF Mono', Menlo, monospace;
    letter-spacing: .02em;
}

/* ⚠️ Bootstrap 5.3 FIGE `#0d6efd` / `#198754` DANS les classes `.btn-outline-*` :
   la surcharge de `--bs-primary` / `--bs-success` au `:root` ne les atteint PAS.
   Le thème le savait déjà — `.btn-primary` et `.btn-outline-secondary` sont
   surchargés par `--bs-btn-*` plus haut — mais ces deux familles-ci avaient été
   oubliées, et ce sont précisément les deux présentes dans la barre de filtres.
   Résultat : des bascules et des exports peints dans deux teintes qui n'ont
   AUCUN nom dans le système. */
.btn-outline-primary {
    --bs-btn-color:                 var(--clr-blue-mid);
    --bs-btn-border-color:          var(--clr-blue-mid);
    --bs-btn-hover-bg:              var(--clr-blue-mid);
    --bs-btn-hover-border-color:    var(--clr-blue-mid);
    --bs-btn-active-bg:             var(--clr-navy);
    --bs-btn-active-border-color:   var(--clr-navy);
    --bs-btn-focus-shadow-rgb:      46, 109, 170;
    --bs-btn-disabled-color:        var(--clr-blue-mid);
    --bs-btn-disabled-border-color: var(--clr-blue-mid);
}

/* ⚠️ PAS de texte teal sur blanc : `#3ab5b0` sur `#fff` = 2,49:1, très en
   dessous du seuil AA de 4,5:1. Le texte reste donc navy et le teal ne sert
   que d'accent de bordure et de fond au survol. Même arbitrage que la pill
   ambre : le SIGNAL porte le fond, la LISIBILITÉ porte le texte. */
.btn-outline-success {
    --bs-btn-color:                 var(--clr-navy);
    --bs-btn-border-color:          var(--clr-teal);
    --bs-btn-hover-bg:              var(--clr-teal-pale);
    --bs-btn-hover-color:           var(--clr-navy);
    --bs-btn-hover-border-color:    var(--clr-teal);
    --bs-btn-active-bg:             var(--clr-teal-pale);
    --bs-btn-active-color:          var(--clr-navy);
    --bs-btn-active-border-color:   var(--clr-teal);
    --bs-btn-focus-shadow-rgb:      58, 181, 176;
}

/* Anneau de focus maison — y compris celui que Tom Select pose lui-même, sinon
   le filtre Clinique garderait l'anneau bleu Bootstrap quand ses quatre voisins
   passent au bleu du thème. */
.form-control:focus,
.form-select:focus,
.focus .ts-control {
    border-color: var(--clr-blue-light);
    box-shadow: 0 0 0 .25rem rgba(46, 109, 170, .25);
}

/* ⚠️ `.form-control:focus` de Bootstrap (0,2,0) rétablit `--bs-body-bg`, donc le
   gris `#f5f7fa`, par-dessus le `background: #fff` du thème (0,1,0). Un champ
   FOCUSÉ prenait ainsi la couleur d'un champ DÉSACTIVÉ — exactement la
   confusion que le thème cherche à éviter ailleurs. */
.form-control:focus {
    background-color: #fff;
}

/* Row dépubliée / désactivée : texte barré et grisé pour signaler l'état.
   Le strikethrough s'applique à TOUTES les cellules visibles sauf celle
   des actions (`.text-end`) — sinon le line-through traverse les
   whitespaces entre les boutons d'action et crée un trait disgracieux.
   La pill INAMI (mono) hérite bien du barré pour la cohérence. */
.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr.miniapp-row-inactive > td:not(.text-end) {
    text-decoration: line-through;
    color: var(--clr-text-3);
}

.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr.miniapp-row-inactive > td .btn-link {
    text-decoration: none;
}

/* Les pills (display: inline-block) créent un nouveau formatting context :
   le `text-decoration: line-through` du parent <td> ne se propage pas.
   On le pose explicitement pour barrer aussi le tag INAMI mono et les
   pills cliniques. */
.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr.miniapp-row-inactive > td .miniapp-pill {
    text-decoration: line-through;
}

/* #59 : extension aux sub_listings (DOM légèrement différent — pas de
   `.card-body` intermédiaire). Mêmes règles que la liste principale pour
   les rows archived/inactive. */
.miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr.miniapp-row-inactive > td:not(.text-end) {
    text-decoration: line-through;
    color: var(--clr-text-3);
}

.miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr.miniapp-row-inactive > td .btn-link {
    text-decoration: none;
}

.miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr.miniapp-row-inactive > td .miniapp-pill {
    text-decoration: line-through;
}

/* #61 : rows cliquables → ouvrent l'élément en mode view. Le JS
   `row-clickable.js` gère la délégation et préserve les actions internes.
   Hover discret + cursor pour signaler l'interactivité. Le focus ring
   reste visible pour l'accessibilité clavier (Enter ouvre aussi). */
.miniapp-row-clickable {
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.miniapp-row-clickable:hover {
    background-color: var(--clr-blue-pale, #eef3fb);
}

.miniapp-row-clickable:focus {
    outline: 2px solid var(--clr-navy);
    outline-offset: -2px;
}

/* ════════ État inactif sur les pages view/edit ════════ */

/* Le titre h1 reçoit un petit badge texte « INACTIF » à droite. */
.miniapp-entity-status {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    background: rgba(212, 64, 64, .12);
    color: var(--clr-danger);
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 600;
    margin-left: 8px;
    vertical-align: middle;
}

/* Bandeau prominent affiché au-dessus du form/view pour rendre l'état
   inactif impossible à manquer. Plus visible qu'un simple badge dans le titre. */
.miniapp-inactive-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    background: rgba(212, 64, 64, .08);
    border: 1px solid rgba(212, 64, 64, .25);
    border-left: 4px solid var(--clr-danger);
    border-radius: 6px;
    color: var(--clr-text);
    margin-bottom: 24px;
}

.miniapp-inactive-banner__icon {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--clr-danger);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
}

.miniapp-inactive-banner__title {
    font-weight: 600;
    color: var(--clr-danger);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: .8rem;
}

.miniapp-inactive-banner__text {
    font-size: .9rem;
    color: var(--clr-text-2);
    margin-top: 2px;
}

/* ════════ Actions row (icônes cerclées colorées) ════════ */

.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr > td .btn-link {
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--clr-teal-pale);
    color: var(--clr-teal);
    margin-left: 4px;
    transition: filter var(--transition, .15s);
}

.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr > td .btn-link:hover {
    filter: brightness(.92);
    text-decoration: none;
}

.miniapp-content .card > .card-body > .table-responsive > .table > tbody > tr > td .btn-link.text-danger {
    background: var(--clr-pink-pale);
    color: var(--clr-pink) !important;
}

/* ════════ Responsive ════════ */
@media (max-width: 900px) {
    .miniapp-footer__inner {
        grid-template-columns: 1fr 1fr;
        gap: 24px;
    }
}

/* Bandeau supérieur du drawer mobile (`__topbar`) — réserve l'espace pour le
   bouton de fermeture, séparé du brand block pour ne pas amputer le texte
   « OD Connect ». Pattern Bootstrap offcanvas-header. */
.miniapp-sidebar__topbar {
    display: none;
}

.miniapp-sidebar__close {
    width: 36px;
    height: 36px;
    border: none;
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
    border-radius: 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.1rem;
    transition: background var(--transition);
}

.miniapp-sidebar__close:hover {
    background: rgba(255, 255, 255, 0.2);
}

@media (max-width: 768px) {
    .miniapp-sidebar {
        transform: translateX(-100%);
        transition: transform var(--transition);
    }

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

    /* Le bandeau de fermeture apparaît AU-DESSUS du brand block en mode
       drawer ouvert. Justify-end pour pousser le X à droite. Padding aligné
       sur le brand block pour cohérence visuelle. */
    .miniapp-sidebar--open .miniapp-sidebar__topbar {
        display: flex;
        justify-content: flex-end;
        padding: 12px 14px 0;
    }

    .miniapp-layout__main {
        margin-left: 0;
    }

    .miniapp-topbar {
        padding: 0 16px;
    }

    .miniapp-topbar__username {
        display: none;
    }

    .miniapp-content {
        padding: 24px 18px;
    }
}

/* ════════ Mini-app _fields — cards de classes Pimcore ════════ */
.miniapp-fields-card {
    transition: all var(--transition);
    color: var(--clr-text);
}

.miniapp-fields-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    color: var(--clr-text);
}

.miniapp-fields-card__icon {
    width: 40px;
    height: 40px;
    border-radius: var(--radius);
    background: var(--clr-blue-pale);
    color: var(--clr-blue-mid);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
    flex-shrink: 0;
}

/* ════════ Sidebar collapsed (desktop icons-only) ════════ */
/* La sidebar passe à 64px : icônes seules, labels masqués, tooltips natifs
   via l'attribut `title=`. Le main content compense margin-left. Transitions
   smooth pour ne pas surprendre l'utilisateur. */
.miniapp-sidebar,
.miniapp-layout__main {
    transition: width var(--transition), margin-left var(--transition);
}

@media (min-width: 769px) {
    .miniapp-layout--sidebar-collapsed .miniapp-sidebar {
        width: 64px;
    }

    .miniapp-layout--sidebar-collapsed .miniapp-layout__main {
        margin-left: 64px;
    }

    .miniapp-layout--sidebar-collapsed .miniapp-sidebar__brand-text,
    .miniapp-layout--sidebar-collapsed .miniapp-sidebar__section-title,
    .miniapp-layout--sidebar-collapsed .miniapp-sidebar__link-label {
        display: none;
    }

    .miniapp-layout--sidebar-collapsed .miniapp-sidebar__brand {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    .miniapp-layout--sidebar-collapsed .miniapp-sidebar__link {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    .miniapp-layout--sidebar-collapsed .miniapp-sidebar__link i {
        margin: 0;
    }
}

@media (max-width: 600px) {
    .miniapp-footer__inner {
        grid-template-columns: 1fr;
        gap: 20px;
        padding: 28px 20px 24px;
    }

    .miniapp-footer__col--social {
        flex-direction: row;
    }
}

/* ----------------------------------------------------------------------------
   Audit diff table (_audit_logs/<id>/view).
   3 statuts visuels par-clé : changed (jaune), added (vert), removed (rouge),
   unchanged (gris pâle, peu intrusif).
   ---------------------------------------------------------------------------- */
.audit-diff__row--changed {
    background-color: #fff3cd; /* Bootstrap warning bg-subtle */
}
.audit-diff__row--added {
    background-color: #d1e7dd; /* Bootstrap success bg-subtle */
}
.audit-diff__row--removed {
    background-color: #f8d7da; /* Bootstrap danger bg-subtle */
}
.audit-diff__row--unchanged {
    color: #6c757d; /* text-muted */
}
.audit-diff__row--unchanged .audit-diff__value {
    opacity: 0.75;
}
.audit-diff__key {
    vertical-align: middle;
    white-space: nowrap;
}
.audit-diff__value {
    vertical-align: top;
    /* `overflow-wrap: anywhere` casse seulement quand un mot dépasse la cellule
       (pas de wrap char-par-char en utilisation normale). Combiné avec
       `table-layout: fixed` + largeurs explicites côté template, on garantit
       que la table tient dans son container sans débordement horizontal. */
    overflow-wrap: anywhere;
    word-break: normal;
}

/* ----------------------------------------------------------------------------
   Barre supérieure sur téléphone — correctif du 2026-09-08.

   Signalé par l'utilisateur : une barre de défilement HORIZONTALE sur la liste
   des dentistes et celle des cliniques. ⚠️ Le débordement ne venait PAS des
   cartes annuaire (mesuré : zéro élément de carte hors cadre) mais du SHELL,
   et il est ANTÉRIEUR à leur livraison — les listes étaient simplement trop
   illisibles auparavant pour qu'on le remarque.

   Arithmétique mesurée à 390 px de viewport, `__username` déjà masqué :

     __left (menu + logo)      124 px
     sélecteur de langue        78 px
     pastille utilisateur       53 px
     lien « Déconnexion »      130 px   ← le plus gros poste
     padding (2 × 16)           32 px
     ------------------------------------
     total                     417 px   pour 390 disponibles

   Le libellé du lien suffit à lui seul à faire déborder. On le masque sous
   480 px : l'icône reste, et l'intitulé reste porté par l'attribut `title` du
   lien — l'information n'est pas perdue pour les technologies d'assistance.
   Nouveau total : 317 px, soit 73 px de marge.

   ⚠️ Seuil à 480 px et non 768 px : une tablette a la place, et masquer le
   libellé là où il tient dégraderait l'écran sans raison.
   ---------------------------------------------------------------------------- */
@media (max-width: 480px) {
    .miniapp-topbar__logout span {
        display: none;
    }
}

/* Cartes annuaire : masquées par défaut, révélées par la media query ci-dessous.
   ⚠️ Cette déclaration doit rester AVANT la media query — même spécificité
   (0,1,0), c'est l'ORDRE SOURCE qui départage.

   ⚠️ Le nom `miniapp-entry` n'est pas cosmétique : `.miniapp-card` est DÉJÀ pris
   par les cartes du tableau de bord (§ « Dashboard cards », plus haut dans ce
   fichier), qui posent `flex-direction: column`, `height: 100%` et
   `overflow: hidden`. La collision jouait dans les DEUX sens — nos cartes
   s'empilaient verticalement, et le tableau de bord héritait de notre padding,
   de notre bordure et de notre `align-items`. Ne pas revenir à `card`. */
.miniapp-entries {
    display: none;
}

/* ----------------------------------------------------------------------------
   Liste CRUD responsive : la table cède la place aux CARTES ANNUAIRE sous 992 px
   (spec 2026-09-08). Le gabarit rend LES DEUX structures — `<table>` et
   `<ul class="miniapp-entries">` — depuis les mêmes données, et le CSS en masque
   une : le serveur ne connaît pas la largeur du viewport.

   ⚠️ Le masquage se fait par `display: none`, JAMAIS par `visibility` ni
   `opacity`. La structure masquée garderait sinon son ordre de tabulation
   complet ET ses formulaires POST delete/restore en double — deux boutons de
   suppression pour un enregistrement, dont un invisible.

   ⚠️ Le pliage libellé/valeur (`::before { content: attr(data-label) }`) est
   RETIRÉ pour les listes — devenu sans objet — et CONSERVÉ pour les
   `sub_listings` juste en dessous, qui restent hors du périmètre de ce chantier.
   Le breakpoint reste 992 px : la sidebar de 260 px est visible jusqu'à 768 px,
   donc à 800 px de viewport le contenu n'a que ~540 px — une carte y est
   confortable, une table de huit colonnes non.
   ---------------------------------------------------------------------------- */
@media (max-width: 991.98px) {
    .miniapp-content .card > .card-body > .table-responsive {
        display: none;
    }

    .miniapp-entries {
        display: flex;
    }

    /* Pagination : pas de wrap horizontal forcé sur mobile. */
    .miniapp-content .pagination {
        flex-wrap: wrap;
        justify-content: center;
    }

    /* #60 : même transformation table → cards pour les sub_listings.
       Le DOM diffère légèrement (pas de `.card-body` intermédiaire dans
       .miniapp-sub-listing), donc on duplique les règles avec le bon
       sélecteur racine. `data-label` est posé sur les `<td>` du template
       `_sub_listing.html.twig`. */
    .miniapp-content .miniapp-sub-listing > .table-responsive {
        overflow: visible;
        border: 0;
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table {
        background: transparent;
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table > thead {
        display: none;
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr {
        display: block;
        margin: 0 0 12px;
        padding: 12px;
        background: #fff;
        border: 1px solid var(--clr-border, #dee2e6);
        border-radius: 6px;
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr > td {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 12px;
        padding: 4px 0;
        border: 0;
        text-align: left !important;
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr > td::before {
        content: attr(data-label);
        flex: 0 0 35%;
        font-size: .72rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: .04em;
        color: var(--clr-text-3, #6c757d);
        text-align: left;
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr > td.text-end {
        justify-content: flex-end;
        padding-top: 8px;
        border-top: 1px solid var(--clr-border-light, #eef2f6);
        margin-top: 8px;
    }
    .miniapp-content .miniapp-sub-listing > .table-responsive > .table > tbody > tr > td.text-end::before {
        display: none;
    }
}

/* ----------------------------------------------------------------------------
   Cartes annuaire (spec 2026-09-08). Masquées par défaut, révélées sous 992 px
   par le bloc @media ci-dessus.

   ⚠️ La vignette à initiales est le rendu NOMINAL, pas un placeholder d'attente :
   2 contacts sur 655 portent une photo (mesuré le 2026-09-08). 494 vignettes
   grises identiques seraient pires que la table qu'on remplace, d'où quatre
   teintes déterministes assignées par identifiant Pimcore.
   ---------------------------------------------------------------------------- */
.miniapp-entries {
    /* ⚠️ `display` est déclaré PLUS HAUT, juste avant la media query — pas ici.
       Le déclarer dans ce bloc le placerait APRÈS la règle qui le révèle : à
       spécificité égale, la dernière gagne, et les cartes restaient invisibles
       à TOUTE largeur. Vécu le 2026-09-08 : markup correct, CSS valide, 1074
       tests verts, écran vide. */
    flex-direction: column;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 10px;
}

.miniapp-entry {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    background: var(--clr-surface);
    border: 1px solid var(--clr-border);
    border-radius: var(--radius-lg);
    padding: 11px 10px 11px 11px;
    position: relative;
}

.miniapp-entry.miniapp-row-clickable {
    cursor: pointer;
}

.miniapp-entry.miniapp-row-clickable:hover {
    border-color: var(--clr-blue-light);
    box-shadow: var(--shadow-sm);
}

.miniapp-entry:focus-visible {
    outline: 2px solid var(--clr-blue-mid);
    outline-offset: 2px;
}

/* Inactif : même convention que `.miniapp-row-inactive` sur les lignes de table. */
.miniapp-entry--muted .miniapp-entry__title,
.miniapp-entry--muted .miniapp-entry__avatar {
    opacity: .55;
}

.miniapp-entry__avatar {
    flex: none;
    width: 46px;
    height: 46px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-family: var(--ff-display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: .03em;
    overflow: hidden;
    background: var(--clr-blue-pale);
    color: var(--clr-navy);
}

.miniapp-entry__avatar--a { background: var(--clr-blue-pale);   color: var(--clr-navy); }
.miniapp-entry__avatar--b { background: var(--clr-teal-pale);   color: var(--clr-teal); }
.miniapp-entry__avatar--c { background: var(--clr-pink-pale);   color: var(--clr-pink); }
.miniapp-entry__avatar--d { background: var(--clr-orange-pale); color: var(--clr-orange); }

.miniapp-entry__avatar--photo {
    background: var(--clr-surface-alt);
}

.miniapp-entry__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.miniapp-entry__main {
    flex: 1;
    min-width: 0;
}

.miniapp-entry__title {
    display: block;
    font-weight: 800;
    font-size: .98rem;
    line-height: 1.25;
    color: var(--clr-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.miniapp-entry__meta {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 4px;
    font-size: .8rem;
    color: var(--clr-text-3);
    min-width: 0;
}

.miniapp-entry__meta-item {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.miniapp-entry__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 6px;
}

/* Les pills viennent de `formatListRow` en HTML déjà composé : on ne les
   tronque pas côté serveur (ce serait le réinterpréter). L'écrêtage est ici,
   et `card-pills.js` ajoute le « +N ». Sans JS, tout s'affiche en passant à la
   ligne — dégradation acceptable. */
.miniapp-entry__pills[data-pills-max="1"] > .miniapp-pill:nth-of-type(n+2),
.miniapp-entry__pills[data-pills-max="2"] > .miniapp-pill:nth-of-type(n+3),
.miniapp-entry__pills[data-pills-max="3"] > .miniapp-pill:nth-of-type(n+4) {
    display: none;
}

.miniapp-entry__pills .miniapp-pill + .miniapp-pill {
    margin-left: 0; /* le `gap` du flex remplace la marge de `.miniapp-pill + .miniapp-pill` */
}

.miniapp-entry__pills-more {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px dashed var(--clr-border);
    color: var(--clr-text-3);
    font-size: .78rem;
    font-weight: 600;
    line-height: 1.4;
}

.miniapp-entry__tail {
    flex: none;
    display: flex;
    align-items: center;
    align-self: center;
    gap: 2px;
}

.miniapp-entry__call,
.miniapp-entry__kebab {
    border: 0;
    background: none;
    padding: 6px 4px;
    color: var(--clr-text-3);
    cursor: pointer;
    border-radius: 6px;
    display: grid;
    place-items: center;
    font-size: 1.05rem;
    text-decoration: none;
}

.miniapp-entry__call {
    color: var(--clr-blue-mid);
}

.miniapp-entry__call:hover,
.miniapp-entry__kebab:hover {
    background: var(--clr-surface-alt);
    color: var(--clr-navy);
}

.miniapp-entry__call:focus-visible,
.miniapp-entry__kebab:focus-visible {
    outline: 2px solid var(--clr-blue-mid);
    outline-offset: 1px;
}

/* ----------------------------------------------------------------------------
   Feuille d'actions des cartes annuaire. Ancrée en bas, une seule par document.
   ---------------------------------------------------------------------------- */
.miniapp-sheet-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(11, 18, 32, .55);
    opacity: 0;
    transition: opacity .2s ease;
    z-index: 1090;
}

.miniapp-sheet-backdrop.open {
    opacity: 1;
}

.miniapp-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1091;
    max-width: 520px;
    margin: 0 auto;
    max-height: 82vh;
    overflow-y: auto;
    background: var(--clr-surface);
    border-top-left-radius: 18px;
    border-top-right-radius: 18px;
    box-shadow: var(--shadow-md);
    padding: 8px 0 max(14px, env(safe-area-inset-bottom));
    transform: translateY(102%);
    transition: transform .26s cubic-bezier(.4, 0, .2, 1);
}

.miniapp-sheet.open {
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .miniapp-sheet,
    .miniapp-sheet-backdrop {
        transition: none;
    }
}

.miniapp-sheet__grip {
    display: block;
    width: 38px;
    height: 4px;
    border-radius: 999px;
    background: var(--clr-border);
    margin: 6px auto 10px;
}

.miniapp-sheet__head {
    display: flex;
    gap: 11px;
    align-items: center;
    padding: 0 18px 12px;
    border-bottom: 1px solid var(--clr-border-light);
}

.miniapp-sheet__name {
    font-weight: 800;
    font-size: 1rem;
    color: var(--clr-text);
}

.miniapp-sheet__group {
    padding: 8px 0;
}

.miniapp-sheet__group + .miniapp-sheet__group {
    border-top: 1px solid var(--clr-border-light);
}

.miniapp-sheet__label {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--clr-text-3);
    padding: 4px 18px 6px;
}

.miniapp-sheet__item {
    display: flex;
    align-items: center;
    gap: 13px;
    width: 100%;
    background: none;
    border: 0;
    padding: 11px 18px;
    text-align: left;
    font-family: var(--ff-body);
    font-size: .95rem;
    color: var(--clr-text);
    cursor: pointer;
    text-decoration: none;
}

.miniapp-sheet__item > i {
    color: var(--clr-blue-mid);
    font-size: 1.05rem;
}

.miniapp-sheet__item:hover,
.miniapp-sheet__item:focus-visible {
    background: var(--clr-surface-alt);
    color: var(--clr-text);
    outline: none;
}

.miniapp-sheet__item--danger,
.miniapp-sheet__item--danger > i {
    color: var(--clr-danger);
}

.miniapp-sheet__chev {
    margin-left: auto;
    color: var(--clr-text-3);
    font-size: .85rem;
}

/* ----------------------------------------------------------------------------
   Pagination — couleurs du thème (Bootstrap 5 expose des variables dédiées
   `--bs-pagination-*` qui n'héritent pas auto de `--bs-primary`, d'où ces
   overrides explicites pour aligner la page active sur le navy Odontolia).
   ---------------------------------------------------------------------------- */
.miniapp-content .pagination {
    --bs-pagination-color:               var(--clr-navy);
    --bs-pagination-hover-color:         var(--clr-navy-deep);
    --bs-pagination-hover-bg:            var(--clr-blue-pale);
    --bs-pagination-hover-border-color:  var(--clr-border);
    --bs-pagination-focus-color:         var(--clr-navy-deep);
    --bs-pagination-focus-bg:            var(--clr-blue-pale);
    --bs-pagination-focus-box-shadow:    0 0 0 .2rem rgba(27, 42, 74, .25);
    --bs-pagination-active-color:        #fff;
    --bs-pagination-active-bg:           var(--clr-navy);
    --bs-pagination-active-border-color: var(--clr-navy);
}

/* ----------------------------------------------------------------------------
   Grille filtres : auto-fit + minmax = chaque filtre prend au moins 200px et
   s'étire pour combler l'espace disponible. Pas de calcul JS, pas de breakpoint
   à maintenir — le navigateur ajuste le nombre de colonnes selon la largeur.
   Le `date_range` (qui contient 2 inputs) demande plus d'espace : on lui
   double sa largeur via `span 2` (au pire 2 colonnes), ou via min-width custom.
   ---------------------------------------------------------------------------- */
/* Barre unique : la grille des filtres dimensionnés + le groupe de toggles
   restent à gauche, les actions (export/reset) sont poussées à droite. Wrap
   propre sur écran étroit. */
.miniapp-filters__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 8px 12px;
}
.miniapp-filters__bar > .miniapp-filters__grid {
    /* `display: contents` : la grille s'efface, ses filtres deviennent des
       items flex directs de la barre → chacun se dimensionne à son contenu
       (min 200px) et se place à côté des toggles, au lieu d'être étiré sur
       toute la largeur par le `1fr` de la grille auto-fit. */
    display: contents;
}
.miniapp-filters__bar > .miniapp-filters__grid > * {
    /* Largeur cible bornée (le select n'a pas de largeur intrinsèque → sans
       borne il s'étire sur toute la ligne et rejette les toggles au wrap). */
    flex: 0 1 240px;
    min-width: 200px;
}
/* Toggles binaires groupés, compacts (taille du contenu, pas de cellule ≥200px). */
.miniapp-filters__toggles {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 8px;
}
/* Avertissement d'auto-soumission : discret mais LISIBLE — 6,93:1 mesuré sur
   `--clr-text-2`. Le masquer visuellement le retirerait aux lecteurs voyants,
   qui subissent le même changement de contexte inattendu. */
.miniapp-filters__hint {
    flex: 1 1 100%;
    margin: 0 0 6px;
    font-size: .74rem;
    color: var(--clr-text-2);
}

/* Rangée « bascules + actions ». `--break` la pousse sur sa propre ligne et
   sépare les deux groupes ; sans lui elle reste un item flex ordinaire, poussé
   à droite — le rendu d'avant pour les mini-apps sans bascule. */
.miniapp-filters__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    margin-left: auto;
}
.miniapp-filters__row--break {
    flex: 1 1 100%;
    margin-left: 0;
    justify-content: space-between;
}

/* ─── Ligne d'état : compte de résultats + jetons de critères retirables ─── */
.miniapp-filters__state {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 8px;
    padding-top: 10px;
    margin-top: 10px;
    border-top: 1px solid var(--clr-border-light);
}
.miniapp-filters__state-count {
    font-size: .78rem;
    font-weight: 600;
    color: var(--clr-text-2);
    margin-right: 4px;
}
/* Le jeton reprend le vocabulaire du multi-select actif — teal sur teal pâle —
   parce que c'est le SEUL contrôle de la barre qui savait déjà dire « je suis
   appliqué ». On étend sa langue au lieu d'en inventer une cinquième.
   ⚠️ Texte navy et non teal : le teal sur teal pâle vaut 2,26:1, très sous le
   seuil AA. Le signal porte le fond, la lisibilité porte le texte. */
.miniapp-filters__token {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border: 1px solid var(--clr-teal);
    border-radius: 999px;
    background: var(--clr-teal-pale);
    color: var(--clr-navy);
    font-size: .78rem;
    text-decoration: none;
    transition: background-color .12s ease, border-color .12s ease;
}
.miniapp-filters__token:hover,
.miniapp-filters__token:focus-visible {
    background: var(--clr-teal);
    color: #fff;
}
.miniapp-filters__token-label {
    font-weight: 600;
    opacity: .75;
}
.miniapp-filters__token-label::after {
    content: ' :';
}
.miniapp-filters__token .bi-x {
    font-size: 1rem;
    line-height: 1;
    opacity: .6;
}
.miniapp-filters__token:hover .bi-x {
    opacity: 1;
}

/* Actions (export/reset) alignées à droite de la barre. */
.miniapp-filters__actions {
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.miniapp-filters__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 8px;
    align-items: end;
}
/* Le date_range a 3 enfants (label + 2 dates) — il a besoin de ~2× la largeur
   d'un filtre simple pour rester confortable. On le force à occuper au minimum
   deux unités de la grille tant qu'il y a la place (sinon il se contente
   d'une cellule comme les autres). */
.miniapp-filters__grid > .input-group:has(input[type="date"] ~ input[type="date"]) {
    grid-column: span 2;
    min-width: 320px;
}

/* ----------------------------------------------------------------------------
   Multi-select dropdown — `<details>` natif HTML5, zero JS pour le toggle.
   Le `<summary>` agit comme bouton, le panneau d'options se révèle au click.
   ---------------------------------------------------------------------------- */
.miniapp-filters__multi {
    position: relative;
    display: flex;          /* permet au summary de prendre toute la largeur de la cellule grid */
    flex-direction: column;
}
.miniapp-filters__multi > summary {
    list-style: none;
    cursor: pointer;
    padding: 0.25rem 0.5rem;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.5rem center;
    background-size: 16px 12px;
    padding-right: 2rem;
}
.miniapp-filters__multi > summary::-webkit-details-marker {
    display: none;  /* Safari : retire la flèche native pour rester cohérent */
}
.miniapp-filters__multi[open] > summary {
    border-color: var(--clr-blue-mid);
    box-shadow: 0 0 0 0.25rem rgba(46, 109, 170, 0.15);
}
.miniapp-filters__multi-label {
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
    color: var(--clr-text-2);
    margin-right: 0.5rem;
}
.miniapp-filters__multi-panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 10;
    background: #fff;
    border: 1px solid var(--clr-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    padding: 0.5rem 0;
    /* ⚠️ Plafond relevé le 2026-09-09, après mesure : à 280px le panneau des
       8 spécialités faisait 294px de contenu pour 278px de hauteur utile —
       une barre de défilement entière pour SEIZE pixels, soit 5 % du contenu.
       Le plafond mordait pile à 8 options.
       `min(60vh, 420px)` laisse passer une douzaine d'options sans barre tout
       en restant borné sur un écran court. Le plafond reste NÉCESSAIRE : les
       catalogues sont des listes gérées que le client peut allonger. */
    max-height: min(60vh, 420px);
    overflow-y: auto;
}
.miniapp-filters__multi[data-active="1"] > summary {
    border-color: var(--clr-teal);
    background-color: var(--clr-teal-pale);
}

/* ----------------------------------------------------------------------------
   Pages d'authentification (login, reset password, register).
   Carte centrée, sans sidebar. Utilisée via :
     {% extends '@WfMiniapp/base.html.twig' %}
     {% block sidebar %}{% endblock %}  ← pas de chrome appli pour les pré-auth
   ---------------------------------------------------------------------------- */
.auth-page {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    background: var(--clr-bg);
}
.auth-card {
    width: 100%;
    max-width: 460px;
    background: var(--clr-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    padding: 36px 32px;
    border-top: 3px solid;
    border-image: linear-gradient(90deg, var(--clr-teal), var(--clr-pink), var(--clr-orange)) 1;
}
.auth-card__title {
    font-family: var(--ff-display);
    font-size: 1.4rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--clr-navy);
    text-align: center;
    margin-bottom: 6px;
}
.auth-card__subtitle {
    font-size: .88rem;
    color: var(--clr-text-2);
    text-align: center;
    margin-bottom: 24px;
}
.auth-card__divider {
    height: 1px;
    background: var(--clr-border-light);
    margin: 18px 0 22px;
}
.auth-form__group { margin-bottom: 14px; }
.auth-form__label {
    display: block;
    font-size: .78rem;
    font-weight: 700;
    color: var(--clr-text-2);
    text-transform: uppercase;
    letter-spacing: .06em;
    margin-bottom: 6px;
}
.auth-form__input {
    width: 100%;
    padding: 10px 14px;
    border: 1px solid var(--clr-border);
    border-radius: var(--radius);
    font-family: var(--ff-body);
    font-size: .92rem;
    color: var(--clr-text);
    background: var(--clr-surface);
    transition: border-color var(--transition), box-shadow var(--transition);
}
.auth-form__input:focus {
    outline: none;
    border-color: var(--clr-blue-mid);
    box-shadow: 0 0 0 3px rgba(46,109,170,.12);
}
.auth-form__input-wrap { position: relative; }
.auth-form__toggle {
    position: absolute;
    top: 50%; right: 10px;
    transform: translateY(-50%);
    cursor: pointer;
    color: var(--clr-text-3);
    background: none; border: none; padding: 4px;
    display: flex; align-items: center;
}
.auth-form__toggle:hover { color: var(--clr-blue-mid); }
.auth-form__forgot {
    display: inline-block;
    margin-top: 4px;
    font-size: .78rem;
    color: var(--clr-blue-mid);
    font-weight: 600;
    text-decoration: none;
}
.auth-form__forgot:hover { text-decoration: underline; }
.auth-form__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 22px;
    background: linear-gradient(135deg, var(--clr-navy), var(--clr-blue-mid));
    color: #fff;
    border: none;
    border-radius: var(--radius);
    font-family: var(--ff-display);
    font-size: .9rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    cursor: pointer;
    transition: filter var(--transition), transform var(--transition);
    margin-top: 8px;
}
.auth-form__btn:hover { filter: brightness(1.08); transform: translateY(-1px); color: #fff; }
.auth-alert {
    padding: 10px 14px;
    border-radius: var(--radius);
    background: var(--clr-pink-pale);
    color: var(--clr-pink);
    border-left: 3px solid var(--clr-pink);
    font-size: .85rem;
    margin-bottom: 18px;
}

/* ----------------------------------------------------------------------------
   Page « Mon compte » (`/{_locale}/account`). Grid 2 colonnes (profil à
   gauche, infos à droite), responsive en colonne unique < 800px. Le
   topbar/sidebar/footer sont fournis par le shell mini-app v2.
   ---------------------------------------------------------------------------- */
.account-grid {
    display: grid;
    grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
    gap: 24px;
}
@media (max-width: 800px) { .account-grid { grid-template-columns: 1fr; } }

.account-card {
    background: var(--clr-surface);
    border-radius: var(--radius-lg);
    padding: 24px 26px;
    box-shadow: var(--shadow-sm);
    border-top: 3px solid;
    border-image: linear-gradient(90deg, var(--clr-teal), var(--clr-pink)) 1;
}
.account-card__title {
    font-family: var(--ff-display);
    font-size: 1.1rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--clr-navy);
    margin-bottom: 16px;
}
.account-info { display: grid; gap: 10px; }
.account-info__row {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--clr-border-light);
    font-size: .88rem;
}
.account-info__row:last-child { border-bottom: none; }
.account-info__label { color: var(--clr-text-3); font-weight: 600; }
.account-info__value { color: var(--clr-text); font-weight: 500; word-break: break-word; }

/* Avatar circulaire utilisé sur la carte profil (déclinable en grand format
   via inline style `width/height/font-size`). Même rendu que celui du
   `_topbar.html.twig` (gradient navy diagonal). */
.account-avatar {
    width: 34px; height: 34px; border-radius: 50%;
    background: linear-gradient(135deg, var(--clr-navy), var(--clr-blue-mid));
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: .75rem; font-weight: 800; flex-shrink: 0;
}

/* Searchable-select (Tom Select) : largeur fixe du contrôle pour qu'il ne
   change pas de largeur entre la valeur courante (ex. « 01_LIGNY ») et le
   placeholder « Rechercher une clinique… » affiché à l'ouverture. Ciblé sur
   le wrapper généré par NOTRE composant uniquement (frère adjacent du <select
   data-searchable-select> masqué). */
/* ⚠️ Dans un `input-group`, Tom Select fournit DÉJÀ son intégration Bootstrap
   (`.input-group > .ts-wrapper { flex-grow:1; width:1% }`, hauteur `-sm`,
   rayons de bordure sur nth-child(2)/last-child). Notre largeur fixe de 18rem
   ci-dessous — écrite pour le sélecteur de clinique du planning, qui vit HORS
   input-group — l'écrasait par spécificité (0,2,2 contre 0,1,1). Comme
   `.input-group` est en `flex-wrap: wrap`, le wrapper passait sous son libellé :
   62 px au lieu de 31, et le libellé « CLINIQUE » se retrouvait AU-DESSUS de son
   champ alors que ses quatre voisins ont le leur en ligne.
   On ne se bat pas contre Tom Select : on cesse de le contredire.
   ⚠️ Le `min-width: 0` n'est pas décoratif — sans lui l'item flex refuse de
   descendre sous sa largeur min-content et le retour à la ligne revient sur un
   nom de clinique long. */
.input-group > select[data-searchable-select] + .ts-wrapper {
    width: 1%;
    flex: 1 1 auto;
    min-width: 0;
}

select[data-searchable-select] + .ts-wrapper {
    width: 18rem;
    max-width: 100%;
}
