  /* Tableaux de résultats : sql_results sous la réponse et cartes de
     données brutes du relais direct. Extrait d'app.css avec app-table.js
     (cliquet de taille du statique). */
  .msg .sql-results {
    margin-top: 0.6rem;
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
  }
  .msg .sql-results table {
    border-collapse: collapse;
    width: 100%;
    font-size: 0.85rem;
  }
  .msg .sql-results th,
  .msg .sql-results td {
    padding: 0.35rem 0.6rem;
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
  }
  .msg .sql-results th { background: var(--accent-soft); font-weight: 650; }
  .msg .sql-results tr:last-child td { border-bottom: none; }
  .msg .sql-results-note {
    padding: 0.3rem 0.6rem;
    color: var(--muted);
    font-size: 0.8rem;
  }
  /* Cartes de données brutes (relais direct) : mêmes tableaux que
     sql-results, plus un bandeau-titre par service. */
  .msg .raw-results { margin-top: 0.6rem; }
  .msg .raw-results .raw-card {
    margin-top: 0.6rem;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    overflow: hidden;
  }
  .msg .raw-results .raw-card-title {
    padding: 0.35rem 0.6rem;
    font-size: 0.8rem;
    font-weight: 650;
    color: var(--muted);
    background: var(--accent-soft);
    border-bottom: 1px solid var(--border);
  }
  .msg .raw-results .sql-results {
    margin-top: 0;
    border: none;
    border-radius: 0;
  }
  .msg .raw-results .raw-kv {
    margin: 0;
    padding: 0.35rem 0.6rem;
    font-size: 0.85rem;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.15rem 0.8rem;
  }
  .msg .raw-results .raw-kv dt { color: var(--muted); font-weight: 650; }
  .msg .raw-results .raw-kv dd { margin: 0; overflow-wrap: anywhere; }
  .msg .raw-results .raw-text {
    margin: 0;
    padding: 0.5rem 0.6rem;
    font-size: 0.85rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-height: 60vh;
    max-height: 60dvh;
    overflow-y: auto;
  }

  /* Une ligne s'ouvre en fiche : le curseur et l'état actif le disent, et
     sur écran tactile la ligne devient une cible de 44px. */
  .msg .sql-results tbody tr { cursor: pointer; }
  @media (hover: hover) {
    .msg .sql-results tbody tr:hover td { background: var(--accent-soft); }
  }
  .msg .sql-results tbody tr:active td { background: var(--accent-soft); }
  .msg .sql-results tbody tr:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
  }
  /* Le conseil ne se montre que sur un tableau qui déborde (classe posée à
     la mesure, app-table.js) : ailleurs il n'y a rien à aller chercher. */
  .msg .sql-results-hint { display: none; }
  .msg .sql-results.scrolls .sql-results-hint {
    display: block;
    position: sticky;
    left: 0;
    padding: 0.3rem 0.6rem;
    color: var(--muted);
    font-size: 0.75rem;
    border-top: 1px solid var(--border);
  }

  /* --- Fiche d'une ligne : la lecture verticale, sans scroll horizontal. --- */
  #row-dialog { width: min(94vw, 520px); padding: 1rem 1.1rem; }
  .row-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
  }
  .row-head h2 { margin: 0; overflow-wrap: anywhere; }
  /* dialog button vaut width:100% : le « fermer » du bandeau reprend sa
     largeur naturelle. */
  #row-dialog .row-head button { width: auto; flex: 0 0 auto; }
  .row-fields {
    margin: 0;
    max-height: 60vh;
    max-height: 60dvh;
    overflow-y: auto;
    font-size: 0.9rem;
  }
  .row-fields dt {
    color: var(--muted);
    font-size: 0.75rem;
    font-weight: 650;
    text-transform: uppercase;
    letter-spacing: 0.03em;
  }
  .row-fields dd {
    margin: 0 0 0.7rem;
    /* Le point de la fiche : une valeur longue passe à la ligne au lieu de
       pousser la colonne hors de l'écran. */
    overflow-wrap: anywhere;
    white-space: pre-wrap;
  }
  .row-fields dd.empty { color: var(--muted); }
  /* Aller-retour vers le texte complet : l'extrait reste lisible, il pâlit
     seulement — le vider ferait clignoter la fiche pour rien. */
  .row-fields.loading { opacity: 0.55; }
  .row-fields.loading dd { transition: opacity 0.15s; }
  .row-nav {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.9rem;
  }
  /* dialog button vaut width:100% par défaut : ici trois boutons se partagent
     la ligne, les flèches restent au gabarit du doigt. */
  #row-dialog .row-nav button {
    width: auto;
    flex: 0 0 auto;
    min-width: 44px;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
  }
  #row-dialog .row-nav button:disabled { opacity: 0.4; cursor: default; }
  #row-dialog #row-copy { flex: 1 1 auto; }

  @media (pointer: coarse) {
    .msg .sql-results td { padding-top: 0.65rem; padding-bottom: 0.65rem; }
    #row-dialog .row-nav button { min-height: 44px; }
  }
