/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE LAYOUT — Drill-down navigation UX
   Components render these classes only when IMobileLayoutService.IsMobile == true.
   Desktop never sees this markup (no CSS-only hiding).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Mobile Page Header (back button + title) ────────────────────────── */
.mobile-page-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--linkooc-border-color, #dee2e6);
    position: sticky;
    top: 0;
    background: var(--linkooc-bg, #fff);
    z-index: 10;
    min-height: 48px;
    flex-shrink: 0;
}

.mobile-back-btn {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    min-width: 44px;
    height: 44px;
    padding: 0 0.5rem 0 0.25rem;
    border: none;
    background: transparent;
    border-radius: 8px;
    font-size: 1.25rem;
    color: var(--linkooc-text, #212529);
    -webkit-tap-highlight-color: transparent;
    cursor: pointer;
    flex-shrink: 0;
    max-width: 50%;
}

.mobile-back-btn:active {
    background: var(--linkooc-surface-hover, #f5f5f5);
}

.mobile-back-label {
    font-size: 0.875rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mobile-page-title {
    font-size: 1.0625rem;
    font-weight: 600;
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
    color: var(--linkooc-text, #212529);
}

.mobile-count-badge {
    font-size: 0.8125rem;
    color: var(--linkooc-text-muted, #6d6d6d);
    flex-shrink: 0;
}

/* ── Mobile Full-Screen Panels ───────────────────────────────────────── */
.linkooc-mobile-list,
.linkooc-mobile-detail,
.menu-editor-mobile-tree,
.menu-editor-mobile-detail {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    width: 100%;
    overflow: hidden;
}

.linkooc-mobile-list .linkooc-list-container,
.linkooc-mobile-detail,
.menu-editor-mobile-tree,
.menu-editor-mobile-detail {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* ── Touch-Friendly List Items ───────────────────────────────────────── */
.linkooc-mobile-list .linkooc-list-item {
    min-height: 52px;
    padding: 0.75rem 1rem;
}

/* ── Mobile Tabs: horizontal scroll ──────────────────────────────────── */
@media (max-width: 768px) {
    /* The tab bar is the scroller — never the body. Its native scrollbar is
       hidden on purpose, so the only thing left to say "there is more to the
       right" is the scroll shadow below (plan 393). */
    .linkooc-tabs-container,
    .linkooc-tabs-container:hover,
    .linkooc-tabs-container:focus-within,
    /* Plan 420: the item-detail rail (ItemDetail.razor's ul.nav.nav-tabs) joins
       the SAME rule rather than getting a second recipe. It already scrolled —
       what it lacked was any sign that it does. Its cover colour differs, so
       that one value is a custom property (--lk-tab-scroll-cover) overridden
       just below; every other declaration is shared verbatim. */
    .linkooc-detail-container>.nav-tabs,
    .linkooc-detail-container>.nav-tabs:hover,
    .linkooc-detail-container>.nav-tabs:focus-within,
    /* Plan 459: the establishment sheet's rail (EstablishmentEdit.razor's
       ul.nav.nav-tabs, a DIRECT child of .linkooc-page-container) joins the same
       rule — route (b) of the plan. Route (a), wrapping it in
       .linkooc-detail-container, was rejected: that class carries a whole
       layout contract elsewhere in this file (flex:1, min-height:0,
       overflow:visible under .linkooc-mobile-detail) and adding a box between
       the header and the rail changes the page's flex column. Adding a
       selector changes nothing but the rail.
       The `>` matters: the sub-rails of the « Compte client » / « Compte
       facturation » tabs are nested deeper inside the form, already fit on one
       line, and must not be touched. */
    .linkooc-page-container>.nav-tabs,
    .linkooc-page-container>.nav-tabs:hover,
    .linkooc-page-container>.nav-tabs:focus-within {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        /* :hover/:focus-within are listed above and !important is required:
           EstablishmentDetailPage's inline <style> reveals a thin scrollbar on
           hover — a desktop affordance. It has no media query, and a tap on a
           phone latches :focus-within with nothing to clear it, so that
           scrollbar would appear on first touch and stay. Being a global
           sheet, mobile.css also loads BEFORE those inline blocks. */
        scrollbar-width: none !important;
        /* Scroll shadows, pure CSS (Roman Komarov's technique):
           layers 1-2 are opaque "covers" painted in the bar's own background
           colour and attached to the CONTENT (local), so they slide away with
           it; layers 3-4 are the shadows, attached to the ELEMENT (scroll), so
           they stay pinned at the edges. A cover sits on top of its shadow when
           that side has nothing more to scroll — the shadow only shows where
           content actually continues off-screen. No JS, no scroll listener.
           The cover colour MUST match the bar's OWN background, otherwise the
           two 32px covers read as tinted bands. --linkooc-surface is that
           colour for .linkooc-tabs-container (opaque in both themes); the
           item-detail rail sits on --linkooc-bg instead, which is why the
           colour is a variable and not a literal. */
        --lk-tab-scroll-shadow: rgba(0, 0, 0, 0.22);
        --lk-tab-scroll-cover: var(--linkooc-surface, #FEFEFE);
        background-image:
            linear-gradient(to right, var(--lk-tab-scroll-cover) 65%, transparent),
            linear-gradient(to left, var(--lk-tab-scroll-cover) 65%, transparent),
            linear-gradient(to right, var(--lk-tab-scroll-shadow), transparent),
            linear-gradient(to left, var(--lk-tab-scroll-shadow), transparent) !important;
        background-position: 0 0, 100% 0, 0 0, 100% 0 !important;
        background-repeat: no-repeat !important;
        background-size: 32px 100%, 32px 100%, 20px 100%, 20px 100% !important;
        background-attachment: local, local, scroll, scroll !important;
    }

    /* Plan 420: the item-detail rail is painted by the page background, not by
       the surface token — the panel header right above it already uses
       var(--linkooc-bg). Same recipe, one different cover colour. */
    .linkooc-detail-container>.nav-tabs,
    .linkooc-detail-container>.nav-tabs:hover,
    .linkooc-detail-container>.nav-tabs:focus-within,
    /* Plan 459: measured live at 390x844, the establishment rail is painted by
       the page background (.linkooc-page-container declares none and the shell
       behind it is --linkooc-bg), exactly like the item-detail rail. */
    .linkooc-page-container>.nav-tabs,
    .linkooc-page-container>.nav-tabs:hover,
    .linkooc-page-container>.nav-tabs:focus-within {
        --lk-tab-scroll-cover: var(--linkooc-bg, #FFFFFF);
    }

    /* Dark theme: a black shadow is invisible on a #171717 surface. */
    main.dark-theme .linkooc-tabs-container,
    main.dark-theme .linkooc-detail-container>.nav-tabs,
    main.dark-theme .linkooc-page-container>.nav-tabs {
        --lk-tab-scroll-shadow: rgba(255, 255, 255, 0.22);
    }

    .linkooc-tabs-container::-webkit-scrollbar,
    .linkooc-tabs-container:hover::-webkit-scrollbar,
    .linkooc-tabs-container:focus-within::-webkit-scrollbar,
    .linkooc-detail-container>.nav-tabs::-webkit-scrollbar,
    .linkooc-detail-container>.nav-tabs:hover::-webkit-scrollbar,
    .linkooc-detail-container>.nav-tabs:focus-within::-webkit-scrollbar,
    .linkooc-page-container>.nav-tabs::-webkit-scrollbar,
    .linkooc-page-container>.nav-tabs:hover::-webkit-scrollbar,
    .linkooc-page-container>.nav-tabs:focus-within::-webkit-scrollbar {
        display: none !important;
        height: 0 !important;
    }

    /* ── Plan 469 (constat F7) : une table large doit DIRE qu'elle continue ──
       Le patron R7b des plans 393/420 ci-dessus, étendu tel quel aux conteneurs
       de tables. Cinq tables ont été mesurées à 390x844 en défilement horizontal
       muet — contenu contre conteneur : /billing-generation 999/358 et 831/358,
       /billing-partner/{id} 403/358 et 420/358, /invoices/{id} 442/358,
       /billing-account/{id} onglet Factures 420/356. Les actions de ligne
       (Factice, Modifier, Supprimer, Envoyer, PDF) sont TOUTES atteignables après
       défilement : il ne manquait que l'indice. On n'ajoute donc que l'indice —
       aucune colonne n'est masquée, aucune n'est réordonnée, rien n'est rétréci.

       Mêmes couches, mêmes variables que R7b : 1-2 sont des « couvercles »
       opaques peints dans la couleur de fond du conteneur et accrochés au
       CONTENU (local), donc ils glissent avec lui ; 3-4 sont les ombres,
       accrochées à l'ÉLÉMENT (scroll), donc épinglées aux bords. Le couvercle
       recouvre son ombre du côté où il n'y a plus rien à défiler — une table qui
       TIENT dans son conteneur n'affiche par construction AUCUNE bande
       (vérifié sur /gestion-dashboard). Pas de JS, pas d'écouteur de défilement.

       Couleur du couvercle : --linkooc-bg, comme les deux rails d'onglets et
       NON --linkooc-surface. Ce n'est pas une préférence, c'est une mesure : sur
       les cinq pages et dans les DEUX thèmes, le premier ancêtre qui peigne
       réellement derrière .table-responsive est div.main (#FFFFFF en clair,
       #0f0f0f en sombre) — les cartes qui les entourent sont transparentes.
       Avec --linkooc-surface (#171717 en sombre) le couvercle se lisait comme
       une bande grise de 32 px sur fond #0f0f0f : 23 contre 15 de luminance,
       mesuré au pixel. C'est exactement pour ça que la couleur est une variable.

       :hover et :focus-within sont listés parce qu'un tap sur écran tactile
       colle :focus-within et que rien ne vient le retirer. */
    .table-responsive,
    .table-responsive:hover,
    .table-responsive:focus-within {
        -webkit-overflow-scrolling: touch;
        --lk-tab-scroll-shadow: rgba(0, 0, 0, 0.22);
        --lk-tab-scroll-cover: var(--linkooc-bg, #FFFFFF);
        background-image:
            linear-gradient(to right, var(--lk-tab-scroll-cover) 65%, transparent),
            linear-gradient(to left, var(--lk-tab-scroll-cover) 65%, transparent),
            linear-gradient(to right, var(--lk-tab-scroll-shadow), transparent),
            linear-gradient(to left, var(--lk-tab-scroll-shadow), transparent);
        background-position: 0 0, 100% 0, 0 0, 100% 0;
        background-repeat: no-repeat;
        background-size: 32px 100%, 32px 100%, 20px 100%, 20px 100%;
        background-attachment: local, local, scroll, scroll;
    }

    /* Thème sombre : une ombre noire est invisible sur une surface #171717. */
    main.dark-theme .table-responsive,
    main.dark-theme .table-responsive:hover,
    main.dark-theme .table-responsive:focus-within {
        --lk-tab-scroll-shadow: rgba(255, 255, 255, 0.22);
    }

    .linkooc-tabs {
        flex-wrap: nowrap;
        min-width: max-content;
    }

    /* !important is required here: pages carry Blazor-scoped .linkooc-tab[b-xxxxx]
       rules whose specificity beats a plain class selector in a global sheet.
       Without it these three declarations are inert (measured: 34px tall tabs). */
    .linkooc-tab {
        white-space: nowrap;
        font-size: 0.8125rem !important;
        padding: 0.5rem 0.75rem !important;
        /* 44px touch target — this is the page's primary navigation. */
        min-height: 44px !important;
        display: inline-flex !important;
        align-items: center !important;
        /* Leaves a sliver of the neighbouring tab visible when a tab is
           scrolled into view, so the bar still reads as "there is more". */
        scroll-margin-inline: 1rem;
    }

    /* Item detail tabs: horizontal scroll instead of wrapping */
    .linkooc-detail-container>.nav-tabs {
        display: flex;
        flex-wrap: nowrap !important;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .linkooc-detail-container>.nav-tabs::-webkit-scrollbar {
        display: none;
    }

    .linkooc-detail-container>.nav-tabs .nav-item {
        flex-shrink: 0;
    }

    .linkooc-detail-container>.nav-tabs .nav-link {
        white-space: nowrap;
        font-size: 0.8125rem;
        padding: 0.5rem 0.75rem;
        /* Same sliver as .linkooc-tab above: scrollIntoView() stops 1rem short
           of the edge so the neighbouring tab stays partly visible and the bar
           still reads as "there is more" (plan 420). */
        scroll-margin-inline: 1rem;
    }

    /* ── Plan 459: the establishment sheet's rail ─────────────────────────
       Same layout half of R7b as the item-detail rail above, with one
       deliberate omission: NO font-size and NO padding. The rail above shrinks
       its labels to 0.8125rem / 0.5rem 0.75rem; here the 7 tabs were measured
       at 84-159 x 44 and the plan's STOP #2 forbids shrinking any control or
       any label. All that was wrong was the wrapping — 3 rows, 130px, stolen
       permanently from the scroller because the rail sits OUTSIDE it. So this
       block only stops the wrap and lets the row scroll.
       flex-wrap needs !important: EstablishmentEdit.razor.css compiles
       `.linkooc-page-container .nav-tabs` to a (0,3,0) scoped selector, and
       Bootstrap's own .nav rule is literal — this global sheet loads first. */
    .linkooc-page-container>.nav-tabs {
        display: flex;
        flex-wrap: nowrap !important;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .linkooc-page-container>.nav-tabs>.nav-item {
        flex-shrink: 0;
    }

    .linkooc-page-container>.nav-tabs>.nav-item>.nav-link {
        white-space: nowrap;
        /* Same 1rem sliver as the two rails above: an item scrolled into view
           stops short of the edge so the neighbour stays partly visible and the
           rail still reads as "there is more". */
        scroll-margin-inline: 1rem;
    }

    /* Page header: stack title/actions vertically */
    .linkooc-page-header .d-flex.justify-content-between {
        flex-direction: row;
        gap: 0.5rem;
    }

    /* Mobile detail: hide duplicate item name (already in MobilePageHeader) */
    .linkooc-mobile-detail .linkooc-detail-title {
        display: none;
    }

    .linkooc-mobile-detail .linkooc-detail-header-row1 {
        justify-content: flex-start;
    }

    .linkooc-mobile-detail .linkooc-panel-header--two-rows {
        padding: 0.5rem 0.75rem;
    }

    /* Mobile detail: fix detail container to fill remaining space and allow scroll */
    .linkooc-mobile-detail .linkooc-detail-container {
        flex: 1;
        min-height: 0;
        height: auto;
        overflow: visible;
    }

    .linkooc-mobile-detail .linkooc-detail-content {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
    }

    /* M3: Hide toolbar controls on mobile */
    .linkooc-toolbar .linkooc-toolbar-reload,
    .linkooc-toolbar .linkooc-toolbar-view-toggle {
        display: none !important;
    }

    .linkooc-toolbar .linkooc-toolbar-filter-text {
        display: none;
    }
}

/* ── Mobile Compact Establishment List (M1) ─────────────────────────── */
.linkooc-mobile-establishment-list {
    display: flex;
    flex-direction: column;
}

.linkooc-mobile-est-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--linkooc-border-color, #eee);
    cursor: pointer;
    min-height: 56px;
    /* M5: 44px minimum touch target */
    -webkit-tap-highlight-color: transparent;
}

.linkooc-mobile-est-row:active {
    background: var(--linkooc-surface-hover, #f8f9fa);
}

.linkooc-mobile-est-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    min-width: 40px;
    border-radius: 50%;
    background: var(--linkooc-primary, #2e7d32);
    color: #fff;
    font-weight: 600;
    font-size: 1rem;
}

.linkooc-mobile-est-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    /* allow text-truncate to work */
}

.linkooc-mobile-est-name {
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--linkooc-text, #212529);
}

.linkooc-mobile-est-meta {
    font-size: 0.8125rem;
    color: var(--linkooc-text-muted, #6d6d6d);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.linkooc-mobile-est-meta i {
    font-size: 0.75rem;
    margin-right: 0.125rem;
}

/* ── Additional mobile overrides ─────────────────────────────────────── */
@media (max-width: 768px) {
    .linkooc-title-right {
        flex-wrap: wrap;
    }

    /* Sticky save bar full width */
    .sticky-save-bar {
        left: 0 !important;
        width: 100% !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE DRILL-DOWN NAVIGATION (duplicated from RCL menu-editor.css
   because RCL static asset fingerprinting serves stale compressed version)
   ═══════════════════════════════════════════════════════════════════════════ */

.mobile-drill-container {
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
    overflow: hidden;
    background: var(--me-bg, #fff);
}

.mobile-drill-detail-content {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.mobile-drill-hide-panel-header .linkooc-panel-header {
    display: none !important;
}

.mobile-drill-search {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--me-border, #dee2e6bf);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.mobile-drill-search .mobile-drill-search-box {
    flex: 1;
    min-width: 0;
}

.mobile-drill-search-box {
    position: relative;
    display: flex;
    align-items: center;
}

.mobile-drill-search-icon {
    position: absolute;
    left: 0.75rem;
    color: var(--me-text-muted, #6d6d6d);
    font-size: 0.875rem;
    pointer-events: none;
}

.mobile-drill-search-input {
    width: 100%;
    padding: 0.625rem 2.25rem 0.625rem 2.25rem;
    border: 1px solid var(--me-border, #dee2e6bf);
    border-radius: 0.5rem;
    font-size: 0.9375rem;
    background: var(--me-bg, #fff);
    color: var(--me-text, #000601);
    outline: none;
    -webkit-appearance: none;
}

.mobile-drill-search-input:focus {
    border-color: var(--me-primary, #08781B);
    box-shadow: 0 0 0 2px var(--me-primary-subtle, #e7f1e8);
}

.mobile-drill-search-input::placeholder {
    color: var(--me-text-muted, #6d6d6d);
}

.mobile-drill-search-clear {
    position: absolute;
    right: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: none;
    background: transparent;
    color: var(--me-text-muted, #6d6d6d);
    cursor: pointer;
    border-radius: 4px;
}

.mobile-drill-search-clear:active {
    background: var(--me-bg-hover, #F7F7F8);
}

/* ── Filters button (opens the filters bottom sheet) ─────────────── */
.mobile-drill-filter-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    min-width: 44px;
    height: 44px;
    border: 1px solid var(--me-border, #dee2e6bf);
    background: var(--me-bg, #fff);
    border-radius: 0.5rem;
    font-size: 1rem;
    color: var(--me-text-muted, #6d6d6d);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    flex-shrink: 0;
}

.mobile-drill-filter-btn:active {
    background: var(--me-bg-hover, #F7F7F8);
    color: var(--me-primary, #08781B);
}

.mobile-drill-filter-btn.has-active-filters {
    border-color: var(--me-primary, #08781B);
    color: var(--me-primary, #08781B);
    background: var(--me-primary-subtle, #e7f1e8);
}

.mobile-drill-filter-count {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: 9px;
    background: var(--me-primary, #08781B);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
}

/* ── Filters sheet rows (reuse .mobile-action-sheet) ─────────────── */
.mobile-filter-sheet-item {
    min-height: 48px;
}

.mobile-filter-sheet-item.active {
    color: var(--me-primary, #08781B);
    font-weight: 600;
}

.mobile-filter-sheet-reset {
    min-height: 48px;
    color: var(--me-text-muted, #6d6d6d);
}

.mobile-drill-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: env(safe-area-inset-bottom, 0);
}

.mobile-drill-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 56px;
    padding: 0.625rem 1rem;
    border: none;
    border-bottom: 1px solid var(--me-border, #dee2e6bf);
    background: var(--me-bg, #fff);
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 120ms ease;
}

.mobile-drill-row:active {
    background: var(--me-bg-hover, #F7F7F8);
}

.mobile-drill-row-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    min-width: 40px;
    border-radius: 50%;
    font-size: 1rem;
}

.mobile-drill-row-icon--folder {
    background: var(--me-primary-subtle, #e7f1e8);
    color: var(--me-primary, #08781B);
}

.mobile-drill-row-icon--item {
    background: var(--me-bg-hover, #F7F7F8);
    color: var(--me-text-muted, #6d6d6d);
}

.mobile-drill-row-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

/* Two lines allowed: "Mousse au chocolat Maison" must not be cut mid-word by the
   price and the ⋮. The row keeps its 56 px floor either way. */
.mobile-drill-row-title {
    font-size: 0.9375rem;
    font-weight: 500;
    color: var(--me-text, #000601);
    white-space: normal;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mobile-drill-row-meta {
    font-size: 0.8125rem;
    color: var(--me-text-muted, #6d6d6d);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Parent path shown under a search result ("Boissons › Vins") */
.mobile-drill-row-path {
    color: var(--me-text-muted, #6d6d6d);
}

.mobile-drill-row-price {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--me-text, #000601);
    white-space: nowrap;
    flex-shrink: 0;
}

.mobile-drill-row-chevron {
    color: var(--me-text-muted, #6d6d6d);
    font-size: 0.75rem;
    flex-shrink: 0;
}

.mobile-drill-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem 1rem;
    color: var(--me-text-muted, #6d6d6d);
    text-align: center;
}

.mobile-drill-empty i {
    font-size: 2.5rem;
    margin-bottom: 0.75rem;
    opacity: 0.5;
}

.mobile-drill-empty p {
    margin: 0;
    font-size: 0.9375rem;
}

.mobile-drill-add-wrapper {
    padding: 0.5rem 1rem 1rem;
}

/* « Ajouter une catégorie / sous-catégorie / un élément » is a primary action on this
   screen: 28 px high is not a finger target. Scoped to the mobile wrapper so the
   desktop tree keeps its compact link. */
.mobile-drill-add-wrapper .btn-add {
    min-height: 44px;
    padding: 0.5rem 0.75rem;
    font-size: 0.9375rem;
}

/* Inline rename straight from a row — same field as the header one, at row scale.
   Two classes deep on purpose: it must beat .mobile-drill-rename-input wherever
   that rule ends up in the cascade. */
.mobile-drill-row-info .mobile-drill-row-rename-input {
    width: 100%;
    min-width: 0;
    min-height: 44px;
    font-size: 0.9375rem;
    font-weight: 500;
}

.mobile-drill-actions-container {
    position: relative;
    flex-shrink: 0;
}

.mobile-drill-actions-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: none;
    background: transparent;
    border-radius: 8px;
    font-size: 1.25rem;
    color: var(--me-text, #000601);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.mobile-drill-actions-btn:active {
    background: var(--me-bg-hover, #F7F7F8);
}

.mobile-drill-actions-menu {
    position: absolute;
    top: 100%;
    right: 0;
    z-index: 100;
    /* Wide enough for "Déplacer les articles vers…" on one line, so every entry
       keeps the same height. */
    min-width: 244px;
    max-width: calc(100vw - 2rem);
    background: var(--me-bg, #fff);
    border: 1px solid var(--me-border, #dee2e6bf);
    border-radius: 0.5rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    overflow: hidden;
}

.mobile-drill-actions-item {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 44px;
    padding: 0.75rem 1rem;
    border: none;
    background: transparent;
    font-size: 0.9375rem;
    color: var(--me-text, #000601);
    cursor: pointer;
    text-align: left;
    white-space: nowrap;
}

.mobile-drill-actions-item:active {
    background: var(--me-bg-hover, #F7F7F8);
}

.mobile-drill-actions-danger {
    color: #dc3545;
}

.mobile-drill-actions-overlay {
    position: fixed;
    inset: 0;
    z-index: 99;
}

.mobile-drill-rename-input {
    flex: 1;
    padding: 0.375rem 0.625rem;
    border: 1px solid var(--me-primary, #08781B);
    border-radius: 0.375rem;
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--me-text, #000601);
    outline: none;
    background: var(--me-bg, #fff);
}

/* ── Collapse the inline-add while the FAB stands in for it ──────────
   The class is now written by the component from its own state (_inlineAddOpen), so it
   comes off again on every close path. It used to be a one-way DOM lock added by an
   `eval` — the wrapper was expanded by adding a second class that nothing ever removed. */
.mobile-drill-add-wrapper--fab-hidden {
    height: 0;
    overflow: hidden;
    padding: 0;
    margin: 0;
    transition: height 200ms ease;
}

/* ── FAB (Floating Action Button) ────────────────────────────────── */
.mobile-fab {
    position: fixed;
    bottom: 24px;
    right: 24px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: none;
    background: var(--me-primary, #08781B);
    color: #fff;
    font-size: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
    cursor: pointer;
    z-index: 100;
    -webkit-tap-highlight-color: transparent;
    transition: transform 120ms ease, box-shadow 120ms ease;
}

.mobile-fab:active {
    transform: scale(0.92);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

/* ── Row ⋮ actions button (articles AND categories) ──────────────── */
.mobile-drill-row-actions-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    min-width: 44px;
    border: none;
    background: transparent;
    border-radius: 50%;
    font-size: 1.125rem;
    color: var(--me-text-muted, #6d6d6d);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    flex-shrink: 0;
}

.mobile-drill-row-actions-btn:active {
    background: var(--me-bg-hover, #F7F7F8);
}

/* ── Bottom Action Sheet ─────────────────────────────────────────── */
.mobile-action-sheet-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(0, 0, 0, 0.4);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    animation: fadeIn 150ms ease;
}

.mobile-action-sheet {
    width: 100%;
    max-width: 420px;
    background: var(--me-bg, #fff);
    border-radius: 1rem 1rem 0 0;
    overflow: hidden;
    animation: slideUp 200ms ease;
}

@keyframes slideUp {
    from {
        transform: translateY(100%);
    }

    to {
        transform: translateY(0);
    }
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.mobile-action-sheet-header {
    padding: 1rem 1.25rem 0.5rem;
    border-bottom: 1px solid var(--me-border, #dee2e6bf);
}

.mobile-action-sheet-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--me-text, #000601);
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mobile-action-sheet-body {
    padding: 0.5rem 0;
}

.mobile-action-sheet-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 44px;
    padding: 0.875rem 1.25rem;
    border: none;
    background: transparent;
    font-size: 1rem;
    color: var(--me-text, #000601);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    text-align: left;
}

.mobile-action-sheet-item:active {
    background: var(--me-bg-hover, #F7F7F8);
}

.mobile-action-sheet-item i {
    font-size: 1.125rem;
    width: 24px;
    text-align: center;
}

.mobile-action-sheet-danger {
    color: #dc3545;
}

.mobile-action-sheet-footer {
    border-top: 1px solid var(--me-border, #dee2e6bf);
    padding: 0.5rem;
}

.mobile-action-sheet-cancel {
    width: 100%;
    padding: 0.875rem;
    border: none;
    background: transparent;
    font-size: 1rem;
    font-weight: 600;
    color: var(--me-primary, #08781B);
    cursor: pointer;
    border-radius: 0.5rem;
    -webkit-tap-highlight-color: transparent;
}

.mobile-action-sheet-cancel:active {
    background: var(--me-bg-hover, #F7F7F8);
}

/* ── Edit mode (reorder) ─────────────────────────────────────────── */
.mobile-edit-mode-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem 1rem;
    background: var(--me-primary-subtle, #e7f1e8);
    border-bottom: 1px solid var(--me-border, #dee2e6bf);
}

.mobile-edit-mode-label {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--me-text, #000601);
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

.mobile-edit-mode-done {
    border: none;
    background: var(--me-primary, #08781B);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 600;
    padding: 0.375rem 1rem;
    border-radius: 0.375rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.mobile-edit-mode-done:active {
    opacity: 0.85;
}

/* ── Drag handle ─────────────────────────────────────────────────── */
.mobile-drag-handle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    min-width: 44px;
    height: 44px;
    color: var(--me-text-muted, #6d6d6d);
    font-size: 1.25rem;
    cursor: grab;
    -webkit-tap-highlight-color: transparent;
    touch-action: none;
}

.mobile-drag-handle:active {
    cursor: grabbing;
    color: var(--me-primary, #08781B);
}

/* ── SortableJS mobile ghost/chosen/drag classes ─────────────────── */
.mobile-sortable-ghost {
    opacity: 0.4;
    background: var(--me-primary-subtle, #e7f1e8) !important;
    border: 2px dashed var(--me-primary, #08781B) !important;
    border-radius: 0.5rem;
}

.mobile-sortable-chosen {
    background: var(--me-bg-hover, #F7F7F8) !important;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    border-radius: 0.5rem;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TELERIK-WINDOW RESPONSIVE — Makes ALL TelerikWindow dialogs mobile-friendly
   Below 768px: force full-width, limit height, scroll content.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 767.98px) {

    /* ── Container: full-width on mobile ─────────────────────────────── */
    .k-window.telerik-blazor {
        width: 95% !important;
        max-width: 95% !important;
        max-height: 85vh !important;
        min-height: unset !important;
        margin: 0 auto;
    }

    /* ── Content area: scrollable ─────────────────────────────────────── */
    .k-window.telerik-blazor .k-window-content {
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch;
    }

    /* ── Title bar: compact ──────────────────────────────────────────── */
    .k-window.telerik-blazor .k-window-titlebar {
        padding: 0.5rem 0.75rem !important;
        font-size: 0.9375rem;
    }

    /* ── Footer: wrap buttons ────────────────────────────────────────── */
    .k-window.telerik-blazor .k-window-footer .d-flex {
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* ── Image preview lightboxes: true fullscreen ───────────────────── */
    .k-window.telerik-blazor[style*="80vw"] {
        width: 100% !important;
        max-width: 100% !important;
        /* Règle mobile uniquement : `100vh` faisait passer le bas de la visionneuse
           sous la barre d'outils iOS. Repli d'abord, `dvh` ensuite. */
        height: 100vh !important;
        height: 100dvh !important;
        max-height: 100vh !important;
        max-height: 100dvh !important;
        border-radius: 0 !important;
    }

    /* ── Tables inside windows: horizontal scroll ────────────────────── */
    .k-window.telerik-blazor .table-responsive {
        -webkit-overflow-scrolling: touch;
    }

    /* ── Multi-column forms: stack on mobile ─────────────────────────── */
    .k-window.telerik-blazor .col-md-6 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* ── Window file picker: reduce fixed dimensions ────────────────── */
    .k-window.window-file-picker {
        height: 85vh !important;
    }

    /* ── Inline buttons (d-flex justify-content-between) wrap ─────── */
    .k-window.telerik-blazor .d-flex.justify-content-between {
        flex-wrap: wrap;
        gap: 0.375rem;
    }

    /* ── Input groups: stack on narrow screens ────────────────────── */
    .k-window.telerik-blazor .input-group {
        flex-wrap: wrap;
    }

    .k-window.telerik-blazor .input-group>.form-control,
    .k-window.telerik-blazor .input-group>.btn {
        flex: 1 1 auto;
    }

    /* ── TelerikGrid inside windows: reduce height ───────────────── */
    .k-window.telerik-blazor .k-grid {
        max-height: 40vh;
    }

    /* ── Pairing dialog cards: single column ─────────────────────── */
    .k-window.k-window-size-50 .col-md-6.mb-3 {
        flex: 0 0 100%;
        max-width: 100%;
    }

    /* ── Add-establishment form: fix legacy TextBox inside dialogs ── */
    .add-establishment-form .k-input.k-input-solid.nav-link {
        padding: 0.5rem 0.75rem !important;
        min-height: 2.75rem;
    }

    .add-establishment-form .k-input.k-input-solid.nav-link input {
        padding-left: 0.5rem !important;
        width: 100% !important;
        font-size: 1rem;
    }

    /* ── Hide copy icon on mobile inside creation forms ─────────── */
    .add-establishment-form .visibleonhover,
    .add-establishment-form .parentvisibleonhover:hover .visibleonhover {
        display: none !important;
    }
}

.mobile-sortable-drag {
    opacity: 0.9;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
    border-radius: 0.5rem;
}

/* ── Reorder button (next to search bar) ─────────────────────────── */
.mobile-reorder-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    min-width: 44px;
    height: 44px;
    border: 1px solid var(--me-border, #dee2e6bf);
    background: var(--me-bg, #fff);
    border-radius: 0.5rem;
    font-size: 1rem;
    color: var(--me-text-muted, #6d6d6d);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    flex-shrink: 0;
}

.mobile-reorder-btn:active {
    background: var(--me-bg-hover, #F7F7F8);
    color: var(--me-primary, #08781B);
}

/* ── Move-to category picker ─────────────────────────────────────── */
.mobile-move-picker {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    max-height: 80vh;
    background: var(--me-bg, #fff);
    border-radius: 1rem 1rem 0 0;
    display: flex;
    flex-direction: column;
    animation: slideUp 0.25s ease-out;
    z-index: 1001;
}

.mobile-move-picker-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 1rem;
    border-bottom: 1px solid var(--me-border, #dee2e6bf);
    flex-shrink: 0;
}

.mobile-move-picker-title {
    font-size: 1rem;
    font-weight: 600;
    margin: 0;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mobile-move-picker-list {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: env(safe-area-inset-bottom, 0);
}

.mobile-move-picker-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.875rem 1rem;
    border: none;
    background: none;
    text-align: left;
    font-size: 0.9375rem;
    color: var(--me-text, #000601);
    cursor: pointer;
    border-bottom: 1px solid var(--me-border-subtle, #f0f0f0);
}

.mobile-move-picker-item:active {
    background: var(--me-bg-hover, #F7F7F8);
}

/* ── Dropdown menus: jamais plus larges que l'écran (plan 440) ─────────────
   Le patron maison est recopié dans 11 pages (copies scoped du plan 401) avec
   le même ancrage `right: 0; min-width: 280px`, qui suppose le toggle collé au
   bord droit. Ce filet est VOLONTAIREMENT hors media query : un téléphone en
   paysage fait 640–930 px de large, dépasse le seuil 768 et reçoit le rendu
   bureau — c'est justement là que l'opérateur voit des menus mal placés.
   `max-width` ne se bat pas avec les `min-width: 280px` scoped (propriétés
   différentes, et 280 < 100vw-1rem dès 296 px de large). */
.linkooc-dropdown-menu {
    max-width: calc(100vw - 1rem);
}

/* ── Dropdown menus: scrollable on mobile ─────────────────────────────── */
@media (max-width: 768px) {
    .linkooc-dropdown-menu {
        max-height: calc(100dvh - 120px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* ── Dropdown menus: écran très bas = téléphone en paysage (plan 440) ──────
   Mesuré le 2026-08-10 à 844×390 : le menu est `position: absolute` sous un
   toggle qui vit dans l'en-tête de page (top réel 144→215 px). Avec 390 px de
   haut, une carte de 250–290 px sort par le bas — et aucune règle ne s'applique
   là, l'ancien filet étant enfermé dans `max-width: 768px` alors qu'un
   téléphone couché fait 640–930 px de large. 5 instances sur 12 étaient
   tronquées (translations, menus, documents, clients réservation, utilisation
   IA), items non cliquables.

   `max-height` seul ne suffit pas : la hauteur disponible dépend du haut du
   menu, que CSS ne sait pas lire tant qu'on reste en `absolute`. On bascule
   donc en `fixed` sur ces seuls écrans — le menu s'accroche au coin haut-droit
   du viewport, à quelques pixels du toggle qui est lui aussi tout en haut.

   Le seuil 500px ne touche ni les téléphones debout (740–844 de haut) ni les
   tablettes couchées (768) ni le bureau : uniquement le cas cassé.

   !important obligatoire : cette feuille est chargée AVANT
   LinkoocBackOffice.styles.css (App.razor:39 puis :44), donc les 11 copies
   scoped `:where(.linkooc-dropdown-menu)[b-xxxxx]` gagnent à spécificité
   égale. Sans les drapeaux, ce bloc serait inerte — même leçon que les
   `.linkooc-tab` du plan 393. */
@media (max-height: 500px) {
    .linkooc-dropdown-menu {
        position: fixed !important;
        top: 0.5rem !important;
        bottom: auto !important;
        right: 0.5rem !important;
        left: auto !important;
        max-height: calc(100dvh - 1rem) !important;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* ── F6 (plan 457) — verrou de défilement pendant une popup ────────────────
   Les popups maison (`<div class="modal fade show d-block">` + backdrop écrit
   à la main, /user-management et ses voisines) ne passent PAS par le JS de
   Bootstrap : rien ne pose de verrou nulle part, et la liste continuait de
   défiler derrière la popup ouverte (mesuré 0 → 500).

   Le scroller réel de l'application n'est ni `body` ni `.linkooc-page-container`
   mais `main > .content` (BackOfficeLayout.razor:314 — mesuré clientHeight 788
   / scrollHeight 1512), d'où la cible.

   `overflow: hidden` et non `clip` : `hidden` garde l'élément scrollable, donc
   la position de défilement est CONSERVÉE et la liste reprend là où elle était
   à la fermeture ; `clip` la remettrait à zéro.

   La portée tient au `:has()` : la règle n'existe que tant qu'un `.modal.show`
   est dans le document. Un seul sélecteur, une seule propriété — volontairement
   à part des autres blocs `.content` de ce fichier pour ne rien leur disputer. */
@media (max-width: 768px) {
    body:has(.modal.show) .content {
        overflow: hidden !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   R12 TOUCH TARGETS — Telerik controls, panel buttons, dialog close (plan 399)

   The repo's floor is 44px (R12 in SubAgents/Design/LINKOOC_MOBILE_RESPONSIVE.md).
   Plan 393 applied it to .linkooc-tab and to the .linkooc-page-header squares;
   this block extends it to the controls that were still below it — measured in
   prod on 2026-08-07 at 390×844: Telerik fields 38px, .k-list-item 32px,
   .btn / .Matrix_Button 37px, Bootstrap .btn-close 32×32.

   Two rules of engagement for this file, both learned the hard way:

   1. !important is MANDATORY, not cosmetic. Pages carry literal inline <style>
      blocks (and Blazor-scoped [b-xxxxx] rules) that are injected AFTER this
      global sheet and win at equal specificity. That is exactly why the
      pre-existing .linkooc-tab declarations here were inert until plan 393.
      Do not "clean up" these flags.
   2. Desktop :hover / :focus-within variants carry higher specificity than a
      plain class and there is no way to un-hover a touch screen — a tap latches
      :focus-within with nothing to clear it. Any selector below that has a
      desktop interaction variant lists those pseudo-classes explicitly.

   Only the SURFACE grows here. font-size is deliberately never touched: the
   audit finding was about tap area, not legibility.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── Telerik fields ──────────────────────────────────────────────────
       In Telerik UI for Blazor 8 / Kendo Themes 8 these classes sit on the
       WRAPPER element; the real <input> is the .k-input-inner child. Sizing the
       wrapper is therefore the correct anchor — and 2.75rem is the same value
       the .add-establishment-form rule above already uses, kept consistent.
       .k-picker covers DropDownList/DatePicker, .k-combobox the ComboBox;
       .k-textbox is the legacy alias still emitted on TelerikTextBox. */
    .k-input,
    .k-input:hover,
    .k-input:focus-within,
    .k-textbox,
    .k-textbox:hover,
    .k-textbox:focus-within,
    .k-picker,
    .k-picker:hover,
    .k-picker:focus-within,
    .k-combobox,
    .k-combobox:hover,
    .k-combobox:focus-within,
    .k-dropdownlist,
    .k-dropdownlist:hover,
    .k-dropdownlist:focus-within {
        min-height: 2.75rem !important;
        /* 44px */
    }

    /* The inner control must fill the taller wrapper, otherwise the caret and
       the real hit area stay in a 38px band floating inside a 44px box. */
    .k-input>.k-input-inner,
    .k-picker>.k-input-inner,
    .k-combobox>.k-input-inner,
    .k-dropdownlist>.k-input-inner {
        align-self: stretch;
    }

    /* ── Dropdown options ────────────────────────────────────────────────
       Telerik renders popups in a body-level .k-animation-container, outside
       the component's DOM, so a global rule is the only way to reach them.
       .k-list-optionlabel is the placeholder row ("Aucun filtre"). */
    .k-list-item,
    .k-list-item:hover,
    .k-list-optionlabel,
    .k-list-optionlabel:hover {
        min-height: 2.75rem !important;
        align-items: center !important;
    }

    /* ── Panel buttons ───────────────────────────────────────────────────
       Matrix_Button always emits .Matrix_Button and, with the default
       UseBootstrapClasses = true, .btn as well — both are listed because some
       call sites opt out of the Bootstrap classes.
       min-height/min-width only GROW a control: the 44×44 header squares that
       plan 393 pinned in linkooc-theme.css keep their explicit width/height,
       and buttons already at or above 44px are left exactly as they are. */
    .btn,
    .btn:hover,
    .btn:focus-within,
    .Matrix_Button,
    .Matrix_Button:hover,
    .Matrix_Button:focus-within {
        min-height: 2.75rem !important;
        min-width: 2.75rem !important;
    }

    /* ── Dialog close cross ──────────────────────────────────────────────
       Bootstrap ships .btn-close as box-sizing: content-box, width/height 1em
       plus .25em padding. Switching to border-box with an explicit 44×44 and no
       padding gives a square hit area, while background-size pins the glyph at
       its original 1rem — the cross must not visually inflate with the target.
       .k-window-titlebar-action is the TelerikWindow equivalent; it is scoped to
       the titlebar so this can never reach a NumericTextBox spinner button
       (stacking two 44px spinners would make the field 88px tall). */
    .btn-close,
    .btn-close:hover,
    .btn-close:focus-within {
        box-sizing: border-box !important;
        width: 2.75rem !important;
        height: 2.75rem !important;
        /* Plan 459: measured 43 x 44 in the three Bootstrap confirmation
           modals of this sheet — one pixel short, and `width` alone could not
           explain it. The cross is a flex item of `.modal-header`
           (`display: flex`), so the default `flex-shrink: 1` let the title
           squeeze it below its declared width. A declared size is not a floor
           inside a flex row; these three lines make it one. */
        min-width: 2.75rem !important;
        min-height: 2.75rem !important;
        flex-shrink: 0 !important;
        padding: 0 !important;
        background-position: center !important;
        background-size: 1rem auto !important;
        background-repeat: no-repeat !important;
    }

    .k-window-titlebar .k-window-titlebar-action,
    .k-window-titlebar .k-window-titlebar-actions .k-button {
        min-width: 2.75rem !important;
        min-height: 2.75rem !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   R12B TOUCH TARGETS — the families plan 399 did not reach (plan 402)

   Plan 399 lifted the TELERIK controls, the .btn family and the dialog close
   cross to the 44px floor. The controls below are hand-rolled (page-level
   <style> blocks, RCL scoped CSS) and stayed under it. Measured live on
   /establishments/340 at 390x844 on 2026-08-07, BEFORE this block:

     .menu-scrollable .nav-link ............ 37       (burger navigation)
     .nav-tabs .nav-link ................... 39       (Contenu / SEO)
     .linkooc-translation-nav__item ........ 40       (Traductions categories)
     .linkooc-translation-segment__button .. 27 x 50  (Tous / Manquantes)
     .tpl-icon-btn ......................... 30 x 30  (Modifier/Supprimer/Voir)
     .kiosk-advanced-toggle ................ 27.5     (« Avancé »)
     .k-spinner-increase / -decrease ....... 21 x 29  (compteur du kiosque)
     .lk-visual-asset-filter-button ........ 23 x 28  (All / Linkooc / Local)
     input[type=range] ..................... 16       (Largeur, Écart)
     .k-input-inner ........................ 42       (tous les champs texte)

   Same two rules of engagement as the R12 block above: !important is load
   bearing (page <style> elements are literal and arrive AFTER this global
   sheet, so they win at equal specificity), and every selector with a desktop
   :hover / :focus-within variant lists those pseudo-classes explicitly because
   a tap latches :focus-within on a touch screen with nothing to clear it.

   Only the SURFACE grows. font-size is never touched — the finding is about
   tap area, not legibility.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── Burger navigation rows ──────────────────────────────────────────
       Scoped to nav.menu-scrollable on purpose: a bare `.nav-link` would also
       hit `.add-establishment-form .k-input.k-input-solid.nav-link` (a text
       field wearing the class) and every Bootstrap nav in the app. */
    .menu-scrollable .nav-link,
    .menu-scrollable .nav-link:hover,
    .menu-scrollable .dropdown-item,
    .menu-scrollable .dropdown-item:hover {
        min-height: 2.75rem !important;
        display: flex !important;
        align-items: center !important;
    }

    /* ── Bootstrap tab bars (Contenu / SEO in the section detail, and every
       other .nav-tabs in the back office) ───────────────────────────────── */
    .nav-tabs .nav-link,
    .nav-tabs .nav-link:hover,
    .nav-tabs .nav-link:focus-within {
        min-height: 2.75rem !important;
        display: inline-flex !important;
        align-items: center !important;
    }

    /* ── Traductions: category list + Tous/Manquantes segmented control ─── */
    .linkooc-translation-nav__item,
    .linkooc-translation-nav__item:hover,
    .linkooc-translation-segment__button,
    .linkooc-translation-segment__button:hover {
        min-height: 2.75rem !important;
        align-items: center !important;
    }

    .linkooc-translation-segment__button,
    .linkooc-translation-segment__button:hover {
        min-width: 2.75rem !important;
    }

    /* ── Square icon buttons: Apparence › Templates (Modifier / Supprimer /
       Voir dans un nouvel onglet) and the Tags chip actions ─────────────── */
    .tpl-icon-btn,
    .tpl-icon-btn:hover,
    .tpl-icon-btn:focus-within,
    .tag-chip-btn,
    .tag-chip-btn:hover,
    .tag-chip-btn:focus-within {
        width: 2.75rem !important;
        height: 2.75rem !important;
        min-width: 2.75rem !important;
        min-height: 2.75rem !important;
    }

    /* ── Kiosque: the « Avancé » disclosure ─────────────────────────────── */
    .kiosk-advanced-toggle,
    .kiosk-advanced-toggle:hover {
        min-height: 2.75rem !important;
        display: flex !important;
        align-items: center !important;
    }

    /* ── Kiosque: the ▲▼ of the inactivity counter ───────────────────────
       Telerik stacks the two spinner buttons in a 29px column, so each one is
       21px tall. Making them 44px TALL would inflate the whole field to 88px;
       laying the column out as a ROW instead gives each arrow a real 44x44
       square while the field itself stays at its 44px floor. Scoped to
       .k-numerictextbox so it can never reach another Telerik spinner. */
    .k-numerictextbox .k-input-spinner {
        flex-direction: row !important;
        width: auto !important;
    }

    .k-numerictextbox .k-spinner-increase,
    .k-numerictextbox .k-spinner-increase:hover,
    .k-numerictextbox .k-spinner-decrease,
    .k-numerictextbox .k-spinner-decrease:hover {
        min-width: 2.75rem !important;
        min-height: 2.75rem !important;
    }

    /* ── Apparence › Assets & Tags: the All / Linkooc / Local scope chips ──
       These live in the RCL (VisualAssetEditor.razor.css) as a 1.45rem pill
       row, so the scoped [b-xxxxx] attribute beats a plain class here. */
    .lk-visual-asset-filter-button,
    .lk-visual-asset-filter-button:hover,
    .lk-visual-asset-filter-button.is-active {
        min-height: 2.75rem !important;
        min-width: 2.75rem !important;
        padding-left: 0.75rem !important;
        padding-right: 0.75rem !important;
    }

    /* The pill group's own 999px radius has to grow with its children,
       otherwise the chips square off against a 1.65rem-tall container. */
    .lk-visual-asset-filter-group {
        border-radius: 1.5rem !important;
    }

    /* ── Sliders (Apparence › Assets « Largeur », Tags « Écart ») ─────────
       The plan is explicit: grow the TOUCH ZONE, not the track. A 44px-thick
       rail is ugly and nobody asked for it. content-box + 14px of vertical
       padding leaves Chrome's intrinsic 16px track exactly as it renders and
       simply wraps 14px of live hit area above and below it (16 + 28 = 44).
       box-sizing is forced because linkooc-legacy-theme.css sets
       `* { box-sizing: border-box }`, and horizontal padding stays at 0 so a
       `width: 100%` slider still measures 100% of its column. */
    input[type="range"] {
        box-sizing: content-box !important;
        padding-top: 14px !important;
        padding-bottom: 14px !important;
    }

    /* ── Text fields ─────────────────────────────────────────────────────
       Types are listed one by one on purpose: a bare `input` would fatten
       checkboxes, radios, switches and — worst of all — the range inputs
       handled just above. .k-input-inner is the real <input> inside Telerik's
       44px wrapper; it measured 42px, so the thing a finger actually lands on
       was still under the floor even after plan 399. */
    input[type="text"],
    input[type="search"],
    input[type="email"],
    input[type="tel"],
    input[type="url"],
    input[type="number"],
    input[type="password"],
    input[type="date"],
    input[type="time"],
    textarea,
    select,
    .form-control,
    .linkooc-input,
    .k-input-inner {
        min-height: 2.75rem !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   R12C TOUCH TARGETS — .k-button, the family both earlier passes missed
   (plan 420)

   Plan 399 (R12) named .k-input, .k-textbox, .k-picker, .k-combobox,
   .k-dropdownlist, .k-list-item, .k-list-optionlabel, .btn, .Matrix_Button,
   .btn-close and the window titlebar actions. Plan 402 (R12B) named the
   hand-rolled families. NEITHER named `.k-button` — which is precisely the
   class <TelerikButton> emits, and it dominates the article detail. Measured
   live on the item detail at 390x844 on 2026-08-08, computed min-height `auto`
   on every one of them:

     telerik-blazor k-button ... bg-ai rounded ..... 38 x 174  « Générer avec IA »
     telerik-blazor k-button shake-vertical ........ 38 x 123  « Ajout Prix »
     telerik-blazor k-button d-flex ................ 38 x 109  « Ajouter » (Accord)
     telerik-blazor k-button bg-ai rounded mb-1 .... 30 x 30   les 5 tons du Sommelier
     telerik-blazor k-button bg-transparent ........ 30 x 32   les 14 allergènes
     k-toolbar-toggle-button ....................... 38 x 38   B / I / U / S
     k-clear-value ................................. 28 x 28   la croix « vider »

   Same two rules of engagement as R12 and R12B: !important is load bearing
   (literal page <style> blocks and Blazor [b-xxxxx] rules arrive AFTER this
   global sheet and win at equal specificity), and every selector with a desktop
   :hover / :focus-within variant lists those pseudo-classes explicitly because
   a tap latches :focus-within on a touch screen with nothing to clear it.

   Only the SURFACE grows. font-size is never touched anywhere in this block —
   the finding is about tap area, not legibility.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── The .k-button family ────────────────────────────────────────────
       Three exclusions, and each one would make the UI worse, not better:

       .k-input-button  is the arrow INSIDE a field that R12 already floors at
                        44px (measured 44 x 29). The real target is the whole
                        field; widening the arrow only eats the text column.
       .k-spinner-increase / .k-spinner-decrease
                        are STACKED inside a field. Giving each one a 44px
                        height would make the field 88px tall — the exact trap
                        plan 399 already called out for .btn-close. R12B above
                        already handles them properly, by laying the pair out
                        as a ROW inside .k-numerictextbox so each arrow gets a
                        real 44x44 square while the field stays at 44.

       NOT excluded, deliberately: `.k-window-titlebar-actions .k-button`, which
       plan 399 already pins at 44x44. min-* can only grow a box, so this rule
       merely restates that size — an exclusion would be dead code. */
    .k-button:not(.k-input-button):not(.k-spinner-increase):not(.k-spinner-decrease),
    .k-button:not(.k-input-button):not(.k-spinner-increase):not(.k-spinner-decrease):hover,
    .k-button:not(.k-input-button):not(.k-spinner-increase):not(.k-spinner-decrease):focus-within {
        min-height: 2.75rem !important;
        min-width: 2.75rem !important;
    }

    /* ── The « vider » cross of a dropdown / combobox (F9) ────────────────
       28x28, and it is NOT a .k-button, so the rule above never reaches it.
       Same discipline as .btn-close in R12: border-box so the declared size IS
       the hit area, and the glyph is left strictly alone — it is a child <span>
       whose size does not follow its container, so nothing has to be pinned and
       no font-size is touched.

       Height comes from `align-self: stretch`, NOT from min-height, and that is
       a deliberate trade: .k-input is a border-box flex row floored at 2.75rem
       with a 1px border, so its content box is 42px. A 44px min-height on a
       child would push the FIELD to 46px — inflating the very control R12 sized.
       Stretch gives a 44 x 42 target inside a 44px-tall field that is itself
       one big target. The 28px-wide pinhole, which was the finding, is gone. */
    .k-input .k-clear-value,
    .k-input .k-clear-value:hover,
    .k-picker .k-clear-value,
    .k-picker .k-clear-value:hover,
    .k-combobox .k-clear-value,
    .k-combobox .k-clear-value:hover,
    .k-dropdownlist .k-clear-value,
    .k-dropdownlist .k-clear-value:hover {
        box-sizing: border-box !important;
        min-width: 2.75rem !important;
        align-self: stretch !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    /* ── F8 (plan 459) — la flèche d'ouverture d'un champ Telerik ─────────
       `.k-input-button` is the arrow inside a DropDownList / DatePicker /
       ComboBox. R12C above EXCLUDES it from the .k-button floor, and that
       exclusion stays right: a `min-height` on it pushes the whole FIELD to
       46px, which plan 420 measured and rejected. What the exclusion's note
       got wrong is the width — it read 44 x 29 (h x w), i.e. the arrow is
       44px TALL but only 29px WIDE. On this page that is 3 arrows on Général
       (type + 2 dates), 2 on Compte facturation, 3 in the user-access modal
       and 5 in the subscription dialog.

       So this is the .k-clear-value recipe verbatim, and for the same reason:
       width from `min-width` (free — it eats slack, not height), height from
       `align-self: stretch` and NEVER from `min-height`. The field's own
       2.75rem floor from R12 is untouched, so its height cannot move.
       :hover / :focus-within are listed because a tap latches :focus-within
       on a touch screen with nothing to clear it. */
    .k-input .k-input-button,
    .k-input .k-input-button:hover,
    .k-input .k-input-button:focus-within,
    .k-picker .k-input-button,
    .k-picker .k-input-button:hover,
    .k-picker .k-input-button:focus-within,
    .k-combobox .k-input-button,
    .k-combobox .k-input-button:hover,
    .k-combobox .k-input-button:focus-within,
    .k-dropdownlist .k-input-button,
    .k-dropdownlist .k-input-button:hover,
    .k-dropdownlist .k-input-button:focus-within {
        box-sizing: border-box !important;
        min-width: 2.75rem !important;
        align-self: stretch !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    /* ── F9 (plan 459) — les croix et boutons de dialogue restés sous 44 ──
       `.matrix-close-btn` is MatrixComponents' own close cross
       (matrix-components.css:498): `background: none; border: none;
       padding: 0.25rem`, measured 28 x 29. It is NOT a `.btn`, NOT a
       `.btn-close` and NOT a `.k-button`, so none of R12 / R12B / R12C ever
       reached it. Same discipline as .btn-close in R12: border-box, so the
       declared square IS the hit area, and `font-size` is left alone — the
       glyph must not inflate with the target. */
    .matrix-close-btn,
    .matrix-close-btn:hover,
    .matrix-close-btn:focus-within {
        box-sizing: border-box !important;
        width: 2.75rem !important;
        height: 2.75rem !important;
        min-width: 2.75rem !important;
        min-height: 2.75rem !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
        padding: 0 !important;
    }

    /* The « Filtres avancés » funnel of Matrix_Select (Matrix_Select.razor:30),
       measured 41 x 44 — only the width was short. */
    .matrix-select-filter-btn,
    .matrix-select-filter-btn:hover,
    .matrix-select-filter-btn:focus-within {
        box-sizing: border-box !important;
        min-width: 2.75rem !important;
        min-height: 2.75rem !important;
        display: inline-flex !important;
        align-items: center !important;
        justify-content: center !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   F2 — THE SECTION DETAIL HEADER STAYS ON SCREEN (plan 402)

   /establishments/340 › Sections › a section is a real drill-down: the back
   « ‹ » lives in .mobile-page-header and the Contenu / SEO bar is the
   ul.nav.nav-tabs of WebsiteSectionDetailPanel. Scrolling the form took both
   off screen, so reaching SEO — or going back — meant scrolling all the way up.

   .mobile-page-header ALREADY declares `position: sticky; top: 0` at the top of
   this file. It was inert, and the reason is worth writing down: sticky
   resolves against the nearest SCROLLING ancestor, and both
   .linkooc-mobile-detail (overflow-y: auto) and .linkooc-page-container
   (overflow: hidden, linkooc-theme.css) qualify — but neither actually scrolls
   on this page. Both stretch to the full 1423px of content while the element
   that really scrolls is `main > .content` (measured: clientHeight 788,
   scrollHeight 1439). A sticky element inside a scroll container that never
   scrolls simply never sticks.

   So the fix is two-part: neutralise the two dead scroll containers so sticky
   resolves against .content, then pin the tab bar under the header.

   :has() scopes this to the website-section detail only —
   .linkooc-panel-header--detail is emitted by WebsiteSectionDetailPanel.razor
   and nowhere else — so no other master/detail panel changes behaviour.

   BUDGET: the plan caps the sticky stack at ~110px. Header (65) + tabs (39) =
   104px. Adding .linkooc-panel-header--detail (56px, and redundant — it repeats
   the section name the back button already shows) would push it to 160px, so
   that one is deliberately left to scroll away.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* Height of .mobile-page-header: .mobile-back-btn is a fixed 44px, plus
       0.625rem of padding top and bottom, plus the 1px bottom border. The
       title is `white-space: nowrap`, so it cannot wrap this open. Single
       source of truth for the offset below. */
    .linkooc-mobile-detail:has(.linkooc-panel-header--detail) {
        --lk-mobile-detail-header-h: 65px;
    }

    .linkooc-page-container:has(.linkooc-panel-header--detail),
    .linkooc-mobile-detail:has(.linkooc-panel-header--detail) {
        overflow: visible !important;
    }

    .linkooc-mobile-detail:has(.linkooc-panel-header--detail) .mobile-page-header {
        position: sticky !important;
        top: 0 !important;
        z-index: 10 !important;
    }

    /* An opaque background is not decoration here: without it the form scrolls
       visibly through the tab bar. --linkooc-surface is opaque in both themes
       (same variable the tab-scroll shadows above rely on). */
    .linkooc-mobile-detail:has(.linkooc-panel-header--detail) > ul.nav.nav-tabs {
        position: sticky !important;
        top: var(--lk-mobile-detail-header-h, 65px) !important;
        z-index: 9 !important;
        background: var(--linkooc-surface, #FEFEFE) !important;
    }
}

/* ── Dialogue « Planification de publication » — cibles tactiles (plan 425) ─────────
   « Valider » / « Annuler » sont des TelerikButton : le CSS scopé du composant ne les
   atteint pas de façon fiable, la règle vit donc ici. min-height SEUL — élargir le
   dialogue est interdit (il tient aujourd'hui en 371×433 dans 390×844). */
@media (max-width: 767.98px) {
    .schedule-dialog-actions .k-button {
        min-height: 44px;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   R12F CIBLES TACTILES — les cases à cocher Telerik et la sortie du mode
   Réorganiser (plan 436, findings F5 et F1)

   Mesuré à 390x844 le 2026-08-10 :

     .k-checkbox (dialogue « Dupliquer un menu », x2) ..... 16 x 16
     .mobile-edit-mode-done « Terminé » ................... 87 x 33

   Aucune des deux familles n'avait jamais été nommée : les plans 399 (R12),
   402 (R12B) et 420 (R12C) ont couvert les champs, les familles maison et
   `.k-button`, jamais `.k-checkbox` ni la barre du mode édition.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── F5 : la case à cocher ────────────────────────────────────────────
       CHOIX DE LA VOIE, et pourquoi. Le plan laissait deux options :

       (a) rendre `.k-checkbox-label` cliquable et la floorer à 44 — ÉCARTÉE.
           Nos cases viennent de Matrix_CheckBox, qui enveloppe le
           <TelerikCheckBox> dans un Matrix_FormField : le libellé rendu est un
           `<label class="form-label">` SANS attribut `for`, et il n'y a aucun
           `.k-checkbox-label` dans le DOM. Cliquer ce libellé ne coche rien
           aujourd'hui ; le rendre cliquable demanderait d'éditer les .razor de
           MatrixComponents — hors périmètre d'un plan de feuilles partagées, et
           un piège de plus (deux libellés voisins à 44 de haut se toucheraient).

       (b) une surcouche invisible qui étend la zone SANS grossir le carré
           peint — RETENUE. Le carré reste à 16x16, la charte ne bouge pas,
           et la cible passe à 44x44.

       ::after et non ::before : le thème Kendo peint la coche elle-même dans
       `.k-checkbox:checked::before` (masque SVG). ::after n'est utilisé que
       sous `.k-ripple-container`, un conteneur que Telerik Blazor n'émet pas
       (vérifié : la classe n'apparaît nulle part dans le balisage, seulement
       dans la feuille Kendo). `.k-checkbox` est déjà `position: relative` et
       `-webkit-appearance: none` dans le thème, donc le pseudo-élément est bien
       rendu sur cet <input> et le tap dessus coche la case.

       Taille POSÉE, pas déduite d'un `inset` négatif : le bloc conteneur d'un
       enfant absolu est la boîte de PADDING, pas la boîte de bordure. Sur un
       carré de 16 avec 1px de bordure elle fait 14, et `inset: -14px` donnait
       42x42 — mesuré, deux pixels sous le plancher. Un carré de 2.75rem centré
       par translation vaut 44 quelle que soit la bordure du thème.

       Deux cases voisines ne se recouvrent pas : dans le dialogue Dupliquer
       chacune vit dans un `.col-12.mb-3` avec son libellé au-dessus, ce qui
       espace les carrés de 47px — mesuré — soit 3 de plus que les 44 de la
       surcouche.

       Le glyphe est laissé strictement tranquille : aucun `font-size`, aucune
       largeur/hauteur sur `.k-checkbox` — même discipline que
       `.k-input .k-clear-value` du plan 420 plus haut. */
    .k-checkbox::after {
        content: "" !important;
        position: absolute !important;
        top: 50% !important;
        left: 50% !important;
        width: 2.75rem !important;
        height: 2.75rem !important;
        transform: translate(-50%, -50%) !important;
        display: block !important;
        background: transparent !important;
        /* Coins CARRÉS, volontairement : le test de pointage respecte le
           border-radius, et un rayon rognerait les quatre coins du carré de 44
           qu'on vient de poser. La surcouche est transparente — un arrondi
           n'aurait aucun effet visible, seulement un effet sur la cible. */
        border-radius: 0 !important;
    }

    /* ── F1 : « Terminé », la seule sortie du mode Réorganiser ────────────
       87 x 33 mesurés, et c'est P1 et non P3 parce qu'il n'y a pas d'autre
       sortie : la barre de recherche qui porte le bouton ↕ est masquée en mode
       édition (`@if (!_isEditMode)`) et Échap ne fait rien.

       min-height SEUL (la largeur est déjà à 87). La barre
       `.mobile-edit-mode-bar` fait 50px de haut avec 0.5rem de padding
       vertical : 44 + 8 + 8 = 60, elle grandit donc de 10px au lieu de rogner
       le bouton — `align-items: center` sur un conteneur flex n'écrase pas un
       enfant, il le centre. `flex-shrink: 0` garantit que le libellé du mode ne
       reprend pas cette largeur si le texte s'allonge. */
    .mobile-edit-mode-done,
    .mobile-edit-mode-done:hover,
    .mobile-edit-mode-done:focus-within {
        box-sizing: border-box !important;
        min-height: 2.75rem !important;
        min-width: 2.75rem !important;
        flex-shrink: 0 !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   R12G CIBLES TACTILES — cases à cocher et boutons radio des pages ADMIN
   (plan 474, constats F7a / F7b / F8 / F10 ; F13 traité en fin de bloc)

   Mesuré sur le BackOffice publié en Production à 390x844 le 2026-08-13 :

     /pages-management/create|edit  .Matrix_FormField   292 x 31   (case 16x16)
     /pages-management filtres      .k-radio-list-item   68 x 37   (radio 16x16)
     /role-management « Éditer »    .form-check         267 x 64,5 (case 243x18 !)
     /user-edit?tab=roles           .form-check         358 x 24   (case 14x14)

   PORTÉE — décision explicite, demandée par le STOP n°4 du plan :

   (1) Les familles TELERIK (`.k-radio`, et `.k-checkbox` déjà traité par R12F
       plus haut) sont floorées GLOBALEMENT, dans le média mobile, comme R12,
       R12B, R12C et R12F avant elles. Ce plancher est délibérément à l'échelle
       du BackOffice : un radio de 16 px est aussi injoignable au doigt sur une
       autre page que sur celle-ci. La fuite est donc VOULUE et mesurée (voir le
       rapport du plan : /ai-automations et /menus mesurés avant/après).

   (2) La famille BOOTSTRAP `.form-check` est SCOPÉE, par une classe d'adhésion
       `lk-touch-check-list` posée sur les deux listes concernées
       (RoleManagement.razor, UserEditForm.razor). Décorer `.form-check`
       globalement toucherait aussi :
         - les interrupteurs `.form-switch` (AIAutomations, ReservationSettings),
           dont la géométrie est déjà à leur charge ;
         - les cases de sélection multiple `position-absolute` posées dans un
           coin de carte (Pages.razor:194, Matrix_Grid), qu'un `min-height` de
           44 px déplacerait sans rien gagner ;
         - la matrice de permissions à 4 cases par ligne de PageForm.razor
           (196-216), qu'il tripleraît en hauteur.
       Et surtout : la liste de RoleManagement a besoin d'une RÉPARATION de la
       case elle-même (voir plus bas), qui ne doit surtout pas partir en global.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── F7a : les 3 cases de /pages-management/create et /edit/{id} ───────
       `Matrix_CheckBox` rend un `<label class="form-label">` PUIS l'input, sur
       la même ligne : la ligne existait déjà, elle faisait 31 px et son libellé
       était inerte (aucun `for`). Le plan 474 apparie les deux dans
       `Matrix_CheckBox.razor` (id généré + `for`), ce qui rend le libellé
       cliquable ; il ne restait plus qu'à floorer la ligne.

       La case reste 16x16 : c'est le LIBELLÉ qui porte les 44 px (inline-flex
       centré), et la surcouche 44x44 de R12F couvre déjà le carré lui-même.
       Deux lignes voisines ne se disputent plus cette surcouche : elles étaient
       espacées de 31 px (deux surcouches de 44 se chevauchaient de 13 px), elles
       le sont maintenant de 44. */
    .Matrix_FormField:has(input.k-checkbox) {
        display: flex !important;
        flex-wrap: wrap !important;
        align-items: center !important;
        gap: 0 0.5rem !important;
        min-height: 2.75rem !important;
    }

    /* `flex: 1 1 auto` n'est pas cosmétique : sans lui le libellé s'arrête à son
       texte (« Page d'accueil » ≈ 100 px sur 292) et le centre de la ligne tombe
       sur le conteneur `.Matrix_FormField`, qui est inerte. La garde du plan
       exige que `elementFromPoint` au centre rende la case OU son libellé. */
    .Matrix_FormField:has(input.k-checkbox) > .form-label {
        order: 2 !important;
        flex: 1 1 auto !important;
        display: inline-flex !important;
        align-items: center !important;
        min-height: 2.75rem !important;
        margin-bottom: 0 !important;
        cursor: pointer !important;
    }

    .Matrix_FormField:has(input.k-checkbox) > input.k-checkbox {
        order: 1 !important;
        flex: 0 0 auto !important;
    }

    /* ── F7b : les 6 radios du panneau de filtres de /pages-management ─────
       `k-radio` / `k-radio-label` sont des classes Telerik : la règle GAGNANTE
       est vérifiée depuis `document.styleSheets`, pas seulement écrite ici —
       d'où les `!important`, même discipline que R12/R12B/R12C.

       Le libellé PORTE déjà un `for` (Telerik l'émet), donc l'élargir suffit à
       rendre la ligne cliquable ; la taille du bouton (16x16) ne bouge pas. */
    .k-radio-list-item,
    .k-radio-item {
        display: flex !important;
        align-items: center !important;
        min-height: 2.75rem !important;
    }

    .k-radio-label {
        display: inline-flex !important;
        align-items: center !important;
        min-height: 2.75rem !important;
        margin-bottom: 0 !important;
        cursor: pointer !important;
    }

    /* La colonne de 16 px qu'occupe le bouton reste inerte au-dessus et
       au-dessous du glyphe : on l'habille de la même surcouche invisible que
       R12F, mais ANCRÉE À GAUCHE (`left: 0`) au lieu d'être centrée. Un carré
       centré déborderait de 14 px vers la GAUCHE, c'est-à-dire sur la fin du
       libellé du choix précédent dans une liste horizontale — il volerait ses
       taps. Ancrée à gauche, la surcouche ne s'étend que vers la droite, sur
       son PROPRE libellé, où le tap donne de toute façon le même résultat.
       Comme pour R12F : aucune taille n'est posée sur `.k-radio` lui-même. */
    .k-radio::after {
        content: "" !important;
        position: absolute !important;
        top: 50% !important;
        left: 0 !important;
        width: 2.75rem !important;
        height: 2.75rem !important;
        transform: translateY(-50%) !important;
        display: block !important;
        background: transparent !important;
        border-radius: 0 !important;
    }

    /* ── F8 + F10 : les listes de cases Bootstrap, PAR ADHÉSION ────────────
       `lk-touch-check-list` est posée sur la liste des utilisateurs d'un rôle
       (RoleManagement.razor) et sur la liste des 9 rôles d'un utilisateur
       (UserEditForm.razor). Rien d'autre ne la porte : aucune autre page ne
       change.

       RÉPARATION de la case de RoleManagement : elle était mesurée 243x18,
       c'est-à-dire un bandeau vert pleine largeur et non une case — pas un
       choix de charte mais une fuite de `menu-editor.css` (`.modal-body input
       { width: 100% }`, règle gagnante lue dans `document.styleSheets`, plus
       spécifique que le `.form-check-input { width: 1em }` de Bootstrap). On la
       ramène à 1rem, soit 16x16, la taille des autres cases du dépôt — la garde
       du plan demande justement de prouver qu'aucune case ne dépasse 16 px. La
       case de /user-edit passe de 14 à 16 pour la même raison (le plan
       l'autorise explicitement : « ou passe à 16 par cohérence, mais pas à
       44 »). Aucune case ne grossit vers 44. */
    .lk-touch-check-list .form-check {
        display: flex !important;
        flex-wrap: wrap !important;
        align-items: center !important;
        min-height: 2.75rem !important;
        padding-left: 0 !important;
    }

    /* `padding` et `min-width` sont aussi load bearing que la largeur : la même
       règle `menu-editor.css` `.modal-body input` pose `padding: 8px 12px`, et en
       `box-sizing: border-box` un rembourrage plancherait la case à 26x18 même
       avec `width: 1rem` (mesuré). `min-width: 0` neutralise en plus le minimum
       intrinsèque d'un enfant flex. */
    .lk-touch-check-list .form-check-input {
        flex: 0 0 auto !important;
        float: none !important;
        width: 1rem !important;
        height: 1rem !important;
        min-width: 0 !important;
        padding: 0 !important;
        margin: 0 0.5rem 0 0 !important;
    }

    /* Le libellé prend TOUT le reste de la ligne — c'est lui qui rend la ligne
       cliquable (il porte déjà un `for` dans les deux .razor). `flex: 1 1 0` +
       `min-width: 0` pour que l'e-mail long ne pousse pas la ligne au-delà du
       conteneur ; `flex-wrap` pour qu'il puisse retomber sur deux lignes sans
       rien couper. */
    .lk-touch-check-list .form-check-label {
        flex: 1 1 0 !important;
        min-width: 0 !important;
        display: flex !important;
        flex-wrap: wrap !important;
        align-items: center !important;
        gap: 0 0.25rem !important;
        min-height: 2.75rem !important;
        padding: 0.25rem 0 !important;
        margin-bottom: 0 !important;
        cursor: pointer !important;
    }

    /* Mou de fin de course (règle du plan 455) : la liste des utilisateurs d'un
       rôle est le corps défilant du dialogue et ne portait que les 16 px de son
       `p-3`. Seule la liste EN DIALOGUE est concernée — `.role-list` de
       /user-edit ne défile pas. */
    .modal-body .lk-touch-check-list {
        padding-bottom: 1.5rem !important;
    }

    /* ── F13 : le pied du popup d'une ligne de /pages-management ───────────
       Aperçu (102) + Supprimer (123) + Éditer (92) = 317 px de boutons pour
       349 px de pied, marges de `.modal-footer > *` (0,25rem de chaque côté,
       soit 12 px de plus) comprises : ça débordait de 2 px et « Éditer »
       tombait sur une 2e rangée, portant le pied à 149 px.

       Les 3 boutons RESTENT, avec leur libellé et leur icône : on les met à
       largeur égale (`flex: 1 1 0`) et on resserre marges et rembourrage.
       Classe posée dans Pages.razor — `.modal-footer` seul aurait touché tous
       les dialogues du BackOffice, dont la confirmation de suppression. */
    .lk-pagepopup-footer {
        flex-wrap: nowrap !important;
        gap: 0.375rem !important;
        padding: 0.5rem !important;
    }

    .lk-pagepopup-footer > .btn {
        flex: 1 1 0 !important;
        min-width: 0 !important;
        margin: 0 !important;
        padding-left: 0.25rem !important;
        padding-right: 0.25rem !important;
        white-space: nowrap !important;
        font-size: 0.875rem !important;
    }

    .lk-pagepopup-footer > .btn > i {
        margin-right: 0.25rem !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════════
   PLAN 480 — /settings → Facturation : viser les actions de ligne au doigt,
   et replier la barre d'outils héritée de Matrix_Grid
   (constats F1 et F3 ; F2 et F4 sont côté Blazor, pas ici)

   Mesuré sur le BackOffice publié en Production à 390x844 et 360x780 le
   2026-08-13, sur les quatre grilles de l'onglet Facturation
   (Groupes TVA Clients / Produits, Paramètres TVA, Articles Facturables) :

     .linkooc-action-btn-edit / -delete           32 x 32   (les deux SEULES
                                                  portes d'entrée d'une ligne :
                                                  la ligne n'est pas cliquable)
     .matrix-view-controls                        318 x 226, QUATRE rangées
                                                  (y 613 / 665 / 717 / 769)
     titre « Liste des … » → haut du tableau      299 px

   Les tableaux restent des tableaux qui défilent : aucune colonne n'est
   masquée, réordonnée ni rétrécie, et les quatre dégradés de l'indice de
   défilement de `.table-responsive` (plan 469, plus haut dans ce fichier) ne
   sont pas touchés. Voir le STOP 1 du plan 480.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── F1 : les deux actions de ligne, à 44 px ───────────────────────────
       `linkooc-theme.css` leur pose `width: 32px; height: 32px`. La forme du
       plan 420 est `min-width` / `min-height` et JAMAIS `width` / `height` :
       un minimum l'emporte sur une largeur fixe sans figer le bouton, et il
       laisse la cellule libre de grandir. Pas de `min-height` seul non plus —
       le plan 420 a mesuré qu'un `min-height` posé seul sur un enfant de
       rangée flex gonfle le champ voisin.

       La cellule `.linkooc-actions-cell` fait 104 px pour deux boutons de 32
       et un écart de 8 : à 44 elle demande 96 px de contenu, elle ne déborde
       donc pas de sa colonne. La colonne « Actions » peut néanmoins grandir —
       c'est une CROISSANCE, autorisée par le STOP 1, qui n'interdit que les
       rétrécissements. La hauteur de ligne (88 / 67 / 57 / 88 px selon la
       grille) ne bouge pas : la cellule a déjà plus de 44 px de haut. */
    .linkooc-action-btn-edit,
    .linkooc-action-btn-delete {
        min-width: 2.75rem;
        min-height: 2.75rem;
    }

    /* ── F3 : la barre d'outils héritée, de quatre rangées à deux ──────────
       AUCUN contrôle ne disparaît (STOP 3) : « Actualiser », le compteur,
       « Él./page » et la bascule grille/liste restent tous dans le DOM, tous
       visibles, tous pointables. Ils changent de rangée, pas d'existence.
       `UseLinkoocToolbar` n'est pas basculé (STOP 4) : ça remplacerait la
       barre AUSSI sur le bureau, ce que l'audit n'a pas mesuré.

       Pourquoi les quatre rangées : `.matrix-view-controls-row` passe en
       `flex-direction: column` sous 767px (Matrix_Grid.razor.css:61), donc
       chacun des trois groupes prend une rangée pleine largeur, puis chaque
       groupe se replie à son tour faute de place — recherche + « Actualiser »
       ne tiennent pas dans 294 px (292 + 8 + 130), compteur + « Él./page » +
       bascule non plus (325 pour 294).

       Le levier est `display: contents` sur les trois groupes : leurs boîtes
       disparaissent, leurs enfants deviennent les éléments flex de la rangée
       elle-même, et le repli se fait alors sur les CONTRÔLES et non sur les
       groupes. Le champ de recherche prend une rangée entière (`flex: 1 1
       100%`), tout le reste s'empaquette derrière. C'est le seul moyen
       purement CSS de déplacer un contrôle d'un groupe à l'autre : `order` ne
       traverse pas un conteneur.

       Les `!important` sont obligatoires et non décoratifs : les règles
       concurrentes sont les règles SCOPÉES de `Matrix_Grid.razor.css`, servies
       en dernier dans `LinkoocBackOffice.styles.css` et écrites
       `.matrix-view-controls-row[b-xxxxxxxxxx]` — spécificité (0,2,0) contre
       (0,1,0). Sans `!important` ce bloc est inerte.

       Portée : toute la barre héritée du BackOffice, pas seulement
       /settings — c'est la portée demandée par le plan. Une page qui remplit
       `.matrix-view-controls-actions` (filtres avancés, export) voit ses
       boutons rejoindre le même repli au lieu d'occuper une rangée à eux
       seuls : même gain, aucun contrôle perdu. */
    .matrix-view-controls {
        /* 0.75rem de rembourrage horizontal coûtaient 8 px de largeur utile
           sur les 318 disponibles — autant de repli en moins. */
        padding: 0.5rem !important;
    }

    .matrix-view-controls-row {
        flex-direction: row !important;
        flex-wrap: wrap !important;
        align-items: center !important;
        gap: 0.375rem !important;
    }

    .matrix-view-controls-search,
    .matrix-view-controls-display,
    .matrix-view-controls-actions {
        display: contents !important;
    }

    /* Rangée 1 : le champ de recherche, pleine largeur. `flex-basis: 100%`
       force le retour à la ligne de tout ce qui suit, sans masquer personne.
       Le × d'effacement garde ses 48 x 44 (STOP 2) : rien ici ne le touche —
       c'est le champ MUET à côté de lui que F4 répare, côté Blazor. */
    .matrix-view-controls-search > .Matrix_Search {
        flex: 1 1 100% !important;
        min-width: 0 !important;
    }

    /* Rangées 2 et 3 : les sept contrôles restants, sur une ligne qui se replie
       quand la largeur manque. Aucun n'est autorisé à rétrécir sous sa taille
       intrinsèque (`flex-shrink: 0`) — un bouton qu'on écrase pour tenir sur
       une ligne est un bouton qu'on ne vise plus. La règle `order` juste
       en dessous fixe QUI tombe sur quelle rangée. */
    .matrix-view-controls-search > .Matrix_Button,
    .matrix-view-controls-display > *,
    .matrix-view-controls-actions > * {
        flex: 0 0 auto !important;
    }

    /* « Actualiser » passe en DERNIER, et c'est le point le plus important de ce
       bloc après le repli lui-même.

       `display: contents` fait de « Él./page: » et de sa liste deux éléments
       flex INDÉPENDANTS, et le premier repli mesuré les a séparés : le libellé
       finissait la rangée 2, sa liste ouvrait la rangée 3. Un libellé orphelin
       de son contrôle est pire que la rangée qu'on vient d'économiser.

       Il n'existe pas de « garder avec le suivant » en flexbox, et `flex-grow`
       ne sert à rien ici : le retour à la ligne est décidé AVANT la
       distribution de la place restante, donc gonfler le compteur ne pousse
       personne. Le seul levier est l'ordre. Mesuré (largeur utile 302 px à 390
       et 272 px à 360) :

         rangée 2   compteur 91 + « Él./page: » 59 + liste 77 + écarts = 239
         rangée 3   bascule 96 + « Actualiser » 130 + écart              = 232

       Les deux tiennent aux deux largeurs, et « Actualiser » (130) ne peut plus
       jamais s'intercaler entre le libellé et sa liste : à 239 + 130 la rangée
       2 déborde de toute façon.

       L'ordre de tabulation, lui, ne bouge pas — c'est le compromis assumé de
       `order`. Il reste acceptable ici : les huit contrôles sont dans une même
       barre de 162 px de haut, tous visibles à l'écran en même temps. */
    .matrix-view-controls-search > .Matrix_Button {
        order: 1 !important;
    }
}

   R12H — DIALOGUES DE FACTURATION : la case « Article récurrent » déformée et
   les lignes du sélecteur de partenaire sous le plancher tactile
   (plan 482, constats F6 et F8)

   Mesuré EN VIVANT contre la production à 390x844 le 2026-08-14, dialogue
   « Nouvel article facturable » de /settings/billing → Articles Facturables :

     input.k-checkbox « Article récurrent » .............. 26 x 18
     .list-group-item-action (x5, « Ajouter un partenaire ») 301 x 38 (39 la 1re)

   ── F6a : LA RÈGLE GAGNANTE, LUE ET NON DEVINÉE ────────────────────────────
   Cascade relevée depuis `document.styleSheets` sur `.modal.show .k-checkbox`,
   dans l'ordre où elle s'applique :

     .k-checkbox      (linkooc-telerik.css)  padding: 0; flex: 0 0 auto; border: 1px
     .k-checkbox-md   (linkooc-telerik.css)  width: 1rem; height: 1rem
     .modal-body input (menu-editor.css:1242) width: 100%; padding: 8px 12px;
                                              border: 1px solid          ← GAGNANTE

   `.modal-body input` vaut (0,1,1) et bat `.k-checkbox-md` (0,1,0) : la case
   hérite `width: 100%` et `padding: 8px 12px`. En `box-sizing: border-box` la
   hauteur ne peut alors PAS descendre sous rembourrage + bordures, soit
   8+8+1+1 = 18 px — c'est le 18 mesuré, et non un `height` posé. La largeur
   suit le même calcul : le `<span class="k-checkbox-wrap">` qui enveloppe
   l'input se dimensionne sur son contenu, un `width: 100%` y est résolu comme
   `auto`, donc 0 de contenu + 24 de rembourrage + 2 de bordures = 26. Le
   diagnostic présumé du plan est donc CONFIRMÉ par la mesure — même fuite que
   celle réparée par le plan 459, mais ce dialogue ne porte pas
   `.lk-touch-check-list`.

   PORTÉE — pourquoi une classe marqueur et pas `.modal-body input.k-checkbox` :
   la fuite déborde en réalité sur toute case Telerik posée dans un
   `.modal-body` du BackOffice. La réparer à nu serait tentant, mais le plan
   482 (STOP 2) impose de neutraliser la règle fautive « par une règle plus
   spécifique et NOMMÉE, portée au dialogue concerné ». `menu-editor.css` sert
   le vrai éditeur de menu et n'est pas touché. La fuite résiduelle ailleurs est
   signalée comme dette, pas corrigée ici en aveugle.

   CE QUI N'EST PAS FAIT, ET POURQUOI :
   - la rangée n'est PAS retouchée : `.Matrix_FormField:has(input.k-checkbox)`
     (bloc R12G, plan 474) lui donne déjà `min-height: 2.75rem` — mesurée
     301 x 44 en vivant — et le libellé porte un `for` vers l'id de la case
     (mesuré 267 x 44). F6c est donc satisfait par l'existant.
   - la case n'est PAS agrandie vers 44 (STOP 1 du plan 482, règle du plan 474) :
     elle revient à 16 x 16 et c'est la surcouche invisible `.k-checkbox::after`
     du bloc R12F qui porte les 44 x 44 de cible tactile.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

    /* ── F6b : rendre la case carrée ───────────────────────────────────────
       Les quatre déclarations vont ENSEMBLE. Le plan 459 avait déjà mesuré que
       `padding` et `min-width` sont aussi déterminants que la largeur en
       `box-sizing: border-box` : sans `padding: 0`, un `width: 1rem` laisserait
       la case à 26 x 18 (les 24 px de rembourrage plancheraient la boîte).
       `flex` et `float` sont remis à leur valeur Telerik d'origine pour que la
       case ne parte pas en flottant si une autre feuille l'y pousse.
       Aucun `font-size` : le glyphe de la coche est peint par le thème Kendo
       dans `.k-checkbox:checked::before` (masque SVG) — on le laisse tranquille,
       même discipline que R12F. */
    .lk-billing-item-dialog .modal-body input.k-checkbox {
        width: 1rem !important;
        height: 1rem !important;
        min-width: 0 !important;
        padding: 0 !important;
        flex: 0 0 auto !important;
        float: none !important;
    }

    /* ── F8 : plancher tactile sur les lignes du sélecteur de partenaire ────
       C'est le SEUL moyen de choisir un partenaire (pas de liste déroulante de
       repli), et les lignes faisaient 38 px. `min-height` seul laisserait le
       texte collé en haut de la ligne : le bouton passe en flex centré, ce qui
       ne change ni son libellé, ni sa coche `bi-check-circle`, ni son marquage
       `active`. L'enfant `div.d-flex.w-100` garde sa largeur pleine.

       La classe marqueur est indispensable : `.list-group-item-action` est une
       classe Bootstrap partagée (la liste des entités de /settings/billing la
       porte aussi) — c'est exactement le piège que le plan 474 signale pour
       `.form-check`. */
    .lk-billing-partner-dialog .list-group .list-group-item-action {
        display: flex !important;
        align-items: center !important;
        min-height: 2.75rem !important;
    }

    .lk-billing-partner-dialog .list-group .list-group-item-action > .d-flex {
        flex: 1 1 auto !important;
        min-width: 0 !important;
    }

    /* Mou de fin de course (règle du plan 455). À 5 partenaires la liste ne
       défile pas (5 x 44 = 220 px sous le `max-height: 300px`), mais au 6e ou
       au 7e elle défilera et la dernière ligne serait collée au bord du
       conteneur. Les 24 px posés ici s'ajoutent au rembourrage bas du
       `.modal-body` (16 px) : 40 px de marge sous la dernière ligne, défilement
       ou pas. */
    .lk-billing-partner-dialog .list-group {
        padding-bottom: max(24px, env(safe-area-inset-bottom)) !important;
    }
}
