/* =============================================================================
   ROKAPI — COUCHE MOBILE (≤ 768 px)
   =============================================================================
   Chargée EN DERNIER dans le <head> de chaque page (partials/mobile-assets.php),
   après toutes les feuilles de module. Documentation : [[Responsive mobile]].

   RÈGLE D'OR : rien dans ce fichier hors d'un `@media (max-width: …)` — ou de
   `@media (hover: none)`, qu'aucun poste de bureau à souris ne satisfait. Sur
   un écran de bureau, cette feuille ne fait RIEN : le rendu desktop n'a pas
   bougé d'un pixel, et c'est vérifié par comparaison de captures.

   Principes (voir la note pour les sources) :
   - une colonne, jamais de défilement horizontal de la PAGE — seuls les
     tableaux et les blocs de code défilent latéralement, dans leur cadre ;
   - la navigation est un TIROIR (la sidebar de la page, sortie du flux) ;
   - les popins deviennent des feuilles plein écran ou ancrées en bas ;
   - cibles tactiles ≥ 40 px, champs à 16 px (sinon iOS zoome au focus) ;
   - `100dvh` plutôt que `100vh` (la barre d'adresse mobile mange le bas) ;
   - ce qui est secondaire se masque, ce qui est une fonction principale
     (consulter un rapport, parler au chatbot, lancer un crawl) reste.

   Paliers : 768 px (téléphones et petites tablettes en portrait), 480 px
   (téléphones), 374 px (très petits écrans type iPhone SE 1re génération).
   ============================================================================= */


/* =============================================================================
   1. BARRE DU HAUT
   ============================================================================= */
@media (max-width: 768px) {
    html body .header {
        padding: 0 10px;
        gap: 6px;
    }
    html body .header-left { gap: 6px; min-width: 0; flex: 0 1 auto; }
    html body .header-actions { gap: 6px; flex: none; }

    /* Le bouton ☰ n'apparaît que si la page a une sidebar à ouvrir. */
    body:has(#projectSidebar, #reportSidebar) .header-menu-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        height: 40px;
        margin-left: -4px;
        border: 0;
        border-radius: 10px;
        background: transparent;
        color: var(--text-primary);
        cursor: pointer;
        flex: none;
        -webkit-tap-highlight-color: transparent;
    }
    .header-menu-btn .material-symbols-outlined { font-size: 26px; }
    .header-menu-btn:active,
    .header-menu-btn[aria-expanded="true"] { background: var(--sidebar-hover, rgba(0,0,0,0.05)); }

    /* Boutons de la barre : 36 px (cible tactile correcte sans faire exploser
       la ligne — cinq contrôles doivent tenir sur 360 px). */
    html body .notif-bell-btn,
    html body .header-icon-btn {
        width: 36px;
        height: 36px;
    }
    /* « Partager » : l'icône seule, le libellé ne tient pas. */
    html body .header-icon-btn--label {
        width: 36px;
        padding: 0;
        font-size: 0;
        gap: 0;
    }
    html body .header-icon-btn--label .material-symbols-outlined { font-size: 19px; }

    /* Sélecteur d'espace : l'icône seule, le nom est dans le menu. */
    html body .ws-switcher-btn {
        width: 36px;
        height: 36px;
        padding: 0;
        justify-content: center;
        gap: 0;
    }
    html body .ws-switcher-btn .ws-switcher-name,
    html body .ws-switcher-btn .ws-switcher-caret { display: none; }

    /* Retour au projet (rapport) : déjà dans le tiroir (« Retour aux crawls »). */
    html body .header-back-link { display: none; }

    /* Pastille « tickets en attente » (super admin) : centrée en absolu, elle
       chevaucherait les boutons. Le support reste au pied du tiroir. */
    html body .support-ticket-pill { display: none !important; }

    /* Menus de la barre (notifications, téléchargements, espace, compte,
       partage) : une feuille pleine largeur sous la barre, et non une bulle
       de 340-380 px accrochée au bord droit qui sortirait de l'écran. */
    html body .notif-dropdown,
    html body .ws-switcher-menu:not(.header-project-menu),
    html body .user-dropdown-menu,
    html body .share-popover {
        position: fixed;
        top: 66px;
        left: 8px;
        right: 8px;
        width: auto;
        min-width: 0;
        max-width: none;
        max-height: calc(100dvh - 80px);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    html body .notif-dropdown .notif-list { max-height: calc(100dvh - 140px); }
    html body .user-dropdown-item { min-height: 44px; }
}

@media (max-width: 374px) {
    /* Très petits écrans : la marque cède la place aux commandes. */
    body:has(#projectSidebar, #reportSidebar) .header-brand { display: none; }
}


/* =============================================================================
   2. TIROIR DE NAVIGATION (la sidebar de la page)
   =============================================================================
   `#projectSidebar` (projet, accueil, pages hub/admin) et `#reportSidebar`
   (rapport de crawl) sortent du flux : fixés à gauche, sous la barre du haut,
   translatés hors écran. mobile-nav.js pose `.is-mobile-open` et
   `html.mnav-open`. On vise les IDs — `.project-sidebar` sert aussi de rail
   dans la popin d'URL et dans la fiche de config, qui ne sont pas des tiroirs.
   ============================================================================= */
@media (max-width: 768px) {
    #projectSidebar,
    #reportSidebar {
        position: fixed !important;
        top: 60px !important;
        left: 0;
        bottom: 0;
        z-index: 1060;
        width: min(86vw, 320px) !important;
        height: auto !important;
        max-height: none;
        /* `shell.css` pose `align-self: flex-start` (pour le sticky desktop).
           Chrome applique désormais l'alignement aux boîtes positionnées : le
           tiroir prenait la hauteur de son CONTENU au lieu de s'arrêter au bas
           de l'écran — liste jamais défilante, page figée derrière, tout le
           bas du menu inaccessible. `stretch` = de `top` à `bottom`. */
        align-self: stretch;
        display: flex !important;
        transform: translateX(-102%);
        visibility: hidden;
        transition: transform 0.24s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 0.24s;
        box-shadow: none;
        border-right: 1px solid var(--border-color);
        padding-bottom: max(12px, env(safe-area-inset-bottom));
        overscroll-behavior: contain;
    }
    #projectSidebar.is-mobile-open,
    #reportSidebar.is-mobile-open {
        transform: none;
        visibility: visible;
        transition: transform 0.24s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s;
        box-shadow: 12px 0 32px rgba(16, 26, 34, 0.22);
    }
    /* Le bouton de repli desktop n'a rien à faire dans un tiroir. */
    #projectSidebar .project-sidebar-collapse { display: none !important; }

    /* Entrées du tiroir : cibles tactiles de 44 px. */
    #projectSidebar .project-sidebar-item,
    #reportSidebar .rs-item { min-height: 44px; }
    #reportSidebar .rs-supergroup-header { min-height: 44px; }
    #projectSidebar .project-sidebar-nav { margin-top: 4px; }

    .mnav-backdrop {
        position: fixed;
        inset: 60px 0 0 0;
        z-index: 1055;
        background: rgba(16, 26, 34, 0.42);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.2s ease, visibility 0s linear 0.2s;
        -webkit-tap-highlight-color: transparent;
    }
    html.mnav-open .mnav-backdrop {
        opacity: 1;
        visibility: visible;
        transition: opacity 0.2s ease, visibility 0s;
    }
    /* Page figée derrière le tiroir. */
    html.mnav-open,
    html.mnav-open body { overflow: hidden !important; }
    /* La barre passe au-dessus du voile, pour que ☰/✕ reste atteignable. */
    html.mnav-open .header { z-index: 1070; }
}

@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
    #projectSidebar, #reportSidebar, .mnav-backdrop { transition: none !important; }
}


/* =============================================================================
   3. COQUILLES — le contenu prend toute la largeur
   ============================================================================= */
@media (max-width: 768px) {
    html, body { max-width: 100%; }
    /* Filet de sécurité : `clip` et non `hidden` (responsive.css), qui
       cassait `position: sticky` — les en-têtes de tableau et la barre du
       haut ne collaient plus. */
    html, body { overflow-x: clip !important; }
    html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

    .project-shell-body { display: block; min-height: calc(100dvh - 60px); }
    .pj-shell-main {
        padding: 16px 14px calc(88px + env(safe-area-inset-bottom));
        width: 100%;
        min-width: 0;
    }

    html body .dashboard-layout { display: block !important; min-height: calc(100dvh - 60px) !important; }
    html body .main-content {
        padding: 16px 14px calc(88px + env(safe-area-inset-bottom)) !important;
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 !important;
        min-width: 0;
    }

    /* Aucun enfant direct ne doit élargir la page. */
    .pj-shell-main > *,
    .main-content > * { max-width: 100%; min-width: 0; }

    /* Longues URL et identifiants : ils se coupent plutôt que d'élargir.
       `break-word` et non `anywhere` : ce dernier abaisse la largeur
       minimale de CHAQUE mot, et les libellés courts se retrouvaient coupés
       en plein milieu (« DÉCOUVERTE / S ») dès qu'une grille se resserrait. */
    .pj-shell-main,
    .main-content { overflow-wrap: break-word; }

    /* Champs : 16 px minimum, sinon iOS zoome la page au focus. */
    input[type="text"], input[type="search"], input[type="email"], input[type="url"],
    input[type="password"], input[type="number"], input[type="tel"], input:not([type]),
    textarea, select { font-size: 16px !important; }
}


/* =============================================================================
   4. PANNEAUX LATÉRAUX FLOTTANTS
   ============================================================================= */
@media (max-width: 768px) {
    /* Panneau de crawl : plein écran. Fermé, son ombre (-10px 0 50px) débordait
       sur le bord droit de chaque page, en voile gris permanent. */
    html body .crawl-panel {
        width: 100%;
        max-width: 100%;
        height: 100dvh;
        border-left: 0;
    }
    /* Console du crawl : `white-space: pre` est voulu (alignements), les
       lignes longues défilent donc au doigt au lieu d'être rognées. */
    html body .crawl-panel-terminal { overflow-x: auto; }
    html body .crawl-panel:not(.is-open) {
        box-shadow: none;
        visibility: hidden;
        transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 0.3s;
    }
}


/* =============================================================================
   5. CARTES KPI (Component::card) — deux par ligne, compactes
   =============================================================================
   Une carte KPI de bureau (1,5 rem de marge, icône de 48 px, chiffre à 2 rem)
   occupait tout l'écran d'un téléphone : cinq écrans de défilement pour cinq
   nombres. Deux par ligne, l'icône réduite, le libellé sur deux lignes.
   Le composant émet son propre <style> dans le <body> (classe unique
   `card-<id>`), d'où le préfixe `html body [class^="card-"]`, restreint à la
   racine par `:has(> .card-header)` — sans quoi il attrapait aussi
   `.card-title`, `.card-header`… dont la classe commence pareil.
   ============================================================================= */
@media (max-width: 768px) {
    html body .scorecards,
    html body .scorecards-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 10px !important;
    }
    html body [class^="card-"]:has(> .card-header) {
        padding: 12px 12px 12px 14px;
        border-radius: 10px;
        min-width: 0;
    }
    html body [class^="card-"]:has(> .card-header):hover { transform: none; }
    html body [class^="card-"]:has(> .card-header) .card-header { margin-bottom: 6px; gap: 6px; align-items: flex-start; }
    html body [class^="card-"]:has(> .card-header) .card-title {
        font-size: 0.68rem;
        letter-spacing: 0.3px;
        line-height: 1.25;
    }
    html body [class^="card-"]:has(> .card-header) .card-icon { width: 28px; height: 28px; border-radius: 8px; flex: none; }
    html body [class^="card-"]:has(> .card-header) .card-icon .material-symbols-outlined { font-size: 16px; }
    html body [class^="card-"]:has(> .card-header) .card-value { font-size: 1.35rem; margin-bottom: 2px; line-height: 1.2; }
    html body [class^="card-"]:has(> .card-header) .card-desc { font-size: 0.72rem; line-height: 1.3; }
}
@media (max-width: 340px) {
    html body .scorecards,
    html body .scorecards-grid { grid-template-columns: minmax(0, 1fr) !important; }
}


/* =============================================================================
   6. ACCUEIL (index.php) — la liste des projets
   =============================================================================
   Sur desktop, l'accueil est une coquille à hauteur fixe dont seule la liste
   défile. Sur téléphone, un défilement interne empêche la barre d'adresse de se
   replier et coupe la liste à mi-écran : la PAGE défile, comme partout.
   La sidebar de catégories n'est plus masquée : c'est le tiroir (§2).
   ============================================================================= */
@media (max-width: 768px) {
    html body:has(.container-with-sidebar) { overflow: auto; }
    html body .container-with-sidebar {
        display: block !important;
        height: auto !important;
        min-height: calc(100dvh - 60px);
        overflow: visible !important;
        padding: 0 !important;
    }
    html body .main-content-area {
        height: auto;
        overflow: visible;
        padding: 16px 14px calc(88px + env(safe-area-inset-bottom));
    }
    html body #projectListContainer > .projects-pane,
    html body #projectListContainer > .projects-section,
    html body #projectListContainer > .empty-state {
        overflow: visible;
        padding-right: 0;
        max-height: none;
    }
    html body #projectsPane-my,
    html body #projectsPane-all,
    html body #projectsPane-shared { max-height: none; }

    /* En-tête : titre et bouton sur une ligne tant que ça tient. */
    html body .hp-page-head {
        flex-direction: row !important;
        align-items: center !important;
        gap: 10px !important;
        margin-bottom: 14px !important;
    }
    html body .hp-page-head .page-title { font-size: 1.35rem; margin: 0; }
    html body .hp-page-head .btn-primary-action {
        padding: 0.6rem 0.9rem;
        font-size: 0.88rem;
        white-space: nowrap;
    }
    html body .search-container { margin-bottom: 12px !important; }
    html body .search-container .search-input { padding-top: 0.65rem !important; padding-bottom: 0.65rem !important; }

    /* Onglets : une seule ligne qui défile, jamais un libellé sur deux lignes. */
    html body .projects-tabs {
        flex-wrap: nowrap !important;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        margin-bottom: 10px !important;
    }
    html body .projects-tabs::-webkit-scrollbar { display: none; }
    html body .projects-tab {
        white-space: nowrap;
        flex: none;
        margin-right: 14px;
        font-size: 0.88rem !important;
        padding: 0.6rem 0.1rem !important;
    }

    /* Carte projet : identité | score | ⋯ — les autres KPI sont dans le
       projet lui-même, à un tap. */
    html body .pc-row { border-radius: 10px; }
    html body .pc-main {
        grid-template-columns: minmax(0, 1fr) auto 36px;
        gap: 10px;
        padding: 12px 10px 12px 14px;
    }
    html body .pc-main > .pc-kpi { display: none; }
    html body .pc-main > .pc-kpi.pc-kpi-health { display: flex; }
    html body .pc-kpi-health .pc-health-status { display: none; }
    html body .pc-actions { justify-content: flex-end; }
    /* Le menu ⋯ n'apparaît qu'au survol sur desktop — invisible au doigt. */
    html body .pc-kebab-wrap,
    html body .kebab-menu-wrapper { display: block !important; opacity: 1; }
    html body .pc-cat-tag,
    html body .category-badge-simple { display: inline-flex !important; }
    html body .pc-name-line { flex-wrap: wrap; row-gap: 4px; }
    html body .pc-crawl-link { max-width: 100%; }

    /* Cartes « partagés avec moi » : une colonne. */
    html body .pc-shared-grid { grid-template-columns: minmax(0, 1fr); }
}


/* =============================================================================
   7. VUES PROJET — en-têtes, ateliers
   ============================================================================= */
@media (max-width: 768px) {
    /* En-tête de vue (Data Explorer, Segments, API, Datasets, IA…) : titre et
       sous-titre sur toute la largeur, actions en dessous. Côte à côte, le
       titre se cassait mot à mot dans une colonne de 150 px. */
    html body .pj-shell-main .de-header,
    html body .main-content .de-header {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        margin: 0 0 14px;
    }
    html body .de-header-title h1 { font-size: 1.4rem !important; }
    html body .de-header-actions {
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: 8px;
    }

    /* Ateliers « pleine hauteur » (SQL, Segments, Datasets, Génération IA) :
       sur desktop, chaque panneau défile dans un écran borné. Sur téléphone,
       des panneaux défilants empilés se disputent le geste : c'est la PAGE
       qui défile, chaque bloc à sa hauteur naturelle. */
    html body .project-shell-body:has(.sql-workspace-container),
    html body .project-shell-body:has(.categorize-layout),
    html body .project-shell-body:has(.datasets-view),
    html body .project-shell-body:has(.ai-generations-view),
    html body .dashboard-layout:has(.categorize-layout) {
        height: auto;
        min-height: calc(100dvh - 60px);
    }
    html body .pj-shell-main:has(.sql-workspace-container),
    html body .pj-shell-main:has(.categorize-layout),
    html body .pj-shell-main:has(.datasets-view),
    html body .pj-shell-main:has(.ai-generations-view),
    html body .main-content:has(.sql-workspace-container),
    html body .main-content:has(.categorize-layout) {
        display: block;
        height: auto !important;
        overflow: visible;
        padding-bottom: calc(88px + env(safe-area-inset-bottom)) !important;
    }
    html body .sql-workspace-container { overflow: visible; }
}


/* =============================================================================
   8. DATA EXPLORER (SQL) — éditeur, résultats, puis tables
   ============================================================================= */
@media (max-width: 768px) {
    html body .sql-explorer-layout,
    html body .sql-explorer-layout.sidebar-collapsed {
        display: flex;
        flex-direction: column;
        gap: 12px;
    }
    /* L'éditeur d'abord : c'est l'outil. Le panneau de tables vient après,
       et son bouton de repli (dans la barre de l'éditeur) le masque. */
    html body .sql-main { order: 1; height: auto; min-height: 0; }
    html body .sql-sidebar {
        order: 2;
        max-height: 60vh;
        transform: none !important;
    }
    html body .sql-explorer-layout.sidebar-collapsed .sql-sidebar { display: none; }
    html body .sql-editor-surface,
    html body .sql-editor-surface .CodeMirror { min-height: 160px; }
    html body .sql-results-container { min-height: 320px; }
    /* Barre de l'éditeur : les onglets défilent, les actions passent dessous. */
    html body .sql-tabs-row { flex-wrap: wrap; row-gap: 6px; }
    html body .sql-tabs-actions { flex-wrap: wrap; }
    html body .ai-sql-toolbar-btn .shortcut { display: none; }
}


/* =============================================================================
   9. VUE CRAWL (Crawl du site / Crawl de liste)
   ============================================================================= */
@media (max-width: 768px) {
    /* Historique : le tableau garde des colonnes lisibles et défile dans son
       cadre, date figée à gauche — au lieu de huit colonnes écrasées à 40 px
       (« STAT », « SCOI »…) et de durées cassées chiffre par chiffre. */
    html body .pjx-history { padding: 14px 12px; }
    html body .pjx-table-wrap {
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }
    html body .pjx-table {
        table-layout: auto;
        width: max-content;
        min-width: 100%;
    }
    html body .pjx-table th,
    html body .pjx-table td {
        width: auto !important;
        white-space: nowrap;
        overflow: visible;
    }
    html body .pjx-num { white-space: nowrap; overflow-wrap: normal; }
    html body .pjx-table th:first-child,
    html body .pjx-table td:first-child {
        position: sticky;
        left: 0;
        z-index: 1;
        background: var(--card-bg);
        box-shadow: 1px 0 0 var(--border-color-subtle, var(--border-color));
    }

    /* Ordre de lecture sur téléphone : lancer un crawl, la santé du dernier
       crawl (et son rapport), l'historique — puis les blocs de réglage et
       d'information. Les deux colonnes s'effacent (`display: contents`) pour
       que leurs cartes s'ordonnent entre elles. */
    html body .pj-bento { display: flex !important; flex-direction: column !important; align-items: stretch !important; gap: 14px; }
    html body .pj-bento > .pj-col-left,
    html body .pj-bento > .pj-col-center,
    html body .pj-bento > .pj-col-right { display: contents; }
    html body .pj-bento .pj-col-left > *,
    html body .pj-bento .pj-col-center > *,
    html body .pj-bento .pj-col-right > * { order: 10; margin-top: 0; margin-bottom: 0; }
    html body .pj-bento .pj-col-left > *,
    html body .pj-bento .pj-col-center > * { width: auto; max-width: 100%; min-width: 0; }
    html body .pj-bento .pj-actions-float { order: 1; display: flex; flex-direction: column; gap: 8px; }
    html body .pj-bento .pj-actions-float > * { width: 100%; justify-content: center; }
    html body .pj-bento .pjx-state { order: 2; }
    html body .pj-bento .pjx-history { order: 3; }

    /* KPI du dernier crawl : 2 × 2. À trois de front, « vs précédent »
       se cassait sous chaque chiffre. */
    html body .pjx-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 16px 12px; }

    /* Chiffres du dernier crawl : 2 × 2 plutôt que 4 serrés et rognés. */
    html body .pjx-ministats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
    html body .pjx-state-part { padding: 16px 14px; }
    html body .pjx-ov-head { flex-wrap: wrap; row-gap: 6px; margin-bottom: 1rem; }
}


/* =============================================================================
   10. BACKLOG SEO — colonnes à glisser, une par écran
   ============================================================================= */
@media (max-width: 768px) {
    html body .pj-shell-main:has(.bl-view) { padding-bottom: 16px; }
    html body .bl-view { height: calc(100dvh - 60px - 32px); }
    html body .bl-head { flex-wrap: wrap; row-gap: 10px; padding-bottom: 12px; }
    html body .bl-head-main { flex: 1 1 100%; }
    html body .bl-head-actions { flex: 1 1 100%; flex-wrap: wrap; gap: 6px; }
    html body .bl-head-actions .bl-btn { min-height: 38px; }
    html body .bl-filters { flex-wrap: wrap; row-gap: 6px; }
    /* Une colonne ≈ l'écran, la suivante dépasse pour inviter au glissé ;
       l'aimantation cale chaque colonne au bord. */
    html body .bl-board {
        scroll-snap-type: x mandatory;
        scroll-padding-inline: 0;
        overscroll-behavior-x: contain;
        gap: 10px;
    }
    html body .bl-col {
        flex: 0 0 min(84vw, 320px);
        scroll-snap-align: start;
    }
    /* Les actions de colonne n'apparaissent qu'au survol sur desktop. */
    html body .bl-col-head .bl-icon-btn { opacity: 1; }

    /* Popin d'un ticket : feuille plein écran, UN SEUL défilement (détail
       puis discussion). Empilées en colonne, la discussion (`flex: 0 0 auto`)
       ne rétrécissait pas : dès quelques messages, le détail était écrasé à
       zéro et le formulaire d'envoi passait sous le bord de la popin, coupé
       par son `overflow: hidden` — ni contenu ni bouton « Envoyer ». */
    html body .bl-modal-panel {
        width: 100vw;
        height: 100dvh;
        max-height: 100dvh;
        border: none;
        border-radius: 0;
    }
    html body .bl-modal-body {
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    html body .bl-detail { flex: none; overflow: visible; padding: 16px 16px 20px; }
    /* La croix flotte au-dessus : la première ligne lui laisse la place. */
    html body .bl-detail-head { padding-right: 44px; }
    html body .bl-side { flex: none; padding: 16px 16px 0; }
    html body .bl-comments { overflow: visible; }
    /* Le champ de saisie reste à portée de pouce, quelle que soit la longueur
       du fil. */
    html body .bl-comment-form {
        position: sticky;
        bottom: 0;
        z-index: 1;
        margin-inline: -16px;
        padding: 12px 16px max(12px, env(safe-area-inset-bottom));
        background: var(--surface-secondary);
    }
    html body .bl-write-comment { max-height: 35dvh; overflow-y: auto; }
}


/* =============================================================================
   11. API / MCP, PARTAGES
   ============================================================================= */
@media (max-width: 768px) {
    /* Cartes : la marge latérale de 24 px et le padding de 2 rem s'ajoutaient
       à ceux de la coquille — le contenu tenait dans 250 px. */
    html body .pj-shell-main .settings-card {
        margin: 0 0 14px;
        padding: 16px 14px;
    }
    html body .settings-card h2 { font-size: 1.1rem; }
    html body .api-explorer { margin: 0 -14px; border-radius: 0; }
    html body .api-keybar { padding: 0.6rem 0.75rem; }
    /* Champs à copier : l'input prend la ligne, le bouton passe dessous si
       besoin plutôt que de pousser l'input à 150 px. */
    html body .settings-card [style*="display:flex"],
    html body .settings-card [style*="display: flex"] { flex-wrap: wrap; }

    /* Partages : le tableau défile dans sa carte. */
    html body .pjs-table-wrap { overflow-x: auto; overscroll-behavior-x: contain; }
    html body .pjs-table-wrap table { min-width: 520px; }
}


/* =============================================================================
   12. SEGMENTS (catégorisation)
   ============================================================================= */
@media (max-width: 768px) {
    html body .categorize-layout,
    html body .main-content .categorize-layout {
        display: flex !important;
        flex-direction: column;
        gap: 12px !important;
        height: auto !important;
        min-height: 0 !important;
        overflow: visible !important;
    }
    /* segments.css les borne à 400 px sous 1200 px : sur téléphone, cinq lignes
       de tableau et plus de pagination. Hauteur naturelle. */
    html body .categorize-panel { min-width: 0; height: auto !important; max-height: none !important; overflow: visible; }
    html body .categorize-panel.categorize-panel-table { overflow: hidden; }
    html body .table-container-wrapper { overflow: visible; flex: none; }
    /* Barre de répartition : le choix Internes/Externes sur sa ligne, les
       pastilles de catégories dessous, en rangées. */
    html body .stats-bar { flex-wrap: wrap; padding: 10px 12px; row-gap: 8px; }
    html body .stats-bar .category-pills { flex: 1 1 100%; order: 2; }
    html body .stats-bar .pills-separator { display: none; }
    html body .categorize-panel h3 { flex-wrap: wrap; }
    /* Le tableau remplissait « le reste de l'écran » de l'atelier : une fois
       la hauteur libérée, ce reste tombait à quatre lignes. Il reprend sa
       hauteur naturelle (la page défile). */
    html body .categorize-panel-table .table-scroll-area,
    html body .table-container-wrapper > div:first-child { flex: none; max-height: none; overflow: visible; }
    html body .categorize-panel-table [id^="tableContainer_"] { overflow-x: auto; }
}


/* =============================================================================
   13. TABLEAUX DE DONNÉES (url-table, link-table, simple-table, data-table)
   =============================================================================
   Modèle retenu (NN/g, « Mobile tables ») : le tableau garde ses colonnes et
   DÉFILE dans sa carte, la première colonne (l'URL, presque toujours) reste
   figée à gauche pour qu'on sache toujours de quelle ligne on lit les
   chiffres. Pas de cartes empilées : on compare des lignes, et « Colonnes »
   reste le moyen d'alléger.
   ============================================================================= */
@media (max-width: 768px) {
    html body .table-card {
        padding: 12px !important;
        border-radius: 10px;
    }
    /* En-tête : le titre prend la ligne, les actions passent dessous. */
    html body .table-card .table-header > div { flex-wrap: wrap; gap: 8px; }
    html body .table-title-row { flex: 1 1 100%; min-width: 0; }
    html body .table-title { font-size: 0.95rem !important; line-height: 1.3; }
    html body .table-actions { flex-wrap: wrap; gap: 6px; }
    /* responsive.css masquait TOUTES les actions de tableau : sans « Colonnes »
       et sans l'URL Explorer, un tableau large était une impasse sur mobile.
       On les rend, compactes ; « Copier » (presse-papiers de tout le
       tableau) reste masqué — un geste de bureau. */
    html body .table-card .btn-table-action.btn-explorer,
    html body .table-card .btn-table-action.btn-export,
    html body .table-card .btn-table-action.btn-columns-select,
    html body .table-card .btn-table-action.btn-icon-only { display: inline-flex !important; }
    html body .btn-table-action {
        padding: 0.4rem 0.65rem;
        font-size: 0.8rem;
        min-height: 36px;
    }
    html body .table-pager-btn { min-width: 36px; min-height: 36px; }

    /* La barre de défilement DU HAUT (synchronisée avec le tableau) n'a pas de
       sens au doigt : on fait glisser le tableau lui-même. */
    html body [id^="topScrollbar_"] { display: none !important; }

    html body [id^="tableContainer_"],
    html body .table-scroll-area,
    html body .simple-table-wrapper,
    html body .table-wrapper {
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }
    html body .data-table { font-size: 0.82rem; }
    html body .data-table thead th,
    html body .data-table tbody td {
        padding: 0.55rem 0.6rem;
        white-space: nowrap;
    }
    /* Colonne figée. Fond opaque obligatoire : les cellules défilent dessous. */
    html body .data-table thead th:first-child,
    html body .data-table tbody td:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        box-shadow: 1px 0 0 var(--border-color);
    }
    html body .data-table tbody td:first-child { background: var(--card-bg); }
    html body .data-table thead th:first-child { background: var(--surface-secondary); z-index: 3; }
    html body .data-table .col-url,
    html body .data-table td:first-child { max-width: 62vw !important; }
    html body .data-table td:first-child > * { max-width: 100%; }

    /* Menu Colonnes : une feuille sous la barre du haut, pleine largeur —
       et non un menu de 360 px calé sur le bouton. Le script le positionne
       en ligne (left/top) : d'où les !important. */
    html body [id^="columnDropdown_"] {
        position: fixed !important;
        top: 68px !important;
        left: 8px !important;
        right: 8px !important;
        bottom: auto !important;
        min-width: 0 !important;
        width: auto !important;
        max-height: calc(100dvh - 84px) !important;
        z-index: 2000 !important;
    }
    html body [id^="columnDropdown_"] label { padding: 0.65rem 0.5rem !important; }
}


/* =============================================================================
   14. CHATBOT (Sherpa IA plein écran)
   =============================================================================
   Une vraie app de messagerie : bord à bord, toute la hauteur sous la barre,
   la saisie collée en bas (et au-dessus de la barre d'accueil iOS). Le panneau
   des conversations est déjà un tiroir sous 720 px (chat-panel.css).
   ============================================================================= */
@media (max-width: 768px) {
    html body .pj-shell-main:has(#drBriefRoot) { padding: 0 !important; }
    html body .dr-brief-fullscreen:not(.is-focus) {
        height: calc(100dvh - 60px);
        min-height: 0;
        border: 0;
        border-radius: 0;
    }
    html body .dr-brief-fs-main .dr-brief-composer {
        padding: 10px 12px max(10px, env(safe-area-inset-bottom));
    }
    html body .dr-brief-fullscreen.is-empty .dr-brief-fs-main { padding: 0 14px; }
    html body .dr-brief-hero-title { font-size: 1.35rem; }
    html body .dr-brief-fullscreen .dr-brief-messages { padding-left: 12px; padding-right: 12px; }
    /* Tableaux et blocs de code des réponses : ils défilent dans la bulle. */
    html body .dr-brief-md table { display: block; max-width: 100%; overflow-x: auto; }
    html body .dr-brief-md pre { max-width: 100%; overflow-x: auto; }
    html body #drBriefInput::placeholder { text-overflow: ellipsis; }
}
/* Le tiroir des conversations (`#chatPanel`) a ses règles mobiles dans
   `chat-panel.css`, à qui appartient le préfixe `cvp-` (ChatPanelCssPrefixTest). */
@media (max-width: 768px) {
    /* Raccourcis clavier affichés (Ctrl+K, ⌘+Entrée…) : sans clavier physique,
       ils n'annoncent rien d'utilisable. */
    html body kbd.kbd-hint,
    html body .shortcut-hint { display: none; }
}


/* =============================================================================
   15. SEARCH CONSOLE (vue gsc + search-analytics.php)
   ============================================================================= */
@media (max-width: 768px) {
    html body .gsc-header { flex-direction: column; align-items: stretch; gap: 10px; }
    html body .gsc-header-actions { justify-content: flex-start; flex-wrap: wrap; }
    html body .gsc-prop { flex-wrap: wrap; row-gap: 4px; }
    html body .gsc-prop,
    html body .gsc-sub { overflow-wrap: anywhere; }
    /* Barre des dimensions : une ligne qui défile, jamais « Mots- / clés ». */
    html body .gsc-controls { flex-wrap: wrap; gap: 10px; }
    html body .gsc-controls-left { flex: 1 1 100%; min-width: 0; flex-wrap: nowrap; }
    html body #gscModes {
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        min-width: 0;
        max-width: 100%;
    }
    html body #gscModes::-webkit-scrollbar { display: none; }
    html body #gscModes > button { white-space: nowrap; flex: none; }
    html body .gsc-brand-banner { flex-wrap: wrap; gap: 8px; }
    html body .gsc-brand-banner-text { flex: 1 1 calc(100% - 40px); }
    html body .gsc-evo-chart .gsc-chart { height: 280px; }
    html body .gsc-card { padding: 14px 12px; }
    /* Sélecteur de période : une feuille, plus un menu calé sous le bouton. */
    html body .gsc-datepicker {
        position: fixed !important;
        top: 68px !important;
        left: 8px !important;
        right: 8px !important;
        width: auto !important;
        max-height: calc(100dvh - 84px);
        overflow-y: auto;
        flex-direction: column;
    }
    html body .gsc-dp-presets { flex-direction: row; flex-wrap: wrap; border-right: 0; }
    html body .gsc-evpop { left: 8px !important; right: 8px !important; width: auto !important; }
    /* Tableau : défile dans sa carte. */
    html body .gsc-table-wrap,
    html body #gscTableWrap { overflow-x: auto; overscroll-behavior-x: contain; }
}
@media (max-width: 768px) { html body .gsc-dp-cal { width: auto; flex: 1 1 auto; } }


/* =============================================================================
   16. BULLE SHERPA IA (rapports, vues projet) et grilles de cartes en ligne
   ============================================================================= */
@media (max-width: 600px) {
    /* dr-brief.css remontait la bulle de 76 px pour une « barre de navigation
       du bas » qui n'existe plus : elle flottait au milieu du contenu. */
    html body .dr-brief-bubble { bottom: calc(16px + env(safe-area-inset-bottom)); }
    html body .dr-brief-greeting { bottom: calc(26px + env(safe-area-inset-bottom)); }
    html body .dashboard-layout { padding-bottom: 0; }
    html body .dr-brief-panel {
        height: 100dvh;
        padding-bottom: env(safe-area-inset-bottom);
    }
}
@media (max-width: 768px) {
    /* Grilles de cartes KPI déclarées en ligne (`auto-fit, minmax(220px…)`) :
       une carte par ligne à cette largeur. Deux, comme `.scorecards`. */
    html body [style*="grid-template-columns"]:has(> [class^="card-"] > .card-header) {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 10px !important;
    }
}


/* =============================================================================
   17. PAGES DE COMPTE ET D'ADMINISTRATION (profil, réglages, stockage,
       abonnements, espaces, monitor, analytics, support)
   =============================================================================
   Chacune porte son propre conteneur centré avec 2 rem de marge latérale —
   qui s'ajoutaient à celles de la coquille : 300 px utiles sur 390. Leurs
   styles sont émis dans le <body> (swap hx-boost), d'où `html body`.
   ============================================================================= */
@media (max-width: 768px) {
    html body .pj-shell-main > .container,
    html body .st-page,
    html body .sub-page,
    html body .an-page,
    html body .wsp-page,
    html body .mon-page,
    html body .pj-shell-main > .bl,
    html body .pf {
        padding: 0 !important;
        margin: 0 auto !important;
        max-width: 100% !important;
    }
    html body .pj-shell-main .page-title,
    html body .pf-h1 { font-size: 1.35rem; }
    html body .pj-shell-main > .container > .admin-header { margin-bottom: 1rem !important; }

    /* Réglages : libellé, champ et bouton empilés — le bouton « Tester »
       sortait de l'écran à droite. */
    html body .settings-card,
    html body .pf-card,
    html body .st-card,
    html body .mon-card { padding: 16px 14px; min-width: 0; }
    html body .settings-row,
    html body .settings-bento .settings-row {
        grid-template-columns: minmax(0, 1fr) !important;
        gap: 0.5rem;
    }
    html body .settings-row > .btn,
    html body .settings-row > button { justify-self: start; }
    html body .settings-bento { grid-template-columns: minmax(0, 1fr) !important; }
    html body .settings-tabs-nav {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        overscroll-behavior-x: contain;
    }
    html body .settings-tabs-nav::-webkit-scrollbar { display: none; }
    html body .settings-tab-btn { white-space: nowrap; flex: none; padding: 0.65rem 0.8rem; }

    /* Grilles de chiffres : deux par ligne. */
    html body .st-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    html body .st-big { font-size: 1.3rem; }
    html body .sub-cards { gap: 10px; }
    html body .sub-card { flex: 1 1 calc(50% - 10px); min-width: 0; padding: 0.85rem 1rem; }

    /* Tableaux d'administration sans cadre défilant : le tableau devient
       lui-même le cadre (`display: block` + défilement), ses cellules gardent
       leur largeur naturelle au lieu d'être écrasées mot à mot. */
    html body .st-table:not(.st-empty),
    html body .sub-table,
    html body .wsp-table,
    html body .pf-tbl,
    html body .users-table,
    html body .prompt-vars-table,
    html body .an-table,
    html body .settings-card table {
        display: block;
        width: 100%;
        max-width: 100%;
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }
    html body .st-table:not(.st-empty) :is(th, td),
    html body .sub-table :is(th, td),
    html body .wsp-table :is(th, td),
    html body .pf-tbl :is(th, td),
    html body .users-table :is(th, td),
    html body .an-table :is(th, td),
    html body .settings-card table :is(th, td) { white-space: nowrap; }

    /* Monitor (Admin système). */
    html body .mon-bento { grid-template-columns: minmax(0, 1fr) !important; gap: 12px; }
    html body .mon-sidebar { flex-direction: column; }
    html body .mon-gauges { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
    html body .mon-header { flex-wrap: wrap; gap: 8px; }
    html body .mon-job-row { grid-template-columns: minmax(0, 1fr) auto 64px !important; gap: 6px; }
    html body .mon-job-id,
    html body .mon-job-dur { display: none; }
    html body .mon-job-dir { overflow-wrap: anywhere; }
    html body .mon-proj-head,
    html body .mon-proj-row { grid-template-columns: minmax(0, 1fr) 60px 70px !important; gap: 6px; }
    html body .mon-proj-owner { display: none; }
    html body .mon-card { overflow-x: auto; }
}


/* =============================================================================
   18. POPINS, MODALES ET MENUS FLOTTANTS
   =============================================================================
   Règle générale (Material 3, NN/g « bottom sheets ») : sur téléphone, une
   popin tient dans l'écran — jamais plus haute que la zone visible (`dvh`),
   jamais plus large, son corps défile, ses boutons restent atteignables. Les
   formulaires lourds (nouveau crawl, fiche d'URL) sont déjà plein écran.
   Les ajustements ci-dessous sont ceux qu'a révélés la tournée Playwright de
   chaque popin (voir [[Responsive mobile]] § Vérification).
   ============================================================================= */
@media (max-width: 768px) {
    /* Formulaire « nom + couleur + Créer » (catégories, tags du backlog) : le
       bouton sortait à droite. Le champ prend la ligne, le bouton passe dessous
       s'il le faut. */
    html body .cat-add-form { flex-wrap: wrap; gap: 8px; }
    html body .cat-add-form .cat-name-input { flex: 1 1 160px; min-width: 0; }
    html body .cat-add-form .cat-add-btn { flex: 1 1 100%; justify-content: center; }
    html body .cat-modal-container,
    html body .modal-content,
    html body .pl-modal-content,
    html body .ds-modal-content,
    html body .ds-edit-modal-content,
    html body .sup-modal-content,
    html body .wsp-modal,
    html body .sq-modal,
    html body .brk-modal-card,
    html body .ag-modal-box,
    html body .scope-modal-content,
    html body .help-modal-content,
    html body .welcome-modal-content {
        max-height: calc(100dvh - 24px) !important;
        max-width: calc(100vw - 16px) !important;
    }

    /* Fiche d'URL : les tableaux « Information | Valeur » passent à la ligne
       (le `nowrap` des tableaux de données, §13, les rendait plus larges que
       l'écran), et sans colonne figée — il n'y a que deux colonnes. */
    html body .url-modal-content .details-table td { white-space: normal; overflow-wrap: anywhere; }
    html body .url-modal-content .details-table th { white-space: nowrap; }
    html body .url-modal-content .details-table :is(td, th):first-child { position: static; box-shadow: none; }
    html body .url-modal-content .url-gsc-period { white-space: normal; }
    html body .url-modal-content .url-tab-content { overflow-x: hidden; }

    /* Popovers « Demander à l'IA » (SQL, URL, liens) : une feuille pleine
       largeur, plus une bulle de 560 px calée sur le bouton. */
    html body .ai-sql-popover,
    html body .ai-url-popover,
    html body .ai-link-popover {
        position: fixed !important;
        left: 8px !important;
        right: 8px !important;
        top: 68px !important;
        bottom: auto !important;
        width: auto !important;
        max-height: calc(100dvh - 84px);
        overflow-y: auto;
        z-index: 2000;
    }

    html body #userModal > div { max-height: calc(100dvh - 24px) !important; }

    /* Tiroir ouvert : la bulle Sherpa et son invitation passaient DEVANT. */
    html.mnav-open .dr-brief-bubble,
    html.mnav-open .dr-brief-greeting { visibility: hidden; }
}


/* =============================================================================
   19. PAGES PUBLIQUES (connexion, inscription, mot de passe, invitation)
   ============================================================================= */
@media (max-width: 768px) {
    /* La colonne défilait DANS un document figé, et le formulaire (`min-height:
       0`) glissait sous le sélecteur de langue du pied — « Confirmer le mot de
       passe » disparaissait derrière. Sur téléphone, c'est la page qui défile
       et le pied vient après le formulaire. */
    html body:has(.login-split) { overflow: auto; }
    html body .login-split { min-height: 100dvh; }
    html body .login-pane {
        overflow: visible;
        min-height: 100dvh;
        padding: 20px 18px max(20px, env(safe-area-inset-bottom));
    }
    html body .login-main { flex: 1 0 auto; padding: 20px 0; }
    /* Le logo pleine largeur occupait un tiers d'écran avant le moindre champ. */
    html body .login-logo { margin-bottom: 8px; }
    html body .login-logo img { max-width: 180px; }
    html body .login-header { margin-bottom: 1.25rem; }
    html body .login-title { font-size: 1.45rem; }
    html body .login-foot { justify-content: center; padding-top: 8px; }
}


/* =============================================================================
   20. ÉCRANS TACTILES — ce que le survol révélait
   =============================================================================
   Sur desktop, plusieurs commandes n'apparaissent qu'au survol de leur ligne
   (menu ⋯ d'un ticket, actions d'une colonne du backlog,
   suppression d'un commentaire…). Au doigt, il n'y a pas de survol : elles
   restaient invisibles, donc introuvables. `hover: none` les affiche en
   permanence et agrandit leur zone de tap (22 px → 32 px). Le menu ⋯ d'une
   conversation suit la même règle, dans `chat-panel.css`.
   ============================================================================= */
@media (hover: none) {
    html body .bl-card-menu,
    html body .bl-icon-btn,
    html body .bl-comment-del,
    html body .dr-brief-conv-item-delete,
    html body .btn-add-or,
    html body .pc-kebab-wrap,
    html body .rule-drag-handle { opacity: 1; }
    html body .bl-card-menu { width: 32px; height: 32px; }
    /* Poignée des règles de segments : seul point de départ du glissé au
       doigt, elle mérite une vraie cible. */
    html body .rule-drag-handle { min-width: 36px; min-height: 36px; justify-content: center; margin: -6px 0 -6px -8px; }
}
