/* ============================================================
   cards.css — styles partagés par toutes les cards du dashboard.
   Conventions :
     - Tous les noms de classes sont préservés (les composants
       JS s'y câblent — voir public/src/front/cards/).
     - Couleurs via tokens.css uniquement.
     - Grid : 4 cols ≥1024 px, 2 cols 768–1023 px, 1 col <768 px.
     - Container queries (@container) pour les layouts internes
       qui dépendent de la largeur de la card, pas du viewport.
     - min-width: 0 systématique sur grid items (anti-overflow).
     - Tout est dans @layer components (ordre déclaré dans tokens.css).
   ============================================================ */

@layer components {
  /* --------------------------------------------------------------
   Grid principal
   -------------------------------------------------------------- */
  .dashboard-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--gap-grid);
    padding: 0;
    min-width: 0;
  }

  @media (min-width: 768px) {
    .dashboard-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (min-width: 1024px) {
    .dashboard-grid {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
  }

  /* Section divider : label uppercase + ligne fine à droite */
  .dashboard-grid-section {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
    min-width: 0;
  }
  .dashboard-grid-section:first-child {
    margin-top: 0;
  }

  .dashboard-grid-section-label {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--tx2);
    white-space: nowrap;
  }

  .dashboard-grid-section-line {
    flex: 1 1 auto;
    height: 1px;
    background: var(--bd);
  }

  /* Span helpers — sur mobile (< 768) tout passe en col-1 (cf. fin du fichier). */
  .col-1 {
    grid-column: span 1;
  }
  .col-2 {
    grid-column: span 2;
  }
  .col-3 {
    grid-column: span 3;
  }
  .col-4 {
    grid-column: span 4;
    min-width: 0;
  }

  /* En tablette (768–1023) la grille est à 2 cols : on plafonne. */
  @media (max-width: 1023.98px) {
    .col-3,
    .col-4 {
      grid-column: span 2;
    }
  }

  /* --------------------------------------------------------------
   Card — primitive de base
   -------------------------------------------------------------- */
  .card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    /* Sprint refonte fix 2026-05-13 — Fred : "maintenant que tu as retiré
       les barres grises, grand vide dans les cards". Le min-height: 140px
       réservait l'espace pour le skeleton ; sans skeleton ça créait un
       grand vide visible. min-height retiré au profit d'un padding
       constant — la card s'adapte au contenu, header reste compact en
       loading puis grandit quand le body est rempli.
       Réserve juste assez pour ne pas que la card "saute" lors du fetch. */
    min-height: 100px;
    padding: var(--space-5);
    background: linear-gradient(180deg, var(--bg2), var(--bg2));
    border: 1px solid var(--bd);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-1);
    transition:
      box-shadow var(--t-base),
      border-color var(--t-base);
    /* Container query — permet aux layouts internes de réagir à la
     largeur de la card (utile quand col-1 sur écran large = ~280px,
     mais col-4 = ~1300px pour le même composant). */
    container-type: inline-size;
  }

  .card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--radius-lg);
    border: 1px solid transparent;
    pointer-events: none;
    transition: border-color var(--t-base);
  }
  .card:hover {
    border-color: var(--bd2);
    box-shadow: var(--shadow-2);
  }
  .card:hover::before {
    border-color: color-mix(in srgb, var(--ac) 28%, transparent);
  }

  .card-h {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
    min-width: 0;
  }

  .card-h-lead {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
  }

  .card-title {
    font-size: var(--text-xs);
    color: var(--tx3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .kpi-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: var(--ac2);
    color: var(--ac);
    flex: 0 0 auto;
  }

  .card-body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
  }

  /* --------------------------------------------------------------
   KPI heroes
   -------------------------------------------------------------- */
  .kpi-row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-1);
    min-width: 0;
  }
  .kpi-value {
    font-family: var(--font-mono);
    font-size: var(--text-fluid-kpi);
    font-weight: 600;
    color: var(--tx);
    line-height: 1.05;
    letter-spacing: -0.02em;
    /* Empêche un nombre/string très long de pousser la card */
    overflow-wrap: anywhere;
    word-break: break-word;
    min-width: 0;
  }

  .kpi-trend {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px;
    font-size: var(--text-xs);
    font-family: var(--font-mono);
    font-weight: 500;
    border-radius: 99px;
    width: fit-content;
  }

  .trend-up {
    color: var(--ok);
    background: var(--ok2);
  }
  .trend-down {
    color: var(--dn);
    background: var(--dn2);
  }
  .trend-flat {
    color: var(--tx2);
    background: var(--bg3);
  }

  /* --------------------------------------------------------------
   Live (visiteurs en ligne)
   -------------------------------------------------------------- */
  .live-row {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
  }
  .live-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ac);
    box-shadow: 0 0 0 0 var(--ac2);
    animation: live-pulse 1.5s infinite ease-out;
  }
  @keyframes live-pulse {
    0% {
      box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.45);
    }
    70% {
      box-shadow: 0 0 0 10px rgba(16, 185, 129, 0);
    }
    100% {
      box-shadow: 0 0 0 0 rgba(16, 185, 129, 0);
    }
  }
  .live-sub {
    font-size: var(--text-xs);
    color: var(--tx2);
  }

  /* --------------------------------------------------------------
   Tooltip "?" dans header de card
   -------------------------------------------------------------- */
  .tooltip-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    color: var(--tx3);
    background: transparent;
    border: 0;
    border-radius: 50%;
    cursor: pointer;
    transition:
      color var(--t-fast),
      background-color var(--t-fast);
    flex: 0 0 auto;
  }
  .tooltip-trigger:hover {
    color: var(--ac);
    background: var(--ac2);
  }
  .tooltip-trigger[aria-expanded='true'] {
    color: var(--ac);
    background: var(--ac2);
  }

  .tooltip-popover {
    position: absolute;
    top: calc(var(--space-4) + 26px);
    right: var(--space-4);
    z-index: 50;
    max-width: min(320px, calc(100% - 2 * var(--space-4)));
    padding: var(--space-3);
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 8px;
    box-shadow: var(--shadow-3);
    color: var(--tx2);
    font-size: var(--text-sm);
    line-height: 1.5;
  }
  .tooltip-popover::before {
    content: '';
    position: absolute;
    top: -6px;
    right: 8px;
    width: 10px;
    height: 10px;
    background: var(--bg3);
    border-top: 1px solid var(--bd);
    border-left: 1px solid var(--bd);
    transform: rotate(45deg);
  }
  .tooltip-line {
    margin: 0 0 var(--space-2);
  }
  .tooltip-line:last-child {
    margin-bottom: 0;
  }

  /* --------------------------------------------------------------
   États card (loading / error / empty)
   -------------------------------------------------------------- */
  .card.is-loading .card-body,
  .card.is-error .card-body,
  .card.is-empty .card-body {
    justify-content: center;
    align-items: flex-start;
    color: var(--tx2);
  }

  .card-skeleton {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
  }
  .card-skeleton-line {
    height: 12px;
    background: var(--bg3);
    border-radius: var(--radius-sm);
    /* Sprint refonte fix 2026-05-13 (v3) — Fred : "toujours ces barres
       horizontales grises qui bougent". Animation skeleton-shimmer
       supprimée GLOBALEMENT (avant : uniquement dans .multi-tab-host).
       Skeleton reste comme indicateur statique pendant le fetch (~200-500
       ms), pas d'animation distrayante. */
  }
  .card-skeleton-line.skel-w-50 {
    width: 50%;
  }
  .card-skeleton-line.skel-w-70 {
    width: 70%;
  }
  .card-skeleton-line.skel-w-90 {
    width: 90%;
  }
  .card-skeleton-line.skel-h-20 {
    height: 20px;
  }
  .card-skeleton-line.skel-h-32 {
    height: 32px;
  }
  @keyframes skeleton-shimmer {
    0% {
      background-position: 200% 0;
    }
    100% {
      background-position: -200% 0;
    }
  }

  .card-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid var(--bd);
    border-top-color: var(--ac);
    border-radius: 50%;
    animation: card-spin 0.8s linear infinite;
    vertical-align: middle;
    margin-right: 6px;
  }
  @keyframes card-spin {
    to {
      transform: rotate(360deg);
    }
  }
  .card-loading-text {
    font-size: var(--text-sm);
    color: var(--tx2);
  }

  .card-error {
    font-size: var(--text-sm);
    color: var(--tx2);
  }
  .card-error-title {
    font-weight: 500;
    color: var(--tx);
    margin-bottom: var(--space-1);
  }
  .card-error-code {
    display: inline-block;
    margin-right: var(--space-2);
    padding: 1px 6px;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--dn);
    background: var(--dn2);
    border-radius: var(--radius-sm);
  }
  .card-error-msg {
    margin-bottom: var(--space-2);
  }
  .card-error-retry {
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--ac);
    background: transparent;
    border: 1px solid var(--bd);
    border-radius: var(--radius-sm);
    padding: var(--space-2) var(--space-3);
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      background var(--t-fast);
  }
  .card-error-retry:hover {
    border-color: var(--ac);
    background: var(--ac2);
  }
  .card-error-retry:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
  }

  .card-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-3);
    text-align: center;
    width: 100%;
  }
  .card-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--bg3);
    color: var(--tx3);
  }
  .card-empty-title {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--tx);
    margin: 0;
  }
  .card-empty-text {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.45;
  }

  /* Variante k-anon : icône bouclier + tonalité "protection en cours", pas
   "donnée manquante". Texte légèrement plus large pour accommoder l'explication
   pédagogique. */
  .card-empty--kanon {
    max-width: 360px;
    margin: 0 auto;
    gap: var(--space-2);
  }
  .card-empty--kanon .card-empty-icon {
    background: var(--ac2);
    color: var(--ac);
    width: 44px;
    height: 44px;
  }
  .card-empty--kanon .card-empty-title {
    color: var(--tx);
  }
  .card-empty--kanon .card-empty-text {
    color: var(--tx2);
  }
  .card-empty--kanon .card-empty-text b {
    color: var(--tx);
    font-weight: 600;
  }
  .card-empty-progress {
    margin: var(--space-1) 0 0;
    font-size: var(--text-xs);
    color: var(--tx3);
  }
  .card-empty-progress b {
    color: var(--ac);
    font-weight: 600;
  }

  /* Levier 3 — cardinalité sans détail. Affiché en plus de progress quand
   data.distinct_count > 0. Bloc discret pour rassurer le proprio :
   "tu as bien du trafic, juste pas assez par valeur pour le détailler". */
  .card-empty-cardinality {
    margin: var(--space-1) 0 0;
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.5;
    max-width: 360px;
    text-align: center;
  }
  .card-empty-cardinality b {
    color: var(--tx);
    font-weight: 600;
  }

  /* --------------------------------------------------------------
   Bandeaux contextuels Vue d'ensemble (crawler-notice + widen-period)
   -------------------------------------------------------------- */
  .overview-notices {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
  }
  .overview-notice {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: 8px;
    font-size: var(--text-sm);
    color: var(--tx);
    line-height: 1.45;
  }
  .overview-notice--crawlers {
    border-left: 3px solid var(--ac);
  }
  .overview-notice--widen {
    border-left: 3px solid var(--wr, var(--ac));
  }
  .overview-notice-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--bg3);
    color: var(--ac);
    flex-shrink: 0;
  }
  .overview-notice--widen .overview-notice-icon {
    color: var(--wr, var(--ac));
  }
  .overview-notice-body {
    flex: 1 1 auto;
    min-width: 0;
  }
  .overview-notice-text {
    margin: 0;
    color: var(--tx2);
  }
  .overview-notice-text b {
    color: var(--tx);
    font-weight: 600;
  }
  .overview-notice-cta {
    flex-shrink: 0;
    padding: 6px 12px;
    background: transparent;
    border: 1px solid var(--bd);
    border-radius: 6px;
    font-size: var(--text-sm);
    color: var(--ac);
    text-decoration: none;
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      background var(--t-fast);
  }
  .overview-notice-cta:hover {
    border-color: var(--ac);
    background: var(--ac2);
  }

  /* --------------------------------------------------------------
   Geo top3 (compact card 1.11)
   -------------------------------------------------------------- */
  .geo-map {
    margin-bottom: var(--space-3);
  }
  .geo-top3-title {
    font-size: var(--text-xs);
    color: var(--tx3);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: var(--space-2);
  }
  .top3 {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
  }
  .top3 li {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr) minmax(40px, 60px) auto;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    min-width: 0;
  }
  .top3 .flag {
    width: 20px;
    height: 15px;
    border-radius: 2px;
    object-fit: cover;
    border: 1px solid var(--bd);
  }

  .flag-inline {
    display: inline-block;
    vertical-align: middle;
    border-radius: 50%;
    object-fit: cover;
    margin-right: var(--space-2);
    flex-shrink: 0;
  }
  .cell-country {
    display: inline-flex;
    align-items: center;
    gap: 0;
    min-width: 0;
  }

  .cell-referrer {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
  }
  .cell-referrer-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    color: var(--tx2);
    flex-shrink: 0;
  }

  .top3 .top3-name {
    color: var(--tx);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }
  .top3 .bar {
    display: block;
    position: relative;
    height: 4px;
    background: var(--bg3);
    border-radius: 2px;
    overflow: hidden;
  }
  .top3 .bar-inner {
    display: block;
    height: 100%;
    background: var(--ac);
    border-radius: 2px;
  }
  .top3 .num {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--tx2);
    text-align: right;
  }

  /* --------------------------------------------------------------
   Data table (utilisée par 7+ cards)
   -------------------------------------------------------------- */
  .data-table-wrap {
    width: 100%;
    min-width: 0;
  }
  .data-table-scroll {
    width: 100%;
    overflow-x: auto;
    /* Indique visuellement qu'on peut scroller (gradient mask sur les bords). */
    -webkit-overflow-scrolling: touch;
  }

  .data-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
  }
  .data-table thead th {
    text-align: left;
    padding: var(--space-2) var(--space-3);
    color: var(--tx3);
    font-weight: 500;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--bd);
    white-space: nowrap;
  }
  .data-table tbody td {
    padding: var(--space-2) var(--space-3);
    color: var(--tx);
    border-bottom: 1px solid var(--bd);
  }
  .data-table tbody tr:last-child td {
    border-bottom: 0;
  }
  .data-table tbody tr:hover td {
    background: var(--bg3);
  }

  /* Sprint J 2026-05-14 — row avec tooltip compare hover (Plausible-like).
     Curseur help pour signaler que le hover apporte une info supplémentaire. */
  .data-table tbody tr.dt-row-compare {
    cursor: help;
  }

  /* Tooltip flottant — singleton réutilisé pour toutes les rows. */
  .data-table-compare-tooltip {
    position: absolute;
    z-index: 100;
    min-width: 180px;
    max-width: 280px;
    padding: 10px 12px;
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: 8px;
    box-shadow: var(--shadow-3);
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--tx);
    pointer-events: none;
    animation: dt-tip-in 120ms var(--ease);
  }
  @keyframes dt-tip-in {
    from {
      opacity: 0;
      transform: translateY(-2px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  .data-table-compare-tooltip .dt-tip-label {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tx3);
    margin-bottom: 4px;
  }
  .data-table-compare-tooltip .dt-tip-value {
    font-weight: 500;
    color: var(--tx);
    font-variant-numeric: tabular-nums;
  }
  .data-table-compare-tooltip .dt-tip-delta {
    margin-left: 6px;
    font-size: 12px;
    font-weight: 600;
  }
  .data-table-compare-tooltip .dt-tip-delta.is-up {
    color: var(--ok);
  }
  .data-table-compare-tooltip .dt-tip-delta.is-down {
    color: var(--dn);
  }
  .data-table-compare-tooltip .dt-tip-new {
    font-weight: 600;
    color: var(--ac);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.05em;
  }

  /* Mobile : tooltip plus large + tap au lieu de hover */
  @media (max-width: 640px) {
    .data-table-compare-tooltip {
      max-width: calc(100vw - 32px);
      pointer-events: auto; /* permet tap pour fermer */
    }
    .data-table tbody tr.dt-row-compare {
      cursor: pointer; /* tap au lieu de hover */
    }
  }

  .data-table .cell-text {
    color: var(--tx);
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .data-table .cell-num {
    font-family: var(--font-mono);
    color: var(--tx);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  .data-table .cell-primary {
    position: relative;
  }

  .data-table td.deviation-negative {
    color: var(--dn);
  }

  /* --------------------------------------------------------------
   Pagination
   -------------------------------------------------------------- */
  .pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--bd);
    flex-wrap: wrap;
  }
  .pagination-info {
    font-size: var(--text-xs);
    color: var(--tx3);
  }
  .pagination .load-more {
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--ac);
    background: transparent;
    border: 1px solid var(--bd);
    border-radius: var(--r);
    padding: var(--space-1) var(--space-3);
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      background var(--t-fast);
  }
  .pagination .load-more:hover:not(:disabled) {
    border-color: var(--ac);
    background: var(--ac2);
  }
  .pagination .load-more:disabled {
    color: var(--tx3);
    cursor: not-allowed;
    opacity: 0.5;
  }

  /* --------------------------------------------------------------
   Empty placeholder & subtitle
   -------------------------------------------------------------- */
  .empty-placeholder {
    padding: var(--space-3) 0;
    color: var(--tx2);
    font-size: var(--text-sm);
    line-height: 1.5;
  }
  .empty-placeholder p {
    margin: 0 0 var(--space-2);
  }
  .empty-link {
    color: var(--ac);
    text-decoration: none;
  }
  .empty-link:hover {
    text-decoration: underline;
  }

  .card-subtitle {
    margin: 0 0 var(--space-2);
    font-size: var(--text-xs);
    color: var(--tx2);
    font-family: var(--font-mono);
  }

  .card-notice {
    margin: 0;
    padding: var(--space-3);
    background: var(--bg3);
    color: var(--tx2);
    border-radius: 6px;
    font-size: var(--text-sm);
  }

  .card-header-btn {
    font-family: var(--font-ui);
    font-size: var(--text-xs);
    color: var(--ac);
    background: transparent;
    border: 1px solid var(--bd);
    border-radius: 6px;
    padding: 3px 8px;
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      background var(--t-fast);
  }
  .card-header-btn:hover {
    border-color: var(--ac);
    background: var(--ac2);
  }

  /* --------------------------------------------------------------
   Quartile bars (cards 3.1 + 3.2)
   -------------------------------------------------------------- */
  .quartile-bars {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
  }
  .quartile-bar-row {
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3);
    font-size: var(--text-sm);
    min-width: 0;
  }
  .quartile-bar-label {
    font-family: var(--font-mono);
    color: var(--tx2);
    font-size: var(--text-xs);
  }
  .quartile-bar-track {
    position: relative;
    height: 14px;
    background: var(--bg3);
    border-radius: 3px;
    overflow: hidden;
  }
  .quartile-bar-fill {
    height: 100%;
    transition: width 240ms ease;
    border-radius: 3px;
  }
  .quartile-bar-value {
    font-family: var(--font-mono);
    color: var(--tx);
    font-size: var(--text-xs);
    white-space: nowrap;
  }

  .scroll-abandon {
    margin-bottom: var(--space-3);
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-xs);
    color: var(--tx2);
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 6px;
  }
  .attention-notice {
    margin: var(--space-3) 0 0;
    font-size: var(--text-xs);
    color: var(--tx3);
    font-style: italic;
  }

  /* --------------------------------------------------------------
   Page selector (onglet 3)
   -------------------------------------------------------------- */
  .behavior-selector-wrap {
    margin-bottom: var(--space-4);
  }

  /* UX 2026-05-14 — le pageSelector vit maintenant dans le body de la
     MultiTabCard, juste au-dessus de la .multi-tab-bar. Padding interne
     pour s'aligner sur le rythme de la card ; pas de margin-bottom car
     la .multi-tab-bar a déjà son propre padding-top. */
  .multi-tab-card-body > .behavior-selector-wrap {
    margin-bottom: 0;
    padding: var(--space-3) var(--space-4) 0;
  }

  .page-selector {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    flex-wrap: wrap;
    min-width: 0;
  }
  .page-selector-label {
    font-size: var(--text-sm);
    color: var(--tx2);
    font-weight: 500;
  }
  .page-selector-select {
    flex: 1 1 240px;
    max-width: 100%;
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--tx);
    background: var(--bg);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    padding: var(--space-1) var(--space-3);
    height: 32px;
    min-width: 0;
  }
  .page-selector-select:focus {
    outline: none;
    border-color: var(--ac);
  }
  .page-selector-status {
    font-size: var(--text-sm);
    color: var(--tx3);
  }

  /* --------------------------------------------------------------
   Event selector (card 3.4)
   -------------------------------------------------------------- */
  .event-selector {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
    flex-wrap: wrap;
    min-width: 0;
  }
  .event-selector-label {
    font-size: var(--text-xs);
    color: var(--tx2);
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }
  .event-selector-select {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--tx);
    background: var(--bg);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    padding: 2px var(--space-2);
    height: 28px;
    max-width: 100%;
    min-width: 0;
  }
  .event-timeline-chart {
    min-height: 180px;
  }

  /* --------------------------------------------------------------
   Modal (card 3.3 howto)
   -------------------------------------------------------------- */
  .modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background: rgba(0, 0, 0, 0.5);
  }
  .modal-panel {
    position: relative;
    width: 100%;
    max-width: 560px;
    padding: var(--space-5);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    box-shadow: var(--shadow-3);
  }
  .modal-title {
    margin: 0 0 var(--space-3);
    font-size: var(--text-lg);
    font-weight: 500;
    color: var(--tx);
  }
  .modal-close {
    position: absolute;
    top: var(--space-3);
    right: var(--space-3);
    width: 28px;
    height: 28px;
    font-size: 20px;
    line-height: 1;
    color: var(--tx2);
    background: transparent;
    border: 0;
    cursor: pointer;
  }
  .modal-close:hover {
    color: var(--tx);
  }
  .modal-step {
    margin: 0 0 var(--space-2);
    color: var(--tx);
    font-size: var(--text-sm);
    line-height: 1.5;
  }
  .modal-snippet-wrap {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-3) 0;
    padding: var(--space-3);
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 6px;
    min-width: 0;
  }
  .modal-snippet {
    flex: 1 1 auto;
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--tx);
    white-space: nowrap;
    overflow-x: auto;
    min-width: 0;
  }
  .modal-copy-btn {
    font-family: var(--font-ui);
    font-size: var(--text-xs);
    color: var(--ac);
    background: transparent;
    border: 1px solid var(--bd);
    border-radius: 4px;
    padding: 2px 8px;
    cursor: pointer;
    flex: 0 0 auto;
  }
  .modal-copy-btn:hover {
    border-color: var(--ac);
  }
  .modal-help {
    margin: 0;
    color: var(--tx3);
    font-size: var(--text-xs);
  }

  /* --------------------------------------------------------------
   Donut chart partagé
   -------------------------------------------------------------- */
  .donut-wrap {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 180px;
    min-width: 0;
  }
  .donut {
    display: block;
    max-width: 100%;
    height: auto;
  }
  .donut-segment {
    transition: transform 0.15s ease;
    transform-origin: center;
    cursor: pointer;
  }
  .donut-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    pointer-events: none;
    text-align: center;
  }
  .donut-center-big {
    font-family: var(--font-mono);
    font-size: var(--text-lg);
    color: var(--tx);
    font-weight: 500;
  }
  .donut-center-label {
    font-size: var(--text-xs);
    color: var(--tx2);
    text-transform: uppercase;
    letter-spacing: 0.4px;
  }

  /* --------------------------------------------------------------
   Inline tabs (onglets internes card)
   -------------------------------------------------------------- */
  .inline-tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--bd);
    margin-bottom: var(--space-3);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .inline-tabs::-webkit-scrollbar {
    display: none;
  }

  .inline-tab {
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    padding: 6px 12px;
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--tx2);
    cursor: pointer;
    border-radius: 6px 6px 0 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    flex: 0 0 auto;
  }
  .inline-tab-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    opacity: 0.7;
    filter: grayscale(0.4);
    transition:
      opacity var(--t-fast),
      filter var(--t-fast);
  }
  .inline-tab.is-active .inline-tab-icon,
  .inline-tab:hover:not(.is-active):not(:disabled) .inline-tab-icon {
    opacity: 1;
    filter: none;
  }
  .inline-tab:hover:not(.is-active):not(:disabled) {
    color: var(--tx);
    background: var(--bg3);
  }
  .inline-tab.is-active {
    color: var(--ac);
    border-bottom-color: var(--ac);
    background: var(--ac2);
  }
  .inline-tab.is-disabled,
  .inline-tab[disabled] {
    color: var(--tx3);
    cursor: not-allowed;
    opacity: 0.55;
  }

  /* --------------------------------------------------------------
   Brand icons
   -------------------------------------------------------------- */
  .brand-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--tx2);
    flex: 0 0 auto;
  }
  .brand-icon-fallback {
    background: var(--bg3);
    border-radius: 999px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--tx2);
  }
  .brand-icon-svg {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
  }

  /* --------------------------------------------------------------
   4.1 Channel breakdown (donut + liste)
   -------------------------------------------------------------- */
  .channel-breakdown {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: var(--space-4);
    align-items: center;
    min-width: 0;
  }
  /* Container query : si la card est étroite, on stack en 1 col. */
  @container (max-width: 480px) {
    .channel-breakdown {
      grid-template-columns: 1fr;
    }
    .channel-donut {
      margin-inline: auto;
      max-width: 240px;
    }
  }

  .channel-donut {
    position: relative;
    min-width: 0;
  }
  .channel-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  .channel-row {
    display: grid;
    grid-template-columns: 12px minmax(0, 1fr) auto auto auto;
    align-items: center;
    column-gap: 10px;
    font-size: var(--text-sm);
    min-width: 0;
  }
  .channel-swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    display: inline-block;
  }
  .channel-name {
    color: var(--tx);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }
  .channel-percent {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--tx2);
    min-width: 46px;
    text-align: right;
    font-variant-numeric: tabular-nums;
  }
  .channel-visitors {
    font-family: var(--font-mono);
    color: var(--tx);
    min-width: 52px;
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  /* --------------------------------------------------------------
   4.2 Referrers (checkbox header)
   -------------------------------------------------------------- */
  .header-checkbox {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--text-xs);
    color: var(--tx2);
    cursor: pointer;
    user-select: none;
  }
  .header-checkbox input[type='checkbox'] {
    width: 14px;
    height: 14px;
    accent-color: var(--ac);
    margin: 0;
  }

  /* --------------------------------------------------------------
   4.3 AI traffic
   -------------------------------------------------------------- */
  .ai-agent-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  .ai-agent {
    display: grid;
    grid-template-columns: 32px minmax(0, 1fr) auto auto auto;
    align-items: center;
    column-gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: var(--bg3);
    border-radius: 6px;
    min-width: 0;
  }
  .ai-agent-icon {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ac);
  }
  .ai-agent-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }
  .ai-agent-name {
    font-size: var(--text-sm);
    color: var(--tx);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .ai-agent-provider {
    font-size: var(--text-xs);
    color: var(--tx2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .ai-agent-visits {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--tx);
    font-variant-numeric: tabular-nums;
  }
  .ai-agent-seen {
    font-size: var(--text-xs);
    color: var(--tx3);
    min-width: 80px;
    text-align: right;
  }
  .purpose-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 6px;
    font-size: 10px;
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.3px;
    border-radius: 4px;
  }
  .purpose-training {
    background: var(--wr2);
    color: var(--wr);
  }
  .purpose-search {
    background: var(--ac2);
    color: var(--ac);
  }
  .purpose-assistant {
    background: var(--ac2);
    color: var(--ac);
  }
  .purpose-other {
    background: var(--bg3);
    color: var(--tx3);
  }
  .purpose-human {
    background: var(--ok2, var(--ac2));
    color: var(--ok, var(--ac));
  }

  /* Sections internes "Crawlers IA" vs "Visiteurs depuis chat IA" (Activité IA).
   But : lever la confusion entre robots IA et humains venant de ChatGPT/etc.
   Chaque bloc a son titre, sous-titre court, et son empty-state local. */
  .ai-block {
    margin-top: var(--space-3);
  }
  .ai-block:first-child {
    margin-top: 0;
  }
  .ai-block-heading {
    margin-bottom: var(--space-2);
  }
  .ai-block-title {
    margin: 0;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--tx);
  }
  .ai-block-subtitle {
    margin: 2px 0 0;
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.4;
  }
  .ai-block-empty {
    margin: 0;
    padding: var(--space-3);
    text-align: center;
    font-size: var(--text-xs);
    color: var(--tx3);
    background: var(--bg3);
    border-radius: 6px;
    border: 1px dashed var(--bd);
  }

  .ai-timeline-title {
    margin-top: var(--space-4);
    font-size: var(--text-xs);
    color: var(--tx2);
    text-transform: uppercase;
    letter-spacing: 0.4px;
  }
  .ai-timeline {
    position: relative;
    width: 100%;
    min-height: 160px;
    min-width: 0;
  }

  /* Container query : ai-agent stack en mobile/card étroite */
  @container (max-width: 480px) {
    .ai-agent {
      grid-template-columns: 28px minmax(0, 1fr) auto;
      grid-template-rows: auto auto;
      column-gap: var(--space-2);
    }
    .ai-agent-visits,
    .purpose-badge,
    .ai-agent-seen {
      grid-column: 2 / -1;
      font-size: var(--text-xs);
    }
  }

  /* --------------------------------------------------------------
   5.1 Geo full (choropleth)
   -------------------------------------------------------------- */
  .geo-tabs-wrap {
    margin-bottom: var(--space-2);
  }
  .geo-content-wrap {
    position: relative;
    width: 100%;
    min-height: 480px;
    min-width: 0;
  }
  /* Quand le sous-onglet est vide (pas de carte/données à afficher), on
   relâche le min-height pour ne pas laisser un trou de ~400 px sous le
   message. */
  .card.is-empty .geo-content-wrap,
  .geo-content-wrap:has(> .empty-placeholder),
  .geo-content-wrap:has(> .card-notice),
  .geo-content-wrap:has(> .precision-limited-banner) {
    min-height: 0;
  }
  .choropleth-full {
    position: relative;
    width: 100%;
  }
  .choropleth-full-svg {
    display: block;
    width: 100%;
    height: auto;
    cursor: grab;
  }
  .choropleth-full-svg:active {
    cursor: grabbing;
  }
  .choropleth-full .country--has-data {
    cursor: pointer;
  }

  .choropleth-controls {
    position: absolute;
    top: 10px;
    right: 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    z-index: 2;
  }
  .choropleth-ctrl-btn {
    width: 32px;
    height: 32px;
    background: var(--bg2);
    color: var(--tx);
    border: 1px solid var(--bd);
    border-radius: 6px;
    cursor: pointer;
    font-size: 16px;
    font-family: var(--font-mono);
    line-height: 1;
  }
  .choropleth-ctrl-btn:hover {
    border-color: var(--ac);
    color: var(--ac);
  }

  .choropleth-legend {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
    font-size: var(--text-xs);
    color: var(--tx2);
    flex-wrap: wrap;
  }
  .choropleth-legend-bar {
    flex: 1 1 auto;
    height: 8px;
    border-radius: 4px;
    min-width: 80px;
  }
  .choropleth-legend-min,
  .choropleth-legend-max {
    font-family: var(--font-mono);
  }

  /* --------------------------------------------------------------
   5.5 Devices
   -------------------------------------------------------------- */
  .devices-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-4);
    align-items: center;
    min-width: 0;
  }
  @container (max-width: 480px) {
    .devices-card {
      grid-template-columns: 1fr;
    }
    .devices-donut {
      margin-inline: auto;
      max-width: 240px;
    }
  }

  .devices-donut {
    position: relative;
    min-width: 0;
  }
  .devices-legend {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
  }
  .devices-legend-row {
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr) auto auto;
    align-items: center;
    column-gap: var(--space-2);
    font-size: var(--text-sm);
    min-width: 0;
  }
  .devices-legend-icon {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .devices-legend-icon svg {
    width: 18px;
    height: 18px;
  }
  .devices-legend-label {
    color: var(--tx);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .devices-legend-percent {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--tx2);
    font-variant-numeric: tabular-nums;
  }
  .devices-legend-value {
    font-family: var(--font-mono);
    color: var(--tx);
    min-width: 50px;
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  /* --------------------------------------------------------------
   stat-bar-list (5.3 / 5.4 / 5.6 / 5.7)
   -------------------------------------------------------------- */
  .stat-bar-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  .stat-bar-row {
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr) minmax(60px, 140px) 60px 50px;
    align-items: center;
    column-gap: 8px;
    font-size: var(--text-sm);
    min-width: 0;
  }
  .stat-bar-icon {
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--tx2);
  }
  .stat-bar-label {
    color: var(--tx);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }
  .stat-bar-bar {
    position: relative;
    height: 6px;
    border-radius: 3px;
    background: var(--bg3);
    overflow: hidden;
  }
  .stat-bar-bar-inner {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    height: 100%;
    background: var(--ac3);
    border-radius: 3px;
    transition: width 0.2s ease;
  }
  .stat-bar-value {
    font-family: var(--font-mono);
    color: var(--tx);
    text-align: right;
    font-variant-numeric: tabular-nums;
  }
  .stat-bar-percent {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--tx2);
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  /* Container query : sur card étroite, on retire la barre */
  @container (max-width: 360px) {
    .stat-bar-row {
      grid-template-columns: 20px minmax(0, 1fr) 60px 45px;
      column-gap: 6px;
    }
    .stat-bar-bar {
      display: none;
    }
  }

  /* --------------------------------------------------------------
   Cards success/empty (6.1 / 6.2)
   -------------------------------------------------------------- */
  .card-success-empty {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4);
    background: var(--ok2);
    border: 1px solid var(--ok);
    border-radius: 8px;
    color: var(--ok);
  }
  .card-success-icon {
    flex: 0 0 auto;
    color: var(--ok);
    display: inline-flex;
  }
  .card-success-msg {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--ok);
  }

  /* ============================================================
   Onglet Conformité (7.x)
   ============================================================ */

  /* 7.1 Bandeau status */
  .compliance-status-banner {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    padding: var(--space-6);
    border-radius: var(--r);
    border: 1px solid var(--ok);
    background: var(--ok2);
    margin-bottom: var(--space-5);
    min-width: 0;
  }
  .compliance-status-banner.status-needs_attention {
    border-color: var(--wr);
    background: var(--wr2);
  }
  .compliance-status-banner.status-non_compliant {
    border-color: var(--dn);
    background: var(--dn2);
  }
  .compliance-status-icon {
    display: inline-flex;
    flex: 0 0 auto;
  }
  .compliance-status-icon.icon-compliant {
    color: var(--ok);
  }
  .compliance-status-icon.icon-needs_attention {
    color: var(--wr);
  }
  .compliance-status-icon.icon-non_compliant {
    color: var(--dn);
  }

  .compliance-status-text {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
  }
  .compliance-status-title {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--text-fluid-banner);
    font-weight: 500;
    color: var(--tx);
    line-height: 1.2;
    overflow-wrap: anywhere;
  }
  .compliance-status-sub {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--tx2);
  }
  .compliance-status-attention {
    margin: var(--space-2) 0 0;
    padding-left: var(--space-5);
    font-size: var(--text-sm);
    color: var(--tx);
  }

  /* 7.1bis Référentiels */
  .compliance-referentials {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin-bottom: var(--space-5);
    padding: var(--space-3) var(--space-4);
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 8px;
    min-width: 0;
  }
  .compliance-referentials-heading {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--tx3);
    font-weight: 500;
    flex: 0 0 auto;
  }
  .compliance-referentials-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    min-width: 0;
  }
  .compliance-referential-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: var(--bg);
    border: 1px solid var(--bd);
    border-radius: 999px;
    font-size: var(--text-xs);
    line-height: 1.3;
    color: var(--tx);
    white-space: nowrap;
  }
  .compliance-referential-chip[data-jurisdiction='EU'] {
    background: var(--ac2);
    border-color: var(--ac);
  }
  .compliance-referential-flag {
    font-size: 14px;
    line-height: 1;
  }
  .compliance-referential-label {
    font-weight: 500;
    color: var(--tx);
  }
  .compliance-referential-version {
    font-family: var(--font-mono);
    color: var(--tx3);
    font-size: 11px;
  }
  .compliance-referentials-note {
    margin: var(--space-2) 0 0;
    flex-basis: 100%;
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.45;
  }

  .compliance-download-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
  }
  @container (max-width: 480px) {
    .compliance-download-grid {
      grid-template-columns: 1fr;
    }
  }

  .compliance-download-btn {
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4);
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 8px;
    color: var(--tx);
    text-decoration: none;
    transition:
      border-color var(--t-fast),
      background var(--t-fast);
    min-width: 0;
  }
  .compliance-download-btn:hover {
    border-color: var(--ac);
    background: var(--ac2);
  }
  .compliance-download-btn:focus-visible {
    outline: 2px solid var(--ac);
    outline-offset: 2px;
  }
  .compliance-download-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ac);
  }
  .compliance-download-btn.txt .compliance-download-icon {
    color: var(--wr);
  }
  .compliance-download-label {
    font-size: var(--text-sm);
    color: var(--tx);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .compliance-download-size {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--tx3);
  }

  /* 7.2 Checklist — card retirée 2026-05-10, sélecteurs orphelins purgés
     Sprint audit 2026-05-13 (compliance-checklist + compliance-ref-* sans
     consommateur). */

  /* 7.3 Retention */
  .retention-policy {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
  }
  .retention-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
  }
  .retention-table thead th {
    text-align: left;
    padding: var(--space-2) var(--space-3);
    color: var(--tx3);
    font-weight: 500;
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--bd);
  }
  .retention-table tbody td {
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--bd);
    color: var(--tx);
  }
  .retention-table tbody tr:last-child td {
    border-bottom: 0;
  }
  .retention-cell-duration {
    font-family: var(--font-mono);
    color: var(--tx);
    white-space: nowrap;
  }
  @container (max-width: 480px) {
    .retention-cell-duration {
      white-space: normal;
    }
    .retention-table thead th,
    .retention-table tbody td {
      padding: var(--space-2) var(--space-2);
    }
  }
  .retention-notice {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--tx2);
    font-style: italic;
  }
  .retention-extra {
    margin: 0;
    font-size: var(--text-xs);
    color: var(--tx3);
  }

  /* 7.4 Export / archive / erase */
  .export-erase-actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }
  .export-erase-btn {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-4) var(--space-5);
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--tx);
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 8px;
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      background var(--t-fast),
      color var(--t-fast);
    min-width: 0;
  }
  .export-erase-btn:hover:not(:disabled) {
    border-color: var(--ac);
    background: var(--ac2);
  }
  .export-erase-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  .export-erase-btn-warning {
    color: var(--wr);
    border-color: var(--wr);
    background: transparent;
  }
  .export-erase-btn-warning:hover:not(:disabled) {
    background: var(--wr2);
    border-color: var(--wr);
  }
  .export-erase-btn-danger {
    color: var(--dn);
    border-color: var(--dn);
    background: transparent;
  }
  .export-erase-btn-danger:hover:not(:disabled) {
    background: var(--dn2);
    border-color: var(--dn);
  }
  .export-erase-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
  }
  .export-erase-status {
    font-size: var(--text-xs);
    color: var(--tx3);
  }

  /* Progress bar (réutilisable) */
  .progress-bar-wrap {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .progress-bar-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: var(--text-xs);
    color: var(--tx2);
  }
  .progress-bar-pct {
    font-family: var(--font-mono);
    color: var(--tx);
    font-variant-numeric: tabular-nums;
  }
  .progress-bar {
    width: 100%;
    height: 8px;
    background: var(--bg3);
    border: 1px solid var(--bd);
    border-radius: 4px;
    overflow: hidden;
  }
  .progress-bar-fill {
    height: 100%;
    background: var(--ac);
    border-radius: 4px;
    transition: width 0.3s ease;
  }

  /* Confirm dialog */
  .confirm-dialog-backdrop {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    background: rgba(0, 0, 0, 0.55);
  }
  .confirm-dialog {
    width: 100%;
    max-width: 520px;
    padding: var(--space-6);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    box-shadow: var(--shadow-3);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
  }
  .confirm-dialog-warning {
    border-color: var(--wr);
  }
  .confirm-dialog-danger {
    border-color: var(--dn);
  }
  .confirm-dialog-title {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--text-lg);
    font-weight: 500;
    color: var(--tx);
  }
  .confirm-dialog-desc {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }
  .confirm-dialog-checkbox {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    background: var(--bg3);
    border-radius: 6px;
    font-size: var(--text-sm);
    color: var(--tx);
    cursor: pointer;
  }
  .confirm-dialog-checkbox input[type='checkbox'] {
    margin-top: 2px;
    accent-color: var(--dn);
  }
  .confirm-dialog-type {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--tx);
  }
  .confirm-dialog-type-label {
    color: var(--tx2);
  }
  .confirm-dialog-type-input {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    padding: var(--space-2) var(--space-3);
    background: var(--bg3);
    color: var(--tx);
    border: 1px solid var(--bd);
    border-radius: 6px;
    outline: none;
    min-width: 0;
  }
  .confirm-dialog-type-input:focus {
    border-color: var(--dn);
  }
  .confirm-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    flex-wrap: wrap;
  }
  .confirm-dialog-btn {
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    padding: var(--space-2) var(--space-4);
    border-radius: 6px;
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      background var(--t-fast),
      color var(--t-fast);
    border: 1px solid var(--bd);
    background: transparent;
    color: var(--tx);
  }
  .confirm-dialog-btn-cancel:hover {
    border-color: var(--tx2);
  }
  .confirm-dialog-btn-confirm.confirm-dialog-btn-normal {
    color: var(--ac);
    border-color: var(--ac);
  }
  .confirm-dialog-btn-confirm.confirm-dialog-btn-normal:hover:not(:disabled) {
    background: var(--ac2);
  }
  .confirm-dialog-btn-confirm.confirm-dialog-btn-warning {
    color: var(--wr);
    border-color: var(--wr);
  }
  .confirm-dialog-btn-confirm.confirm-dialog-btn-warning:hover:not(:disabled) {
    background: var(--wr2);
  }
  .confirm-dialog-btn-confirm.confirm-dialog-btn-danger {
    color: var(--dn);
    border-color: var(--dn);
  }
  .confirm-dialog-btn-confirm.confirm-dialog-btn-danger:hover:not(:disabled) {
    background: var(--dn2);
  }
  .confirm-dialog-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  /* Site-new dialog */
  .site-new-dialog-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    margin: var(--space-3) 0 0;
  }
  .site-new-dialog-field > span {
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--tx2);
  }
  .site-new-dialog-input {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--tx);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    padding: var(--space-2) var(--space-3);
    outline: none;
    min-width: 0;
  }
  .site-new-dialog-input:focus {
    border-color: var(--ac);
  }
  .site-new-dialog-error {
    min-height: 1.25em;
    margin: var(--space-2) 0 0;
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--dn);
  }

  /* Toast */
  .toast-wrap {
    position: fixed;
    bottom: var(--space-6);
    left: 50%;
    transform: translateX(-50%);
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    pointer-events: none;
    max-width: calc(100vw - 2 * var(--space-4));
  }
  .toast {
    pointer-events: auto;
    padding: var(--space-3) var(--space-4);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: 8px;
    font-size: var(--text-sm);
    color: var(--tx);
    box-shadow: var(--shadow-3);
    cursor: pointer;
    max-width: 480px;
    animation: toast-enter 180ms ease-out;
  }
  .toast-success {
    border-color: var(--ok);
  }
  .toast-warning {
    border-color: var(--wr);
  }
  .toast-danger {
    border-color: var(--dn);
  }
  .toast-leave {
    opacity: 0;
    transition: opacity 200ms ease;
  }
  @keyframes toast-enter {
    from {
      transform: translateY(8px);
      opacity: 0;
    }
    to {
      transform: translateY(0);
      opacity: 1;
    }
  }

  /* 7.5 DPO contact */
  .dpo-contact {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-5);
    min-width: 0;
  }
  @container (max-width: 720px) {
    .dpo-contact {
      grid-template-columns: 1fr;
      gap: var(--space-4);
    }
  }
  .dpo-contact-section {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
  }
  .dpo-contact-section-label {
    font-size: var(--text-xs);
    color: var(--tx3);
    text-transform: uppercase;
    letter-spacing: 0.5px;
  }
  .dpo-contact-email {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: var(--text-lg);
    color: var(--ac);
    text-decoration: none;
    word-break: break-all;
  }
  .dpo-contact-email:hover {
    text-decoration: underline;
  }
  .dpo-contact-address {
    font-style: normal;
    color: var(--tx2);
    font-size: var(--text-sm);
    line-height: 1.6;
  }
  .dpo-contact-delay {
    margin: 0;
    color: var(--tx2);
    font-size: var(--text-sm);
  }

  .compliance-footer {
    margin-top: var(--space-6);
    padding: var(--space-6) var(--space-4);
    text-align: center;
    border-top: 1px solid var(--bd);
  }
  .compliance-footer p {
    margin: 0 auto;
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.6;
    max-width: 720px;
  }
  .compliance-footer strong {
    color: var(--tx);
  }

  /* ============================================================
   Onglet Intégration
   ============================================================ */

  .integration-grid {
    /* hook overrides */
  }

  /* Code block partagé (snippet + events) */
  .install-code-block {
    position: relative;
    background: var(--bg);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    padding: var(--space-3);
    margin: 0;
    min-width: 0;
  }
  .install-code {
    margin: 0;
    padding: 0;
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    line-height: 1.5;
    color: var(--tx);
    white-space: pre;
    -webkit-overflow-scrolling: touch;
  }
  .install-code code {
    background: transparent;
    padding: 0;
    border: 0;
  }

  .install-copy-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    padding: 6px 10px;
    font-size: var(--text-xs);
    background: var(--bg2);
    color: var(--tx);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    cursor: pointer;
    transition:
      background var(--t-fast),
      color var(--t-fast);
  }
  .install-copy-btn:hover {
    background: var(--bg3);
  }
  .install-copy-btn.is-copied {
    background: var(--ok);
    color: #fff;
    border-color: var(--ok);
  }
  .install-copy-btn-sm {
    padding: 4px 6px;
  }

  /* Card 1 — snippet */
  .install-snippet-instructions,
  .install-snippet-empty {
    margin: 0 0 var(--space-3);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }

  /* Card 1 — lien discret vers /docs/<locale>/bypass-adblockers, posé sous le
   snippet pour signaler l'option self-host à tout intégrateur qui doute du
   blocage adblocker. Bandeau bas, taille modérée pour ne pas voler la
   vedette au snippet principal. */
  .install-snippet-adblock-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: var(--space-3);
    padding: 6px 10px;
    font-size: var(--text-xs);
    color: var(--tx2);
    text-decoration: none;
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    transition:
      color 0.15s ease,
      border-color 0.15s ease,
      background 0.15s ease;
  }
  .install-snippet-adblock-link:hover {
    color: var(--ac);
    border-color: var(--ac);
    background: var(--bg3);
  }
  .install-snippet-adblock-link-icon {
    display: inline-flex;
    color: var(--ac);
  }

  /* Card 1 — bouton "Tester l'installation" + résultat inline. */
  .install-snippet-test-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
  }
  .install-test-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 6px 12px;
    font-size: var(--text-xs);
    background: var(--bg2);
    color: var(--tx);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    cursor: pointer;
    transition: background var(--t-fast);
  }
  .install-test-btn:hover:not(:disabled) {
    background: var(--bg3);
  }
  .install-test-btn:disabled {
    opacity: 0.6;
    cursor: progress;
  }
  .install-test-result {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.4;
  }
  .install-test-result-text {
    color: var(--tx);
  }

  /* Card 2 — opt-out (4 sections) */
  .install-optout-section {
    margin: 0 0 var(--space-4);
    padding: var(--space-3);
    border-radius: 6px;
    background: var(--bg3);
    border-left: 3px solid var(--bg2);
  }
  .install-optout-section:last-child {
    margin-bottom: 0;
  }
  .install-optout-section-why {
    border-left-color: var(--ac);
  }
  .install-optout-section-how {
    border-left-color: var(--tx);
    background: transparent;
    padding: 0;
  }
  .install-optout-section-constraints {
    border-left-color: var(--wr);
    background: var(--wr2);
  }
  .install-optout-section-advantages {
    border-left-color: var(--ok);
    background: var(--ok2);
  }
  .install-optout-section-title {
    margin: 0 0 var(--space-2);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--tx);
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .install-optout-section-body {
    margin: 0 0 var(--space-2);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }
  .install-optout-bullets {
    margin: 0;
    padding: 0 0 0 var(--space-4);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.6;
  }
  .install-optout-bullets li {
    margin: var(--space-1) 0;
  }
  .install-optout-where-label {
    margin: var(--space-3) 0 var(--space-1);
    font-size: var(--text-sm);
    color: var(--tx);
    font-weight: 500;
  }

  .install-optout-anchor {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    background: var(--bg3);
    border-radius: 6px;
    border: 1px dashed var(--bg2);
    flex-wrap: wrap;
    min-width: 0;
  }
  .install-optout-anchor-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: var(--tx2);
    transform: rotate(45deg);
  }
  .install-optout-anchor-text {
    margin: 0;
    flex: 1 1 200px;
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
    min-width: 0;
  }
  .install-optout-anchor-btn {
    flex: 0 0 auto;
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-sm);
    font-weight: 500;
    background: var(--bg2);
    color: var(--tx);
    border: 1px solid var(--bd);
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
    transition:
      background var(--t-fast),
      border-color var(--t-fast);
  }
  .install-optout-anchor-btn:hover {
    background: var(--bg);
    border-color: var(--ac);
  }

  /* Card 5 — danger zone */
  .install-danger-wrap {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
  }
  .install-danger-info {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    column-gap: var(--space-3);
    row-gap: var(--space-1);
    padding: var(--space-3);
    background: var(--bg3);
    border-radius: 6px;
    font-size: var(--text-sm);
    min-width: 0;
  }
  .install-danger-row {
    display: contents;
  }
  .install-danger-key {
    color: var(--tx2);
  }
  .install-danger-value {
    color: var(--tx);
    font-family: var(--font-mono);
    word-break: break-all;
    min-width: 0;
  }
  .install-danger-responsibility {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }
  .install-danger-export-hint {
    margin: var(--space-2) 0 0;
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-sm);
    color: var(--tx);
    line-height: 1.5;
    background: var(--wr2);
    border-left: 3px solid var(--wr);
    border-radius: var(--radius-sm);
  }
  .install-danger-actions {
    margin-top: var(--space-2);
  }

  /* Card 2 — check */
  .install-status-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
  }
  .install-status-dot {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
  }
  .install-status-dot.status-ok {
    background: var(--ok);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--ok) 25%, transparent);
  }
  .install-status-dot.status-partial {
    background: var(--wr);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--wr) 25%, transparent);
  }
  .install-status-dot.status-no_data {
    background: var(--dn);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--dn) 25%, transparent);
  }
  .install-status-label {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--tx);
  }
  .install-check-metrics {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: var(--space-2);
    column-gap: var(--space-3);
    margin: 0 0 var(--space-3);
    font-size: var(--text-sm);
  }
  .install-check-metrics dt {
    color: var(--tx2);
    margin: 0;
  }
  .install-check-metrics dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--tx);
    font-weight: 500;
  }
  .install-check-hint {
    margin: 0 0 var(--space-3);
    padding: var(--space-3);
    font-size: var(--text-xs);
    line-height: 1.5;
    color: var(--tx2);
    background: var(--bg);
    border: 1px solid var(--bd);
    border-radius: var(--r);
  }
  .install-check-hint.hint-ok {
    border-left: 3px solid var(--ok);
  }
  .install-check-hint.hint-partial {
    border-left: 3px solid var(--wr);
  }
  .install-check-hint.hint-no_data {
    border-left: 3px solid var(--dn);
  }
  .install-check-refresh {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 6px 12px;
    font-size: var(--text-xs);
    background: var(--bg2);
    color: var(--tx);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    cursor: pointer;
    transition: background var(--t-fast);
  }
  .install-check-refresh:hover {
    background: var(--bg3);
  }

  /* Events config — accordéon : card install-events retirée 2026-05-13
     (commit 9650a59), 19 sélecteurs orphelins purgés Sprint audit 2026-05-13. */

  /* Card 4 — troubleshoot */
  .install-trouble-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
  }
  .install-trouble-item {
    border: 1px solid var(--bd);
    border-radius: var(--r);
    background: var(--bg);
    min-width: 0;
  }
  .install-trouble-symptom {
    padding: var(--space-3);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--tx);
    cursor: pointer;
    list-style: none;
  }
  .install-trouble-symptom::-webkit-details-marker {
    display: none;
  }
  .install-trouble-symptom::before {
    content: '+';
    display: inline-block;
    width: 1em;
    font-weight: 600;
    color: var(--tx2);
  }
  .install-trouble-item[open] .install-trouble-symptom::before {
    content: '−';
  }
  .install-trouble-fix {
    margin: 0;
    padding: 0 var(--space-3) var(--space-3) calc(var(--space-3) + 1em);
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.6;
  }
  .install-trouble-contact {
    margin: var(--space-4) 0 0;
    font-size: var(--text-xs);
    color: var(--tx2);
    text-align: center;
    font-style: italic;
  }

  /* ============================================================
   Onglet Plateformes
   ============================================================ */

  .platforms-list-intro,
  .platforms-panel-intro {
    margin: 0 0 var(--space-3);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }
  .platforms-tabs-host {
    margin-bottom: var(--space-3);
  }
  .platforms-panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
  }
  .platforms-steps {
    margin: 0;
    padding-left: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--tx);
    line-height: 1.5;
  }
  .platforms-step {
    padding-left: var(--space-1);
  }
  .platforms-snippet {
    margin-top: var(--space-2);
  }
  .platforms-panel-note {
    margin: var(--space-2) 0 0;
    padding: var(--space-2) var(--space-3);
    background: var(--bg2);
    border-left: 3px solid var(--dn);
    border-radius: 4px;
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.5;
  }

  .wp-plugin-intro {
    margin: 0 0 var(--space-3);
    font-size: var(--text-sm);
    color: var(--tx);
    line-height: 1.5;
  }
  .wp-plugin-features {
    margin: 0 0 var(--space-3);
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .wp-plugin-features li {
    padding-left: var(--space-4);
    position: relative;
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.4;
  }
  .wp-plugin-features li::before {
    content: '✓';
    position: absolute;
    left: 0;
    color: var(--ok);
    font-weight: bold;
  }
  .wp-plugin-download {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: var(--dn);
    color: #fff;
    border-radius: var(--r);
    text-decoration: none;
    font-size: var(--text-sm);
    font-weight: 500;
    transition: opacity var(--t-fast);
  }
  .wp-plugin-download:hover {
    opacity: 0.9;
  }
  .wp-plugin-download:focus-visible {
    outline: 2px solid var(--dn);
    outline-offset: 2px;
  }
  .wp-plugin-steps-title {
    margin: var(--space-3) 0 var(--space-2);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--tx);
  }
  .wp-plugin-steps {
    margin: 0;
    padding-left: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }

  /* Card adblock-bypass */
  .adblock-why-title,
  .adblock-how-title,
  .adblock-steps-title {
    margin: var(--space-3) 0 var(--space-1);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--tx);
  }
  .adblock-why-title:first-child {
    margin-top: 0;
  }
  .adblock-why-body,
  .adblock-how-body {
    margin: 0 0 var(--space-2);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }
  .adblock-steps {
    margin: 0;
    padding-left: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--tx2);
    line-height: 1.5;
  }
  .adblock-activation {
    margin-top: var(--space-3);
    padding: var(--space-2) var(--space-3);
    background: var(--bg2);
    border-radius: var(--r);
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    color: var(--dn);
  }
  .adblock-activation-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: var(--text-xs);
    color: var(--tx);
    line-height: 1.5;
    min-width: 0;
  }
  .adblock-activation-body strong {
    color: var(--tx);
    font-weight: 600;
  }

  /* CTA en tête : redirige vers la doc /docs/<locale>/bypass-adblockers
   qui détaille les 5 recettes self-host UE-souveraines. */
  .adblock-doc-cta {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(16, 185, 129, 0.04));
    border: 1px solid rgba(16, 185, 129, 0.25);
    border-radius: var(--r);
    text-decoration: none;
    color: inherit;
    transition:
      border-color 0.15s ease,
      transform 0.15s ease;
  }
  .adblock-doc-cta:hover {
    border-color: rgba(16, 185, 129, 0.55);
    transform: translateY(-1px);
  }
  .adblock-doc-cta-icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(16, 185, 129, 0.15);
    color: var(--ac);
  }
  .adblock-doc-cta-text {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
  }
  .adblock-doc-cta-text strong {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--tx);
  }
  .adblock-doc-cta-text span {
    font-size: var(--text-xs);
    color: var(--tx2);
    line-height: 1.4;
  }
  .adblock-doc-cta-arrow {
    flex-shrink: 0;
    font-size: 18px;
    color: var(--ac);
    font-weight: 600;
  }

  /* --------------------------------------------------------------
   Insight Mistral — onglet Vue d'ensemble (à la demande)
   -------------------------------------------------------------- */
  .card[data-card='insight-mistral'] .card-body {
    padding: var(--space-3) var(--space-4);
  }
  /* Empty-state COMPACT — sprint 2026-05-12. Avant : grand hero ~350px qui
   poussait les KPIs sous le fold. Maintenant : bande horizontale ~56-64px
   (wrap sur mobile en 2 lignes max). Subtitle + CNIL note retirés, déjà
   accessibles via le tooltip "?" du header. */
  .insight-empty.insight-empty--compact {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
    padding: 0;
    text-align: left;
  }
  .insight-empty.insight-empty--compact .insight-empty-icon {
    color: var(--ac);
    background: color-mix(in srgb, var(--ac) 12%, transparent);
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }
  .insight-empty.insight-empty--compact .insight-empty-title {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--tx);
    margin: 0;
    flex: 1 1 auto;
    min-width: 0;
  }
  .insight-empty.insight-empty--compact .insight-controls {
    margin-top: 0;
    gap: var(--space-2);
  }
  .insight-empty.insight-empty--compact .insight-range-opt {
    padding: 4px 10px;
    font-size: var(--text-xs);
  }
  .insight-btn.insight-btn--compact {
    padding: 6px 14px;
    font-size: var(--text-sm);
  }

  /* Legacy empty (utilisé éventuellement par /audit ou un autre point d'entrée
   si quelqu'un re-déclenche renderEmpty sans --compact). Gardé pour rétro-
   compat mais valeurs raccourcies pour limiter la casse visuelle. */
  .insight-empty:not(.insight-empty--compact) {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-3);
  }
  .insight-empty:not(.insight-empty--compact) .insight-empty-icon {
    color: var(--ac);
    background: color-mix(in srgb, var(--ac) 12%, transparent);
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .insight-empty:not(.insight-empty--compact) .insight-empty-title {
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--tx);
    margin: 0;
  }
  .insight-empty-sub {
    font-size: var(--text-sm);
    color: var(--tx2);
    max-width: 56ch;
    margin: 0;
    line-height: 1.5;
  }
  .insight-controls {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    justify-content: center;
    margin-top: var(--space-2);
  }
  .insight-range {
    display: inline-flex;
    border: 1px solid var(--bd);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg);
  }
  .insight-range-opt {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    font-size: var(--text-sm);
    color: var(--tx2);
    cursor: pointer;
    transition:
      background var(--t-fast),
      color var(--t-fast);
  }
  .insight-range-opt input {
    display: none;
  }
  .insight-range-opt:hover {
    background: color-mix(in srgb, var(--ac) 6%, transparent);
  }
  .insight-range-opt.is-active {
    background: var(--ac);
    color: #fff;
    font-weight: 600;
  }
  .insight-cnil-note {
    font-size: 11.5px;
    color: var(--tx3);
    margin: var(--space-3) 0 0;
    max-width: 60ch;
    line-height: 1.5;
  }
  .insight-btn {
    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: 600;
    padding: 9px 18px;
    border-radius: var(--radius-md);
    cursor: pointer;
    border: 1px solid transparent;
    transition:
      background var(--t-fast),
      border-color var(--t-fast),
      color var(--t-fast);
  }
  .insight-btn-primary {
    background: var(--ac);
    color: #fff;
  }
  .insight-btn-primary:hover {
    filter: brightness(1.08);
  }
  .insight-btn-ghost {
    background: transparent;
    color: var(--tx2);
    border-color: var(--bd);
  }
  .insight-btn-ghost:hover {
    color: var(--tx);
    border-color: var(--tx3);
  }

  .insight-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-7) var(--space-4);
  }
  .insight-spinner {
    width: 28px;
    height: 28px;
    border: 2.5px solid color-mix(in srgb, var(--ac) 20%, transparent);
    border-top-color: var(--ac);
    border-radius: 50%;
    animation: insight-spin 0.8s linear infinite;
  }
  @keyframes insight-spin {
    to {
      transform: rotate(360deg);
    }
  }
  .insight-loading-text {
    font-size: var(--text-sm);
    color: var(--tx2);
    margin: 0;
  }

  .insight-result {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }
  .insight-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-3);
    font-size: 11.5px;
    color: var(--tx3);
  }
  .insight-meta-pill {
    background: color-mix(in srgb, var(--ac) 12%, transparent);
    color: var(--ac);
    font-weight: 600;
    padding: 3px 10px;
    border-radius: 999px;
    letter-spacing: 0.02em;
  }
  .insight-meta-time {
    font-variant-numeric: tabular-nums;
  }
  .insight-content {
    font-size: var(--text-md);
    line-height: 1.6;
    color: var(--tx);
  }
  .insight-content p {
    margin: 0 0 var(--space-3);
  }
  .insight-content p:last-child {
    margin-bottom: 0;
  }
  .insight-content strong {
    color: var(--tx);
    font-weight: 600;
  }
  .insight-content code {
    font-family: var(--font-mono);
    font-size: 0.9em;
    background: var(--bg);
    padding: 1px 6px;
    border-radius: 4px;
  }
  .insight-content ul {
    margin: 0 0 var(--space-3);
    padding-left: var(--space-5);
  }
  .insight-content li {
    margin-bottom: 4px;
  }
  .insight-actions {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
  }
  .insight-history {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px dashed var(--bd);
  }
  .insight-history-label {
    font-size: 11.5px;
    color: var(--tx3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
  .insight-history-chip {
    font-family: inherit;
    font-size: 12px;
    background: var(--bg);
    border: 1px solid var(--bd);
    color: var(--tx2);
    padding: 4px 10px;
    border-radius: 999px;
    cursor: pointer;
    transition:
      border-color var(--t-fast),
      color var(--t-fast);
  }
  .insight-history-chip:hover {
    border-color: var(--ac);
    color: var(--tx);
  }

  .insight-error {
    padding: var(--space-5);
    background: color-mix(in srgb, var(--dn) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--dn) 30%, transparent);
    border-radius: var(--radius-md);
    text-align: center;
  }
  .insight-error-title {
    font-size: var(--text-md);
    font-weight: 600;
    color: var(--dn);
    margin-bottom: var(--space-2);
  }
  .insight-error-msg {
    font-size: var(--text-sm);
    color: var(--tx2);
    margin-bottom: var(--space-3);
  }

  /* ============================================================
   Mobile (< 768 px) — overrides généraux
   ============================================================ */
  @media (max-width: 767.98px) {
    /* Tout passe en col-1 */
    [class*='col-'] {
      grid-column: span 1;
    }

    .tooltip-popover {
      left: var(--space-3);
      right: var(--space-3);
      max-width: none;
    }

    .behavior-selector-wrap {
      position: sticky;
      top: 0;
      z-index: 5;
    }
    /* UX 2026-05-14 — quand le pageSelector est intégré dans la MultiTabCard
       (cas par défaut depuis le sprint), il est déjà collé à la barre des
       sub-tabs. Le sticky devient inutile et créerait un chevauchement
       visuel avec la .multi-tab-bar lors du scroll. */
    .multi-tab-card-body > .behavior-selector-wrap {
      position: static;
    }

    .data-table {
      font-size: var(--text-xs);
    }
    .data-table thead th,
    .data-table tbody td {
      padding: var(--space-1) var(--space-2);
    }

    .geo-content-wrap {
      min-height: 320px;
    }
    .choropleth-full-svg {
      height: 320px;
    }

    /* --- Onglet Conformité — fixes mobile ---
     Les SVG du bandeau status sont hardcodés à 80×80 dans le JS — on les
     plafonne ici pour ne pas bouffer l'écran. La card passe en padding
     réduit pour gagner ~16 px utiles. */
    .card {
      padding: var(--space-4);
    }

    .compliance-status-banner {
      flex-direction: column;
      text-align: center;
      align-items: center;
      gap: var(--space-3);
      padding: var(--space-4);
    }
    .compliance-status-icon svg {
      width: 56px;
      height: 56px;
    }
    .compliance-status-text {
      align-items: center;
      width: 100%;
    }
    .compliance-status-attention {
      padding-left: 0;
      list-style-position: inside;
      text-align: left;
    }

    /* On garde flex-row + wrap au niveau du conteneur, mais on transforme
     chaque chip en mini-carte structurée (flag à gauche, label dessus,
     version dessous) pour rester lisible avec des refs longues comme
     "Codice Privacy art. 122 + décision GA 2022". */
    .compliance-referentials {
      padding: var(--space-3);
      gap: var(--space-2);
    }
    .compliance-referentials-list {
      flex-basis: 100%;
      min-width: 0;
      /* Grille 1 col en mobile : chaque chip prend toute la largeur,
       finie l'esthétique de pilule étirée. */
      display: grid;
      grid-template-columns: 1fr;
      gap: 6px;
    }
    .compliance-referential-chip {
      /* Bascule de "pilule inline" en "mini-carte". */
      display: grid;
      grid-template-columns: 24px minmax(0, 1fr);
      grid-template-rows: auto auto;
      align-items: center;
      column-gap: var(--space-3);
      row-gap: 0;
      padding: var(--space-2) var(--space-3);
      border-radius: var(--radius-sm);
      width: 100%;
      min-width: 0;
      /* Annule explicitement les héritages desktop (pilule, nowrap). */
      white-space: normal;
      line-height: 1.4;
    }
    .compliance-referential-flag {
      grid-row: 1 / span 2;
      align-self: center;
      font-size: 18px;
    }
    .compliance-referential-label {
      grid-column: 2;
      grid-row: 1;
      font-size: var(--text-xs);
      font-weight: 600;
      color: var(--tx);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .compliance-referential-version {
      grid-column: 2;
      grid-row: 2;
      font-size: 10.5px;
      color: var(--tx2);
      /* Les refs longues peuvent wrap sur 1-2 lignes maintenant qu'on est
       en bloc, plus en pilule inline. */
      overflow-wrap: anywhere;
    }
    .compliance-referentials-note {
      width: 100%;
      max-width: 100%;
      min-width: 0;
      overflow-wrap: anywhere;
    }

    /* Email DPO : 20 px mono casse sur petits écrans avec adresses longues. */
    .dpo-contact-email {
      font-size: var(--text-md);
    }
    .dpo-contact-section-label {
      font-size: 10px;
    }

    .compliance-download-btn {
      padding: var(--space-3);
    }
    .compliance-download-label {
      font-size: var(--text-sm);
    }

    .compliance-footer {
      padding: var(--space-4) var(--space-2);
    }
    .confirm-dialog {
      padding: var(--space-4);
    }

    /* ============================================================
     Sprint post-audit 2026-05-13 — fixes overflow horizontal mobile
     Retour Fred : "le dash va pas pas centre, les vue deborde sur
     la droite pas tous visible". Cibles 2026 : iPhone SE 375px,
     Android pliable 320px, tablette 768px en mode portrait étroit.
     ============================================================ */

    /* (1) Contenir tout contenu débordant à l'intérieur d'une card.
       overflow-x: clip ne crée pas de scrollbar inutile mais empêche
       qu'un enfant rebelle pousse la card hors viewport. data-table-scroll
       garde son auto en interne via une sous-règle plus spécifique. */
    .card,
    .card-body,
    .card-h {
      max-width: 100%;
      min-width: 0;
      overflow-x: clip;
    }
    .card .data-table-scroll,
    .card .multi-tab-bar,
    .card .install-code {
      overflow-x: auto;
    }

    /* (2) Truncate path/term plus agressivement (320 → min(220px,55vw))
       pour libérer de la place aux colonnes numériques. */
    .data-table .cell-text {
      max-width: min(220px, 55vw);
    }

    /* (3) Long URLs / hostnames / emails forcés à wrap plutôt que
       pousser la grille. */
    .cell-host,
    .cell-path,
    .dpo-contact-email,
    .install-snippet-code,
    .compliance-download-label {
      overflow-wrap: anywhere;
      word-break: break-word;
    }

    /* (4) Sections du dashboard : padding réduit + titre wrap. */
    .dashboard-section-title {
      font-size: 15px;
      overflow-wrap: anywhere;
    }

    /* (5) TOC sticky en bar horizontale : padding réduit + scroll plus net. */
    .dashboard-toc nav {
      padding: var(--space-2) var(--space-3);
      gap: 2px;
    }
    .dashboard-toc-link {
      padding: 4px 8px;
      font-size: 12px;
    }

    /* (6) MultiTabCard host : padding latéral réduit pour gagner ~16 px
       utiles à droite des tables et charts. */
    .multi-tab-host {
      padding: var(--space-3) var(--space-2) var(--space-4);
    }
    .multi-tab-bar {
      padding: 0 var(--space-2);
    }
    .multi-tab-btn {
      padding: 6px 10px;
      font-size: 12px;
    }

    /* (7) Insight Mistral plein largeur — wrap des liens longs. */
    .card[data-card='insight-mistral'] .card-body {
      overflow-wrap: anywhere;
    }
  }

  /* ============================================================
   Très petit (≤ 375 px : iPhone SE, vieux Android) — passes serrées
   ============================================================ */
  @media (max-width: 375px) {
    .card {
      padding: var(--space-3);
    }
    .dashboard-section-title {
      font-size: 14px;
    }
    .data-table .cell-text {
      max-width: 45vw;
    }
    .multi-tab-btn {
      padding: 6px 8px;
      font-size: 11.5px;
    }
  }

  /* ============================================================================
   Formulaires intégrés dans les cards dashboard (DPA signature, futures cards
   avec saisie utilisateur). Réutilise le naming login-* (cohérent avec
   public/css/login.css) pour éviter d'inventer un système parallèle ; les
   règles ci-dessous sont la copie des form-only de login.css, scopées au
   dashboard. Pas de globaux html/body (la page dashboard a ses propres règles).
   ============================================================================ */

  .login-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
  }

  .login-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--tx2);
  }

  .login-field input[type='text'],
  .login-field input[type='email'],
  .login-field input[type='password'],
  .login-field input[type='number'] {
    font-family: var(--font-ui);
    font-size: var(--text-base);
    color: var(--tx);
    background: var(--bg);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    padding: var(--space-3);
    outline: none;
    transition:
      border-color var(--t-fast),
      box-shadow var(--t-fast);
  }
  .login-field input[type='text']:focus,
  .login-field input[type='email']:focus,
  .login-field input[type='password']:focus,
  .login-field input[type='number']:focus {
    border-color: var(--ac);
    box-shadow: 0 0 0 3px var(--ac2);
  }

  /* Bordure rouge pour les inputs/checkbox en faute après un submit invalide.
   Retirée à la prochaine modification du champ (cf. card dpa-signature.js).  */
  .login-field input.is-error,
  .login-field input.is-error:focus,
  .login-checkbox.is-error {
    border-color: var(--dn);
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15);
  }
  .login-checkbox.is-error {
    /* checkbox elle-même n'a pas de bordure visible — on stylise le label
     avec une couleur rouge pour signaler l'erreur. */
    color: var(--dn);
    box-shadow: none;
  }

  /* Bloc radios horizontal (locale FR/EN, etc.) — flex inline avec gap. */
  .login-field-radios {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
  }
  .login-field-radios label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    cursor: pointer;
    color: var(--tx);
  }

  .login-error {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--dn);
  }

  .login-submit {
    margin-top: var(--space-2);
    padding: var(--space-3) var(--space-4);
    font-family: var(--font-ui);
    font-size: var(--text-base);
    font-weight: 500;
    color: #06281e;
    background: var(--ac);
    border: 0;
    border-radius: var(--r);
    cursor: pointer;
    transition: filter var(--t-fast);
  }
  .light .login-submit {
    color: #ffffff;
  }
  .login-submit:hover:not(:disabled) {
    filter: brightness(1.08);
  }
  .login-submit:disabled {
    opacity: 0.6;
    cursor: default;
  }

  /* Bouton secondaire (ex: "Prévisualiser le DPA") — même padding que submit
   mais transparent + bord, pour ne pas concurrencer l'action principale. */
  .login-secondary {
    margin-top: var(--space-2);
    padding: var(--space-3) var(--space-4);
    font-family: var(--font-ui);
    font-size: var(--text-base);
    font-weight: 500;
    color: var(--tx);
    background: transparent;
    border: 1px solid var(--bd);
    border-radius: var(--r);
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    transition:
      border-color var(--t-fast),
      background var(--t-fast);
  }
  .login-secondary:hover {
    border-color: var(--ac);
    background: var(--ac2);
  }

  /* Checkbox + label inline (ex: "J'accepte les termes du DPA"). */
  .login-checkbox {
    display: flex;
    gap: var(--space-2);
    align-items: flex-start;
    font-size: var(--text-sm);
    color: var(--tx2);
    cursor: pointer;
    line-height: 1.5;
  }
  .login-checkbox input[type='checkbox'] {
    margin-top: 2px;
    flex-shrink: 0;
    cursor: pointer;
  }

  /* Section repliable « Signer à nouveau » — encadré discret avec le formulaire
   dedans, déployable au clic. Évite que le formulaire de re-signature occupe
   toute la card quand le DPA est déjà signé. */
  .dpa-signature-resign {
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--bd);
    border-radius: var(--r);
    background: var(--bg);
  }
  .dpa-signature-resign > summary {
    cursor: pointer;
    font-size: var(--text-sm);
    color: var(--tx2);
    padding: var(--space-1) 0;
    list-style: none;
    position: relative;
    padding-left: var(--space-5);
  }
  .dpa-signature-resign > summary::-webkit-details-marker {
    display: none;
  }
  .dpa-signature-resign > summary::before {
    content: '▸';
    position: absolute;
    left: 0;
    transition: transform var(--t-fast);
  }
  .dpa-signature-resign[open] > summary::before {
    transform: rotate(90deg);
  }
  .dpa-signature-resign[open] > summary {
    color: var(--tx);
  }
  .dpa-signature-resign > .login-form {
    margin-top: var(--space-3);
  }

  /* ============================================================================
   * MultiTabCard (Sprint refonte dashboard 2026-05-13)
   * ============================================================================
   * Composite card avec sous-onglets internes. Le tooltip parent informe
   * sur la section globale ; chaque sous-card garde son tooltip + son
   * CSV-export individuels pour le drill-down. On masque uniquement
   * le titre des sous-cards (redondant avec le label du sous-onglet).
   */
  .multi-tab-card-body {
    padding: 0;
  }
  /* UX 2026-05-14 (v4) — sur les cards multi-onglets (Contenus, Comportement,
     Provenance, Audience, Technique), le titre de card agit comme étiquette
     de section et les sub-tabs sont l'interaction principale : on les colle
     visuellement.

     4 sources d'espace cumulées (v1→v3 ont traité les 3 premières) :
     1. `.card { min-height: 100px }` (ligne ~104) — réservation skeleton.
        Inutile ici : les sous-cards masquent leur skeleton. → min-height: 0.
     2. `.card-h { align-items: center }` — le titre est centré verticalement
        dans un header qui prend la hauteur du tooltip/bouton CSV (plus hauts
        que le texte), créant ~6-8px de vide sous le texte. → align-items: end.
     3. `.multi-tab-bar { padding-top }` — éliminé (0). Les boutons gardent
        leur padding interne (8px) qui suffit visuellement.
     4. v4 (cause racine résiduelle) — `line-height` hérité du body (~1.5)
        ajoute ~3-4 px de line-gap invisible sous les glyphes du titre ET
        au-dessus des glyphes des boutons d'onglet. C'est ce vide-fantôme,
        invisible dans l'inspecteur quand on regarde padding/margin, qui
        crée la perception "espace trop grand" après les 3 fixes précédents.
        On force line-height: 1 sur card-title et multi-tab-btn (tous deux
        en white-space: nowrap, donc safe), ET on réduit le padding-top
        du multi-tab-btn de 8px → 4px pour fermer le résidu.

     Total espace vertical entre glyphes du titre et glyphes "Canaux" :
     ~4 px (uniquement le padding-top des boutons), perçu comme collé. */
  .card:has(> .card-body.multi-tab-card-body) {
    min-height: 0;
  }
  .card:has(> .card-body.multi-tab-card-body) .card-h {
    margin-bottom: 0;
    align-items: end;
  }
  .card:has(> .card-body.multi-tab-card-body) .card-title {
    line-height: 1;
  }
  .card:has(> .card-body.multi-tab-card-body) .multi-tab-btn {
    line-height: 1;
    padding-top: 4px;
  }
  .multi-tab-bar {
    display: flex;
    gap: 4px;
    overflow-x: auto;
    padding: 0 var(--space-4);
    border-bottom: 1px solid var(--bd);
    scrollbar-width: thin;
  }
  /* Sprint responsive 2026-05-15 — sur écrans tactiles (mobile, tablette),
     la scrollbar par défaut n'apparaît qu'au moment du scroll actif et
     disparaît ensuite → impossible de deviner que les sub-tabs sont
     scrollables (ex: Canaux / Sites référents / Trafic IA débordent sur
     iPhone). On force une scrollbar fine permanente sur les devices
     hover:none, avec un styling discret cohérent avec la border-bottom. */
  @media (hover: none) {
    .multi-tab-bar {
      scrollbar-color: var(--bd2) transparent;
    }
    .multi-tab-bar::-webkit-scrollbar {
      height: 4px;
      -webkit-appearance: none;
      display: block;
    }
    .multi-tab-bar::-webkit-scrollbar-track {
      background: transparent;
    }
    .multi-tab-bar::-webkit-scrollbar-thumb {
      background-color: var(--bd2);
      border-radius: 2px;
    }
  }
  .multi-tab-btn {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--tx2);
    padding: 8px 14px;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    border-radius: 6px 6px 0 0;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
    transition:
      color var(--t-fast),
      border-color var(--t-fast),
      background var(--t-fast);
  }
  .multi-tab-btn:hover {
    color: var(--tx);
    background: var(--bg2);
  }
  .multi-tab-btn.is-active {
    color: var(--ac);
    border-bottom-color: var(--ac);
  }
  .multi-tab-btn:focus-visible {
    outline: 2px solid var(--ac);
    outline-offset: -2px;
  }
  .multi-tab-host {
    padding: var(--space-3) var(--space-4) var(--space-4);
  }
  /* Sous-card hébergée dans un MultiTabCard : on retire le wrapping
     visuel (border, fond) et on masque le titre (redondant avec le
     label du sous-onglet). Le tooltip + CSV-export restent visibles
     dans le header. */
  .multi-tab-host > .card {
    border: 0;
    background: transparent;
    margin: 0;
    padding: 0;
    box-shadow: none;
  }
  .multi-tab-host > .card > .card-h {
    padding: 0 0 var(--space-2);
    border-bottom: 0;
  }
  .multi-tab-host > .card > .card-h .card-title {
    display: none;
  }
  .multi-tab-host > .card > .card-body {
    padding: 0;
  }
  /* Sprint refonte 2026-05-13 — bug fix flicker : désactiver l'animation
     skeleton-shimmer pour les sous-cards d'un MultiTabCard. Avec le re-mount
     instantané au switch de tab + fetch ~200-500 ms, le shimmer en boucle
     donnait l'impression de "barres horizontales qui clignottent".
     Update v2 (retour Fred "barres grises restent") : on masque
     COMPLÈTEMENT le skeleton dans les sous-cards. Le fetch est court
     (<500 ms en général) ; pas de skeleton = pas de flash visuel
     intermédiaire entre les switches de tab. La sub-card affiche son
     contenu directement quand prêt. */
  .multi-tab-host .card-skeleton {
    display: none;
  }

  /* Wrapper pleine largeur dans une dashboard-section (hors grid 4-cols).
     Utilisé pour l'Insight Mistral qui a son propre layout interne. */
  .dashboard-section-fullwidth {
    width: 100%;
    margin-bottom: var(--space-4);
  }
  .dashboard-section-fullwidth > .card {
    width: 100%;
  }

  /* ============================================================================
   * Dashboard unifié (Sprint refonte 2026-05-13)
   * ============================================================================
   * Layout = grid 2 colonnes : zone principale + TOC sticky à droite.
   * Mobile : TOC se replie au-dessus en barre horizontale scrollable.
   */
  /* Sprint UX mobile 2026-05-14 — minmax(0, 1fr) au lieu de 1fr : sans le min=0,
     un grid-item dont le contenu intrinsèque (TOC nav avec 6 liens en nowrap)
     force la piste plus large que le viewport — bug observé sur ≤ 375 px où
     .dashboard-main et .dashboard-toc rendaient à 467 px dans un parent 351 px,
     le surplus était clippé silencieusement par #tab-content. */
  .dashboard-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 180px;
    gap: var(--space-5);
    align-items: start;
  }
  .dashboard-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
  }
  .dashboard-section {
    scroll-margin-top: 80px;
    min-width: 0;
  }
  .dashboard-section-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--tx);
    margin: 0 0 var(--space-3);
    letter-spacing: -0.01em;
  }
  .dashboard-toc {
    position: sticky;
    top: var(--space-4);
    align-self: start;
    /* min-width: 0 — garde-fou mobile : la TOC a un overflow-x: auto interne,
       ne doit pas forcer son grid-track plus large que le viewport. */
    min-width: 0;
  }
  .dashboard-toc nav {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--space-3);
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: 8px;
    font-size: 13px;
  }
  .dashboard-toc-link {
    color: var(--tx2);
    text-decoration: none;
    padding: 6px 10px;
    border-radius: 4px;
    border-left: 2px solid transparent;
    transition:
      color var(--t-fast),
      background var(--t-fast),
      border-color var(--t-fast);
  }
  .dashboard-toc-link:hover {
    color: var(--tx);
    background: var(--bg);
  }
  .dashboard-toc-link.is-active {
    color: var(--ac);
    border-left-color: var(--ac);
    background: var(--bg);
  }
  @media (max-width: 1024px) {
    .dashboard-layout {
      /* minmax(0, 1fr) — sans le min=0, l'item dont le contenu (.dashboard-toc
         nav avec 6 liens nowrap) est plus large que le viewport force la piste
         à grandir et fait déborder #tab-content latéralement. */
      grid-template-columns: minmax(0, 1fr);
    }
    .dashboard-toc {
      position: relative;
      top: 0;
      order: -1;
      /* max-width: 100% — verrouille la TOC à la largeur du grid-track, son
         <nav> interne avec overflow-x: auto prendra le scroll horizontal. */
      max-width: 100%;
    }
    .dashboard-toc nav {
      flex-direction: row;
      overflow-x: auto;
      scrollbar-width: thin;
    }
    .dashboard-toc-link {
      border-left: 0;
      border-bottom: 2px solid transparent;
      white-space: nowrap;
    }
    .dashboard-toc-link.is-active {
      border-left: 0;
      border-bottom-color: var(--ac);
    }
  }

  /* Bouton flottant "remonter en haut" (Sprint refonte fix 2026-05-13).
     Visible uniquement quand scrollY > 400 (toggle via .is-visible).
     Position bas-droite, fade in/out smooth. */
  .dashboard-scroll-top {
    position: fixed;
    bottom: 24px;
    right: 24px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--bg2);
    border: 1px solid var(--bd);
    color: var(--tx2);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow-2);
    opacity: 0;
    pointer-events: none;
    transform: translateY(8px);
    transition:
      opacity var(--t-base),
      transform var(--t-base),
      color var(--t-fast),
      background var(--t-fast);
    z-index: 100;
  }
  .dashboard-scroll-top.is-visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
  }
  .dashboard-scroll-top:hover {
    color: var(--ac);
    background: var(--bg);
  }
  .dashboard-scroll-top:focus-visible {
    outline: 2px solid var(--ac);
    outline-offset: 2px;
  }

  /* --------------------------------------------------------------
     Click heatmap (Comportement) — sprint heatmap visuel 2026-05-14
     -------------------------------------------------------------- */
  .click-heatmap-wrap {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }

  .click-heatmap-stage {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: 8px;
    overflow: hidden;
  }

  .click-heatmap-wireframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }
  .click-heatmap-wireframe-band {
    fill: var(--bg3);
    fill-opacity: 0.55;
    stroke: var(--bd);
    stroke-width: 0.15;
    stroke-dasharray: 0.6 0.4;
  }

  .click-heatmap-zone-labels {
    position: absolute;
    inset: 0;
    pointer-events: none;
  }
  .click-heatmap-zone-label {
    position: absolute;
    right: 8px;
    transform: translateY(-50%);
    font-size: 9px;
    font-family: var(--font-mono);
    color: var(--tx3);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.55;
  }

  .click-heatmap-grid {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    grid-template-rows: repeat(10, 1fr);
    gap: 2px;
    padding: 4px;
  }
  .click-heatmap-cell {
    border-radius: 3px;
    transition: transform 80ms var(--ease);
  }
  .click-heatmap-cell-empty {
    background: transparent;
  }
  .click-heatmap-cell-masked {
    background: repeating-linear-gradient(
      45deg,
      rgba(139, 145, 154, 0.22),
      rgba(139, 145, 154, 0.22) 3px,
      transparent 3px,
      transparent 6px
    );
  }
  .click-heatmap-cell-value:hover,
  .click-heatmap-cell-masked:hover {
    transform: scale(1.08);
    cursor: crosshair;
  }

  .click-heatmap-axis {
    position: absolute;
    font-size: 9px;
    font-family: var(--font-mono);
    color: var(--tx3);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    pointer-events: none;
    background: var(--bg2);
    padding: 1px 5px;
    border-radius: 2px;
    border: 1px solid var(--bd);
    line-height: 1.4;
  }
  .click-heatmap-axis-top {
    top: 4px;
    left: 50%;
    transform: translateX(-50%);
  }
  .click-heatmap-axis-bottom {
    bottom: 4px;
    left: 50%;
    transform: translateX(-50%);
  }
  .click-heatmap-axis-left {
    top: 50%;
    left: 4px;
    writing-mode: vertical-rl;
    transform: translateY(-50%) rotate(180deg);
  }
  .click-heatmap-axis-right {
    top: 50%;
    right: 4px;
    writing-mode: vertical-rl;
    transform: translateY(-50%);
  }

  .click-heatmap-legend {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    color: var(--tx3);
    flex-wrap: wrap;
  }
  .click-heatmap-legend-label {
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 10px;
    color: var(--tx3);
  }
  .click-heatmap-legend-min,
  .click-heatmap-legend-max {
    font-family: var(--font-mono);
    color: var(--tx2);
    font-variant-numeric: tabular-nums;
  }
  .click-heatmap-legend-bar {
    flex: 1 1 120px;
    height: 10px;
    border-radius: 5px;
    max-width: 220px;
    border: 1px solid var(--bd);
    background: linear-gradient(
      to right,
      rgba(16, 185, 129, 0.22) 0%,
      rgba(245, 158, 11, 0.6) 50%,
      rgba(239, 68, 68, 0.95) 100%
    );
  }
  .click-heatmap-legend-masked {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
  }
  .click-heatmap-legend-masked::before {
    content: '';
    display: inline-block;
    width: 16px;
    height: 10px;
    border-radius: 2px;
    border: 1px solid var(--bd);
    background: repeating-linear-gradient(
      45deg,
      rgba(139, 145, 154, 0.22),
      rgba(139, 145, 154, 0.22) 3px,
      transparent 3px,
      transparent 6px
    );
  }

  .click-heatmap-tooltip {
    position: absolute;
    z-index: 100;
    min-width: 140px;
    max-width: 240px;
    padding: 8px 10px;
    background: var(--bg2);
    border: 1px solid var(--bd);
    border-radius: 8px;
    box-shadow: var(--shadow-3);
    font-family: var(--font-ui);
    font-size: var(--text-sm);
    color: var(--tx);
    pointer-events: none;
    animation: cht-tip-in 100ms var(--ease);
  }
  @keyframes cht-tip-in {
    from {
      opacity: 0;
      transform: translateY(-2px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  .click-heatmap-tooltip .cht-tip-pos {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--tx3);
    margin-bottom: 2px;
    font-family: var(--font-mono);
  }
  .click-heatmap-tooltip .cht-tip-val {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }
  .click-heatmap-tooltip .cht-tip-val-masked {
    color: var(--tx2);
    font-weight: 500;
    font-style: italic;
  }
  .click-heatmap-tooltip .cht-tip-val-empty {
    color: var(--tx3);
    font-weight: 500;
  }

  @media (max-width: 640px) {
    .click-heatmap-axis-left,
    .click-heatmap-axis-right {
      display: none;
    }
    .click-heatmap-zone-label {
      font-size: 8px;
    }
    .click-heatmap-legend-masked {
      margin-left: 0;
    }
  }
} /* end @layer components */
