/* public/shared/ui/components.css — bibliothèque de composants partagés
   (lot A, tâche 3). Uniquement des variables de tokens.css — aucune
   couleur littérale.

   Deux familles de règles ici :
   1. Styles d'éléments de base (button/input/select/textarea/a/h1/h2) et
      classes de compatibilité (.pill/.ok/.bad/.warn/.row) : tokens.css
      (tâche 1) a retiré le <style> inline de dashboard.html qui portait
      ces règles ; les pages existantes (public/dashboard/pages/**) les
      utilisent encore telles quelles — sans ce bloc elles resteraient sans
      style jusqu'à leur migration vers les classes .ui-*.
   2. Les composants .ui-* consommés par dialogs.js / states.js / badge.js
      et par les tâches suivantes (4-18). */

/* ---------- Éléments de base ---------- */
button {
  font-family: inherit; font-size: var(--font-3); font-weight: 600;
  background: var(--brand); color: var(--on-brand); border: 0;
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3);
  cursor: pointer; margin: var(--space-1) var(--space-1) 0 0;
}
button:hover { filter: brightness(1.08); }
button:disabled { opacity: .5; cursor: not-allowed; filter: none; }
button.secondary { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); }
button.danger { background: var(--bad); color: var(--on-brand); }

input, select, textarea {
  font-family: inherit; font-size: var(--font-3); width: 100%;
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); margin: var(--space-2) 0;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}

a { color: var(--brand); }

h1 { margin: 0; font-size: var(--font-6); letter-spacing: -.02em; }
h2 { margin: 0 0 var(--space-3); font-size: var(--font-4); letter-spacing: .02em; }

.row { padding: var(--space-3) 0; border-top: 1px solid var(--border); }
.row:first-child { border-top: 0; padding-top: 0; }

.pill {
  display: inline-flex; align-items: center; gap: var(--space-1);
  border-radius: 999px; padding: var(--space-1) var(--space-2);
  font-size: var(--font-1); border: 1px solid var(--border); color: var(--muted);
}
.ok { color: var(--ok); }
.bad { color: var(--bad); }
.warn { color: var(--warn); }

/* ---------- Calques (tiroir / modale) ---------- */
.ui-layer {
  position: fixed; inset: 0; z-index: 1000; display: flex;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
}
.ui-layer-drawer { justify-content: flex-end; }
.ui-layer-modal { align-items: center; justify-content: center; padding: var(--space-4); }

.ui-drawer {
  display: flex; flex-direction: column; height: 100%; max-width: 100%;
  background: var(--panel); border-left: 1px solid var(--border); box-shadow: var(--shadow);
}
.ui-drawer-left { border-left: 0; border-right: 1px solid var(--border); order: -1; }
.ui-drawer > header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4); border-bottom: 1px solid var(--border); flex: 0 0 auto;
}
.ui-drawer > header h2 { margin: 0; }
.ui-drawer-body { padding: var(--space-4); overflow-y: auto; flex: 1 1 auto; }
@media (max-width: 720px) { .ui-drawer { width: 100% !important; max-width: 100vw; } }

.ui-modal {
  display: flex; flex-direction: column; width: 100%; max-width: 520px; max-height: 90vh;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: var(--space-4); gap: var(--space-3); overflow: hidden;
}
.ui-modal h2 { margin: 0; }
.ui-modal-body { overflow-y: auto; flex: 1 1 auto; }
.ui-modal footer { display: flex; justify-content: flex-end; gap: var(--space-2); }

.ui-icon-btn {
  background: transparent; color: var(--muted); border: 0; border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2); cursor: pointer; font-size: var(--font-3); margin: 0;
}
.ui-icon-btn:hover { color: var(--text); background: var(--panel-2); }

/* ---------- Boutons .ui-btn ---------- */
.ui-btn {
  font-family: inherit; font-size: var(--font-3); font-weight: 600; cursor: pointer;
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); border: 1px solid transparent;
  margin: 0;
}
.ui-btn-default { background: var(--panel-2); color: var(--text); border-color: var(--border); }
.ui-btn-primary { background: var(--brand); color: var(--on-brand); }
.ui-btn-danger { background: var(--bad); color: var(--on-brand); }
.ui-btn:hover { filter: brightness(1.08); }
.ui-btn:disabled { opacity: .5; cursor: not-allowed; filter: none; }

/* ---------- Badge ---------- */
.ui-badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  border-radius: 999px; padding: var(--space-1) var(--space-2);
  font-size: var(--font-1); font-weight: 600; border: 1px solid var(--border);
}
.ui-badge-ok { color: var(--ok); border-color: var(--ok); }
.ui-badge-warn { color: var(--warn); border-color: var(--warn); }
.ui-badge-bad { color: var(--bad); border-color: var(--bad); }
.ui-badge-info { color: var(--info); border-color: var(--info); }
.ui-badge-neutral { color: var(--muted); border-color: var(--border); }

/* ---------- États ---------- */
.ui-empty, .ui-error {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-2);
  padding: var(--space-6) var(--space-4); color: var(--muted);
}
.ui-empty h3 { margin: 0; color: var(--text); font-size: var(--font-4); }
.ui-error p { margin: 0; color: var(--bad); }

.ui-skeleton { display: flex; flex-direction: column; gap: var(--space-2); }
.ui-skeleton-row {
  height: var(--space-6); border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--panel-2) 25%, var(--panel) 50%, var(--panel-2) 75%);
  background-size: 200% 100%; animation: ui-skeleton-pulse 1.4s ease-in-out infinite;
}
@keyframes ui-skeleton-pulse { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ---------- Tuile KPI ---------- */
.ui-kpi {
  display: flex; flex-direction: column; gap: var(--space-1);
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-4);
}
.ui-kpi-label { color: var(--muted); font-size: var(--font-2); }
.ui-kpi-value { color: var(--text); font-size: var(--font-6); font-weight: 700; letter-spacing: -.02em; }
.ui-kpi-delta { font-size: var(--font-2); font-weight: 600; }
.ui-kpi-delta-up { color: var(--ok); }
.ui-kpi-delta-down { color: var(--bad); }
.ui-kpi-delta-flat { color: var(--muted); }
.ui-kpi-hint { color: var(--muted); font-size: var(--font-1); }
/* Lot B, tâche 10 — les deux tons d'ALERTE d'une tuile (le mur de plateau les
   pose sur « aucun opérateur disponible » et « une prise en main attend »).
   Ils étaient dessinés dans la feuille d'un seul écran ; ils vivent avec la
   tuile, comme sa grille juste en dessous. */
.ui-kpi-warn { border-color: var(--warn); }
.ui-kpi-crit { border-color: var(--bad); }
/* La grille des tuiles. Elle vit ICI, avec la tuile qu'elle dispose : posée
   dans la feuille d'un seul écran, elle serait à réécrire au suivant — ce qui
   était déjà arrivé (`shell-kpi-grid`, shell.css). Sans elle, `ui-kpi-grid`
   était une classe déclarée par le rendu et jamais dessinée : les neuf tuiles
   des Rapports s'empilaient en colonne pleine largeur. */
.ui-kpi-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-3);
}

/* ---------- Formulaire ---------- */
.ui-form { display: flex; flex-direction: column; gap: var(--space-3); }
.ui-field { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--font-2); color: var(--muted); }
/* Une case à cocher se lit EN LIGNE (case puis libellé), pas empilée : voir la
   note de buildField() dans public/shared/ui/form.js. */
.ui-field-check { flex-direction: row; align-items: center; gap: var(--space-2); }
/* Lot B, tâche 12 — le RADIO comme la case à cocher. La règle globale
   `input, select, textarea { width: 100% }` (ligne 27) s'applique aussi aux
   ronds de choix : un radio dans un `.ui-field-check` s'étirait sur toute la
   ligne et projetait son libellé au bord opposé. « Qui appelle ? » sur la fiche
   campagne montrait trois ronds empilés au milieu et « IA / Humain / Hybride »
   contre le bord droit, sans qu'on puisse apparier les deux. */
.ui-field-check input[type="checkbox"], .ui-field-check input[type="radio"] { width: auto; flex: 0 0 auto; }
.ui-field-check > span { color: var(--text); }
.ui-field input, .ui-field select, .ui-field textarea { margin: 0; }

/* ---------- Formulaire générique (tâche 5) ---------- */
.ui-field-hint { color: var(--muted); font-size: var(--font-1); }
.ui-field-error { color: var(--bad); font-size: var(--font-1); }
.ui-field input[aria-invalid="true"], .ui-field select[aria-invalid="true"], .ui-field textarea[aria-invalid="true"] {
  border-color: var(--bad); outline-color: var(--bad);
}
.ui-form-error {
  color: var(--bad); font-size: var(--font-2); background: color-mix(in srgb, var(--bad) 12%, transparent);
  border: 1px solid var(--bad); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3);
}
.ui-form-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }

/* ---------- Curseur (lot B, tâche 8) ----------
   Le curseur et sa valeur sont UN champ : le libellé au-dessus, la piste et le
   chiffre côte à côte en dessous — sinon le chiffre s'éloigne de la poignée
   qu'il décrit. La piste prend la place restante et le chiffre garde une
   largeur fixe, pour qu'il ne fasse pas sauter la piste à chaque dizaine. Le
   remplissage vertical donne à la poignée une zone tactile visable au doigt.
   Tokens seulement, jamais une couleur littérale. */
.ui-range { display: grid; grid-template-columns: 1fr auto; grid-template-areas: "label label" "track value"; align-items: center; column-gap: var(--space-3); }
.ui-range > span { grid-area: label; }
.ui-range input[type="range"] { grid-area: track; width: 100%; min-width: 0; margin: 0; padding: var(--space-2) 0; accent-color: var(--brand); background: transparent; border: 0; }
.ui-range .ui-range-value { grid-area: value; min-width: 4.5ch; text-align: right; color: var(--text); font-size: var(--font-3); font-variant-numeric: tabular-nums; }
.ui-range .ui-field-hint, .ui-range .ui-field-error { grid-column: 1 / -1; }
.ui-range input[type="range"]:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- Graphique (tâche 5) ---------- */
.ui-chart { position: relative; width: 100%; aspect-ratio: 16 / 7; }
.ui-chart canvas { width: 100% !important; height: 100% !important; }

/* ---------- Table (base ; complétée tâche 4) ---------- */
.ui-table { width: 100%; border-collapse: collapse; font-size: var(--font-3); }
.ui-table th, .ui-table td { text-align: left; padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border); }
.ui-table th { color: var(--muted); font-weight: 600; font-size: var(--font-1); text-transform: uppercase; letter-spacing: .04em; }

/* ---------- DataTable serveur (tâche 4) ---------- */
.ui-datatable { display: flex; flex-direction: column; gap: var(--space-3); }
.ui-table-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-3); }
.ui-table-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); flex: 1 1 auto; margin: 0; }
.ui-table-form input[type="search"] { min-width: 220px; }
.ui-table-filter { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--font-2); color: var(--muted); }
.ui-table-filter input, .ui-table-filter select { margin: 0; }
.ui-table-filter-daterange { display: flex; gap: var(--space-2); }
.ui-table-export {
  display: inline-flex; align-items: center; gap: var(--space-1);
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); font-size: var(--font-3); font-weight: 600; text-decoration: none; white-space: nowrap;
}
.ui-table-export:hover { filter: brightness(1.08); }

.ui-table th[data-sort] { cursor: pointer; user-select: none; }
.ui-table th[data-sort]:hover, .ui-table th[data-sort]:focus-visible { color: var(--text); }
.ui-table th[data-sort]::after { content: ''; display: inline-block; width: var(--space-3); }
.ui-table th[data-sort][aria-sort="ascending"]::after { content: '▲'; margin-left: var(--space-1); }
.ui-table th[data-sort][aria-sort="descending"]::after { content: '▼'; margin-left: var(--space-1); }
.ui-table tbody tr:hover { background: var(--panel-2); }

/* rowHref : un vrai <a> par ligne (accessible, ouvrable dans un nouvel
   onglet), étiré sur toute la ligne plutôt qu'une navigation pilotée par
   script sur un clic générique de <tr>. */
.ui-table tbody tr.ui-table-row-linked { position: relative; }
.ui-table-row-link { position: absolute; inset: 0; z-index: 0; }

.ui-table-status { padding: var(--space-4) 0; }

.ui-table-pagination { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); color: var(--muted); font-size: var(--font-2); }
.ui-table-pagination button {
  font-family: inherit; font-size: var(--font-2); font-weight: 600; cursor: pointer;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-3); margin: 0;
}
.ui-table-pagination button:disabled { opacity: .5; cursor: not-allowed; }

/* Cartes sous 720 px : chaque ligne devient un bloc, chaque cellule porte
   son étiquette de colonne via data-label (posé par le composant). */
@media (max-width: 720px) {
  .ui-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .ui-table, .ui-table tbody, .ui-table tr, .ui-table td { display: block; width: 100%; }
  .ui-table tr { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: var(--space-3); overflow: hidden; }
  .ui-table td {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    text-align: right; border-bottom: 1px solid var(--border);
  }
  .ui-table td:last-child { border-bottom: 0; }
  .ui-table td::before { content: attr(data-label); color: var(--muted); font-weight: 600; font-size: var(--font-1); text-transform: uppercase; letter-spacing: .04em; text-align: left; }
}

/* ---------- Carte de page (states.js::card) et onglets ---------- */
/* Lot A, tâche 20 — `.ui-card` était déclarée DEUX fois à onze lignes
   d'intervalle (report de la revue de la tâche 12) : mêmes fond, bordure,
   rayon et padding, la seconde ajoutant seulement `margin-bottom`. Un
   lecteur qui tombait sur la première croyait tenir la définition de la
   carte et se trompait d'une marge. Un seul bloc désormais — celui qui
   gagnait de toute façon dans la cascade, donc AUCUN changement de rendu. */
.ui-card {
  background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-4); margin-bottom: var(--space-4);
}
.ui-tabs { display: flex; gap: var(--space-2); border-bottom: 1px solid var(--border); }
.ui-tabs button { background: transparent; color: var(--muted); border-radius: var(--radius-sm) var(--radius-sm) 0 0; padding: var(--space-2) var(--space-3); margin: 0; }
.ui-tabs button[aria-selected="true"] { color: var(--text); background: var(--panel-2); }
.ui-card-header {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--space-3); margin-bottom: var(--space-3);
}
.ui-card-header h2 {
  margin: 0; font-size: var(--font-3); color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em;
}

/* ---------- Kanban (tableau à colonnes déplaçables) ---------- */
/* Lot A, tâche 14 — repris des `.shell-pipeline-*` de public/dashboard/styles/
   shell.css : un tableau kanban est un composant du système de design, pas une
   particularité de l'écran Contacts. Tokens uniquement, aucune couleur
   littérale. */

/* `auto-fit` plutôt qu'un `5` codé en dur : le nombre de colonnes est celui
   des étapes rendues (OPPORTUNITY_STAGES aujourd'hui, autre chose demain), et
   sur un écran étroit les colonnes se replient au lieu de déborder. */
.ui-kanban {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3); align-items: start; overflow-x: auto;
}
.ui-kanban-col {
  background: var(--bg); border: 1px dashed transparent; border-radius: var(--radius-sm);
  padding: var(--space-2); min-height: 120px;
}
.ui-kanban-col.droppable { border-color: var(--accent); }
.ui-kanban-col-head {
  font-size: var(--font-1); text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin-bottom: var(--space-2);
}
.ui-kanban-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); margin-bottom: var(--space-1);
  font-size: var(--font-2); color: var(--text); cursor: grab;
}
.ui-kanban-card .sub { color: var(--muted); font-size: var(--font-1); margin-top: 2px; }
.ui-kanban-card-link {
  display: inline-block; margin-top: var(--space-1); font-size: var(--font-1);
  color: var(--accent); text-decoration: none;
}
.ui-kanban-card-link:hover { text-decoration: underline; }

/* Actions groupées dans une cellule de tableau (agenda : terminer /
   replanifier / annuler). */
.ui-row-actions { display: flex; flex-wrap: wrap; gap: var(--space-1); }

/* ---------- Menu d'appel (services/dialer.js) ---------- */
/* Lot A, tâche 18 — « Appeler » ouvre le même menu sur les quatre écrans qui
   composent (fiche appel, fiche prospect, fiche personne, file du poste). Il
   vit sur <body>, positionné sous son ancre : une carte à `overflow` ne peut
   pas le rogner. Tokens uniquement. */
.callbar-menu {
  z-index: 60; min-width: 180px;
  display: flex; flex-direction: column; gap: var(--space-1);
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: var(--space-2);
}
.callbar-menu-item { justify-content: flex-start; width: 100%; }

/* ---------- Barre d'appel (components/callBar.js) ---------- */
/* Lot A, tâche 18 — le seul élément permanent de la coquille. Elle occupe sa
   propre rangée sous la sortie de page (#shell-callbar, shell.css) : elle ne
   recouvre donc jamais le bas d'un écran, et rien n'a à lui réserver de marge.
   Tokens uniquement, utilisable à 390 px (les rangées se replient). */
.callbar {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  font-size: var(--font-2); color: var(--text);
  min-height: 64px; box-sizing: border-box;
}
.callbar-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
}
.callbar-label { font-weight: 600; }
.callbar-dot {
  width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: 0 0 auto;
}
.callbar-dot-ok { background: var(--ok); }
.callbar-dot-bad { background: var(--bad); }

.callbar-dialpad { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); flex: 1 1 220px; }
.callbar-dialpad input {
  flex: 1 1 140px; min-width: 0;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3);
}
.callbar-dial-status { color: var(--muted); }

/* Sonnerie : l'interlocuteur d'abord, les deux gestes ensuite. */
.callbar-caller { display: flex; flex-direction: column; gap: 2px; flex: 1 1 200px; }
.callbar-caller .sub { color: var(--muted); font-size: var(--font-1); }
[data-state="ringing"] .callbar-caller b { font-size: var(--font-4); }

/* En appel : la durée est le seul chiffre qui compte, elle se lit de loin. */
.callbar-timer { font-variant-numeric: tabular-nums; font-size: var(--font-4); font-weight: 600; }
.callbar-dtmf {
  display: grid; grid-template-columns: repeat(6, minmax(32px, 1fr));
  gap: var(--space-1); flex: 0 1 260px;
}
.callbar-dtmf button { padding: var(--space-1) 0; min-width: 0; }

/* Wrap-up : le résultat, la note, les suites, puis la sortie. */
.callbar-wrapup { display: flex; flex-direction: column; gap: var(--space-2); }
.callbar-wrapup select,
.callbar-wrapup textarea {
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3);
  font-family: inherit; font-size: var(--font-2);
}
.callbar-wrapup textarea { flex: 1 1 240px; min-height: 40px; resize: vertical; }
.callbar-acw { color: var(--muted); font-variant-numeric: tabular-nums; }
/* Le repli n'est pas un détail discret : c'est la seule chose qui dit à
   l'opérateur que sa qualification n'est PAS enregistrée. */
.callbar-fallback {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  border: 1px solid var(--warn); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
}
.callbar-fallback a { color: var(--accent); }

@media (max-width: 720px) {
  .callbar { padding: var(--space-2) var(--space-3); }
  .callbar-dtmf { flex: 1 1 100%; grid-template-columns: repeat(6, minmax(28px, 1fr)); }
}

/* Lot A, tâche 18 (ronde 1) — deux choses qu'un opérateur doit voir sans les
   chercher : combien d'après-appels attendent derrière celui-ci, et le fait
   que le serveur n'a PAS confirmé sa présence (il ne recevra pas d'appel). */
.callbar-wrap-count {
  font-size: var(--font-1); color: var(--warn);
  border: 1px solid var(--warn); border-radius: var(--radius-sm);
  padding: 0 var(--space-2);
}
.callbar-presence-warning {
  border-top: 1px solid var(--bad); padding-top: var(--space-2); color: var(--bad);
}

/* ---------- Secret affiché une seule fois (Lot C, tâche 6) ---------- */
/* Une clé d'API fait 57 caractères sans le moindre espace : sans `word-break`,
   elle déborde de la modale au lieu de revenir à la ligne, et la fin du secret
   — la seule partie qui compte — devient invisible. Monospace pour qu'un `0` et
   un `O` se distinguent à la relecture, sélectionnable pour qu'une copie à la
   main reste possible là où le presse-papier n'existe pas. */
.ui-code {
  display: block; width: 100%; box-sizing: border-box;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--font-2); line-height: 1.5;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3); margin: var(--space-3) 0;
  overflow-wrap: anywhere; word-break: break-all; user-select: all;
}
