/* ============================================================
   V1-W19REV — F36 refonte backoffice (ARCH-FRONTEND §63.2).
   Charte V7 Forest OBLIGATOIRE (V2/V3, PLAN.md §4m.19) — "v0 a le droit d'être moche" est ABROGÉE
   pour ce chantier, elle a produit le rejet du 29/08. Tokens verrouillés (copie locale, ADR-FE-W19REV-01
   — deux projets, deux cycles de build, pas de <link> cross-projet vers ParkMe.Mobile). Thème CLAIR
   uniquement (V3, AC-W19REV-10) : la section DARK de parkman-tokens.css §62-94 N'EST PAS COPIÉE ici,
   et aucune règle CSS ne teste `[data-theme=dark]` ni `prefers-color-scheme`. Texte "CroqPark", jamais
   "ParkMe". Composants signature mobile (.pm-dock/.pm-chomp/.pm-swipe/.pm-drive) N'APPARAISSENT JAMAIS
   dans le backoffice — patrons tactiles sans sens dans un outil de bureau. Réutilisés tels quels :
   .pm-card/.pm-btn/.pm-badge/.pm-chip/.pm-ttl.
   V1-W19REV — F36 refonte backoffice. Charte V7 Forest OBLIGATOIRE, thème CLAIR seul, tokens copiés
   verbatim (ADR-FE-W19REV-01), .pm-dock/.pm-chomp/.pm-swipe/.pm-drive JAMAIS ici (patrons tactiles). */

/* ============================================================
   TOKENS — copie mot pour mot de docs/brand/ui-pack-v7/01-tokens/parkman-tokens.css §:root
   (verrouillées + light seul). Si le fichier source évolue, resynchroniser manuellement (pas
   d'automatisation V1, volume de changement trop faible pour la justifier, §63.10).
   ============================================================ */
:root {
  /* ===== VERROUILLÉES (identiques 2 modes — NE PAS MODIFIER) ===== */
  --pm-saffron:        #FBBF24;
  --pm-saffron-dark:   #F59E0B;
  --pm-forest:         #065F46;
  --pm-forest-dark:    #022C22;
  --pm-forest-light:   #10B981;
  --pm-forest-subtle:  #D1FAE5;
  --pm-p-blue:         #2563EB;
  --pm-spot-free:      #22C55E;
  --pm-spot-fresh:     #F59E0B;
  --pm-spot-taken:     #E24B4A;
  /* 2026-09-03 hotfix — token manquant, présent côté mobile (parkman-tokens.css) depuis V1-W10 E9
     mais jamais porté ici : sans lui, un spot en état gris terminal (D48) n'avait aucun token à lire
     côté carte admin. Même valeur hex que le mobile (source de vérité). */
  --pm-spot-grey:      #94A3B8;
  --pm-pmr:            #0EA5E9;
  --pm-cta-text:       #022C22;

  /* ===== LIGHT (Forest Clean) — SEUL mode utilisé côté backoffice (V3, AC-W19REV-10) ===== */
  --pm-bg-map:         #F2F7F1;
  --pm-map-block:      #E9F1E8;
  --pm-map-street:     #DCE7DB;
  --pm-map-park:       #CDEBD9;
  --pm-surface:        #FFFFFF;
  --pm-ink:            #11201B;
  --pm-muted:          #5C7268;
  --pm-stroke:         #E4EDE7;
  --pm-chip-bg:        #F0F5EF;
  --pm-scrim:          rgba(17, 32, 27, 0.30);
  --pm-pellet:         var(--pm-saffron-dark);
  --pm-shadow-card:    0 2px 8px rgba(15, 23, 42, 0.05);
  --pm-shadow-dock:    0 -8px 24px rgba(15, 23, 42, 0.10);
  --pm-glass-stroke:   transparent;
  --pm-surface-opacity: 1;

  /* ===== Typo ===== */
  --pm-font-display: 'Space Grotesk', 'Inter', system-ui, sans-serif;
  --pm-font-body:    'Inter', system-ui, -apple-system, sans-serif;

  /* ===== Géométrie ===== */
  --pm-r-card: 22px;
  --pm-r-chip: 18px;
  --pm-space-1: 4px;  --pm-space-2: 8px;  --pm-space-3: 12px;
  --pm-space-4: 16px; --pm-space-5: 20px; --pm-space-6: 24px;
  --pm-space-7: 28px; --pm-space-8: 32px; --pm-space-10: 40px;

  /* ===== Motion ===== */
  --pm-t-micro: 150ms cubic-bezier(0.4, 0, 0.2, 1);
  --pm-t-base:  220ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ============================================================
   BASE
   ============================================================ */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--pm-font-body);
  color: var(--pm-ink);
  background: var(--pm-bg-map);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}
a { color: var(--pm-forest); }
a:hover { color: var(--pm-forest-dark); }

.pm-display { font-family: var(--pm-font-display); font-weight: 700; letter-spacing: -0.04em; }
.pm-title   { font-family: var(--pm-font-display); font-weight: 700; font-size: 22px; letter-spacing: -0.02em; }
.pm-body    { font-size: 14px; line-height: 1.5; }
.pm-muted   { color: var(--pm-muted); font-size: 13px; }
.pm-label   { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--pm-muted); display: block; margin-bottom: 6px; }

/* ============================================================
   BOUTONS — copie verbatim parkman-tokens.css §BOUTONS (ADR-FE-W19REV-01).
   Note densité bureau : override .pm-btn { width: auto } — la charte mobile pose width:100%.
   ============================================================ */
.pm-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 20px; border-radius: 22px; border: none;
  font-family: var(--pm-font-display); font-size: 14px; font-weight: 600;
  cursor: pointer; transition: transform var(--pm-t-micro), opacity var(--pm-t-micro), background var(--pm-t-micro);
  width: auto;
  text-decoration: none;
}
.pm-btn:active { transform: scale(0.98); }
.pm-btn[disabled], .pm-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pm-btn--cta     { background: var(--pm-saffron); color: var(--pm-cta-text); font-weight: 700; }
.pm-btn--cta:hover:not(:disabled) { background: var(--pm-saffron-dark); }
.pm-btn--forest  { background: var(--pm-forest); color: #FFFFFF; }
.pm-btn--forest:hover:not(:disabled) { background: var(--pm-forest-dark); }
.pm-btn--outline { background: transparent; color: var(--pm-ink); border: 1.5px solid var(--pm-stroke); }
.pm-btn--outline:hover:not(:disabled) { border-color: var(--pm-forest); color: var(--pm-forest); }
.pm-btn--danger  { background: transparent; color: var(--pm-spot-taken); border: 1.5px solid var(--pm-spot-taken); }
.pm-btn--danger:hover:not(:disabled) { background: var(--pm-spot-taken); color: #FFFFFF; }
.pm-btn--compact { height: 36px; padding: 0 14px; border-radius: 18px; font-size: 13px; }

/* ============================================================
   CHIPS / FILTRES
   ============================================================ */
.pm-chip {
  display: inline-flex; align-items: center; justify-content: center;
  height: 34px; padding: 0 14px; border-radius: var(--pm-r-chip);
  background: var(--pm-chip-bg); color: var(--pm-ink);
  font-size: 13px; font-weight: 600; border: none; cursor: pointer;
  transition: background var(--pm-t-micro);
}
.pm-chip:hover:not(.pm-chip--selected) { background: var(--pm-stroke); }
.pm-chip--selected { background: var(--pm-forest); color: #FFFFFF; font-weight: 700; }
.pm-chip--pmr { color: var(--pm-pmr); }
.pm-chip--pmr.pm-chip--selected { background: var(--pm-pmr); color: #FFFFFF; }

/* ============================================================
   CARDS / PILLS
   ============================================================ */
.pm-card {
  background: var(--pm-surface); border-radius: var(--pm-r-card);
  border: 1px solid var(--pm-stroke); box-shadow: var(--pm-shadow-card);
  padding: var(--pm-space-5);
}
.pm-pill {
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 14px; border-radius: 20px;
  background: var(--pm-surface); border: 1px solid var(--pm-stroke);
}

/* Badge statut place — utilisé sur la Carte admin pour rappeler le vocabulaire D48 en légende */
.pm-badge { display: inline-flex; align-items: center; height: 24px; padding: 0 10px;
            border-radius: 12px; font-size: 11px; font-weight: 800; color: #FFF; letter-spacing: 0.04em; }
.pm-badge--free  { background: var(--pm-spot-free); }
.pm-badge--fresh { background: var(--pm-spot-fresh); }
.pm-badge--taken { background: var(--pm-spot-taken); }
.pm-badge--pmr   { background: var(--pm-pmr); }

/* TTL RING — copie verbatim parkman-tokens.css §TTL (utilisé côté Carte admin, D48 vocabulaire) */
.pm-ttl { position: relative; display: inline-grid; place-items: center; }
.pm-ttl__track { stroke-opacity: 0.22; fill: none; }
.pm-ttl__bar   { fill: none; stroke-linecap: round; transform: rotate(-90deg); transform-origin: center;
                 transition: stroke-dashoffset 1s linear; }
.pm-ttl--free  { color: var(--pm-spot-free); }
.pm-ttl--fresh { color: var(--pm-spot-fresh); }
.pm-ttl--taken { color: var(--pm-spot-taken); }
.pm-ttl--pmr   { color: var(--pm-pmr); }

/* ============================================================
   ADMIN LAYOUT — densité bureau (§4m.4). Sidebar 232px + main scrollable.
   Composants signature mobile .pm-dock/.pm-chomp/.pm-swipe/.pm-drive JAMAIS ici (§63.2).
   ============================================================ */
.admin-shell {
  display: grid;
  grid-template-columns: 232px 1fr;
  min-height: 100vh;
}

.admin-sidebar {
  background: var(--pm-surface);
  border-right: 1px solid var(--pm-stroke);
  padding: var(--pm-space-5) var(--pm-space-4);
  display: flex;
  flex-direction: column;
  gap: var(--pm-space-2);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
.admin-sidebar__logo {
  display: block;
  margin-bottom: var(--pm-space-6);
  text-decoration: none;
}
.admin-sidebar__logo img { height: 28px; width: auto; display: block; }
.admin-sidebar__link {
  display: block;
  padding: 10px 14px;
  border-radius: var(--pm-r-chip);
  color: var(--pm-ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 13.5px;
  transition: background var(--pm-t-micro);
}
.admin-sidebar__link:hover:not(.active) { background: var(--pm-chip-bg); }
.admin-sidebar__link.active {
  background: var(--pm-forest);
  color: #FFFFFF;
}
.admin-sidebar__footer {
  margin-top: auto;
  padding-top: var(--pm-space-4);
  border-top: 1px solid var(--pm-stroke);
  display: flex;
  flex-direction: column;
  gap: var(--pm-space-2);
}
.admin-sidebar__identity {
  font-size: 12px;
  color: var(--pm-muted);
  word-break: break-word;
}

.admin-main {
  padding: var(--pm-space-6) var(--pm-space-8);
  overflow-x: auto;
  min-width: 0;
}
.admin-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--pm-space-6);
  gap: var(--pm-space-4);
  flex-wrap: wrap;
}
.admin-header h1 {
  font-family: var(--pm-font-display);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--pm-ink);
}
.admin-header__sub {
  font-size: 13px;
  color: var(--pm-muted);
  margin: 4px 0 0;
}
.admin-section { margin-bottom: var(--pm-space-6); }
.admin-section h2 {
  font-family: var(--pm-font-display);
  font-size: 18px;
  font-weight: 700;
  margin: 0 0 var(--pm-space-4);
  color: var(--pm-ink);
}
.admin-section h3 {
  font-family: var(--pm-font-display);
  font-size: 15px;
  font-weight: 700;
  margin: var(--pm-space-4) 0 var(--pm-space-2);
  color: var(--pm-ink);
}

/* ============================================================
   TABLE — densité bureau, 30-50 lignes visibles (§4m.4). PAS des cartes façon mobile.
   ============================================================ */
.admin-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--pm-surface);
  border-radius: var(--pm-r-card);
  overflow: hidden;
  box-shadow: var(--pm-shadow-card);
  border: 1px solid var(--pm-stroke);
}
.admin-table th {
  text-align: left;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--pm-muted);
  padding: 12px 14px;
  border-bottom: 1px solid var(--pm-stroke);
  background: var(--pm-chip-bg);
}
.admin-table td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--pm-stroke);
  font-size: 13px;
  color: var(--pm-ink);
  vertical-align: middle;
}
.admin-table tr:last-child td { border-bottom: none; }
.admin-table tr.clickable { cursor: pointer; }
.admin-table tr.clickable:hover td,
.admin-table tr.selected td { background: var(--pm-chip-bg); }

/* Coloration douce pour actions sensibles dans le journal d'audit (§63.6, jamais un hex en dur —
   variante par transparence sur --pm-spot-taken). AC-W19REV-2 respecté. */
.admin-audit-row--sensitive td { background: rgba(226, 75, 74, 0.06); }
.admin-audit-row--sensitive:hover td { background: rgba(226, 75, 74, 0.12); }

/* ============================================================
   METRIC CARDS — Dashboard/Temperature (§63.6, §63.7).
   ============================================================ */
.admin-metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--pm-space-4);
}
.admin-metric-card {
  background: var(--pm-surface);
  border-radius: var(--pm-r-card);
  border: 1px solid var(--pm-stroke);
  box-shadow: var(--pm-shadow-card);
  padding: var(--pm-space-5);
}

/* V1-W19.7 — TS-W19.7-M-DASHBOARD-01-01 (§65.10). Les cartes KPI cliquables sont des <button> (elles
   doivent être atteignables au clavier), donc il faut neutraliser le style natif du bouton — sans
   quoi elles ne ressembleraient plus du tout aux cartes non cliquables voisines. L'affordance repose
   sur le curseur + un liseré forest au survol et au focus : l'anneau de focus n'est JAMAIS supprimé,
   c'est le seul repère d'un opérateur qui navigue au clavier.
   Clickable KPI cards are <button>s for keyboard reachability, so the native button styling is reset.
   The focus ring is never removed — it is the only cue for a keyboard operator. */
.admin-metric-card--clickable {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: border-color var(--pm-t-micro), box-shadow var(--pm-t-micro);
}
.admin-metric-card--clickable:hover { border-color: var(--pm-forest); }
.admin-metric-card--clickable:focus-visible { outline: 2px solid var(--pm-forest); outline-offset: 2px; }
.admin-metric-card__value {
  font-family: var(--pm-font-display);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--pm-ink);
  margin: 0;
  line-height: 1.1;
}
.admin-metric-card__label {
  font-size: 11px;
  color: var(--pm-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 8px;
  font-weight: 700;
}
.admin-metric-card--compact .admin-metric-card__value { font-size: 24px; }

/* V1-W22.8 (§187.3, S-397③) — alert variant for the "événements de détection reçus" card. Grep
   before merge confirmed no --alert/--warning variant existed for admin-metric-card yet — this is
   the first one, tokens only (same pm-spot-taken danger token as admin-message--error above), never
   a hex in the component itself.
   V1-W22.8 (§187.3, S-397③) — variante alerte pour la carte "événements reçus". Tokens uniquement. */
.admin-metric-card--alert {
  border-color: var(--pm-spot-taken);
  box-shadow: 0 0 0 1px var(--pm-spot-taken);
}
.admin-metric-card__sub-value {
  font-size: 12px;
  color: var(--pm-muted);
  margin: 0;
}
.admin-metric-card__alert-text {
  font-size: 12px;
  color: var(--pm-spot-taken);
  font-weight: 700;
  margin: var(--pm-space-2) 0 0;
}

/* ============================================================
   FORMULAIRES — inputs, textareas, selects tous rebasés sur les tokens.
   ============================================================ */
.admin-form-row {
  display: flex;
  align-items: center;
  gap: var(--pm-space-3);
  margin-bottom: var(--pm-space-3);
  flex-wrap: wrap;
}
.admin-input, .admin-select, .admin-textarea {
  font-family: var(--pm-font-body);
  font-size: 13.5px;
  color: var(--pm-ink);
  background: var(--pm-surface);
  border: 1px solid var(--pm-stroke);
  border-radius: 10px;
  padding: 9px 12px;
  transition: border-color var(--pm-t-micro);
  min-width: 0;
}
.admin-input:focus, .admin-select:focus, .admin-textarea:focus {
  outline: none;
  border-color: var(--pm-forest);
}
.admin-input--wide { min-width: 280px; }
.admin-textarea { min-height: 80px; resize: vertical; font-family: var(--pm-font-body); }

/* ============================================================
   FILTERS BAR — barre de filtres au-dessus d'un tableau
   ============================================================ */
.admin-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pm-space-3);
  align-items: end;
  margin-bottom: var(--pm-space-4);
  padding: var(--pm-space-4);
  background: var(--pm-surface);
  border: 1px solid var(--pm-stroke);
  border-radius: var(--pm-r-card);
}
.admin-filter-group { display: flex; flex-direction: column; gap: 4px; }

/* ============================================================
   PAGINATION
   ============================================================ */
.admin-pagination {
  display: flex;
  align-items: center;
  gap: var(--pm-space-3);
  justify-content: center;
  margin-top: var(--pm-space-4);
}
.admin-pagination__page { color: var(--pm-muted); font-size: 13px; }

/* ============================================================
   MESSAGES (info / success / error) — jamais un hex en dur, tokens seulement.
   ============================================================ */
.admin-message {
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 13.5px;
  font-weight: 600;
  margin-bottom: var(--pm-space-4);
}
.admin-message--info    { background: var(--pm-chip-bg); color: var(--pm-forest-dark); border: 1px solid var(--pm-stroke); }
.admin-message--success { background: var(--pm-forest-subtle); color: var(--pm-forest-dark); border: 1px solid var(--pm-forest-light); }
.admin-message--error   { background: rgba(226, 75, 74, 0.08); color: var(--pm-spot-taken); border: 1px solid var(--pm-spot-taken); }

/* ============================================================
   V1-W21 D61 — TS-W21-F-ADMINMAPCONTRACT-01-02 (ARCH-FRONTEND §69.2)
   Bannière de troncature de la carte admin. Même NOM de classe que le patron mobile
   (`pm-toast`/`pm-toast--info`, §66.3) : un seul vocabulaire de refus honnête dans tout le produit,
   jamais deux (ADR-FE-W21-01). Registre INFO uniquement — une troncature admin dit que le périmètre
   a grandi (ARCH-BACKEND §107.1), pas que le backoffice est en panne, et lui donner l'allure d'une
   erreur apprendrait à l'opérateur à se méfier d'un écran qui fonctionne.
   Tokens uniquement ; backoffice en thème clair seul (AC-W19REV-10), donc pas de bloc sombre ici.

   Admin map truncation banner. Same class NAME as the mobile pattern: one honest-refusal vocabulary
   across the product, never two. INFO register only — an admin truncation says the perimeter grew,
   not that the backoffice is broken. Tokens only; backoffice is light-theme only.
   ============================================================ */
.pm-toast {
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 13.5px;
  font-weight: 600;
  border: 1px solid var(--pm-stroke);
  background: var(--pm-surface);
  color: var(--pm-ink);
}
.pm-toast--info { background: var(--pm-forest-subtle); color: var(--pm-forest-dark); border-color: var(--pm-forest-light); }

.admin-map-truncated-banner { margin-bottom: var(--pm-space-4); }

/* La mention « place de démonstration » dans la popup carte (§69.3) : distincte des autres lignes
   sans emprunter une couleur D48 — le saffron dit « attention à la nature de cette donnée », il
   n'encode ni le temps ni l'identité PMR.
   The "demo spot" popup row (§69.3): distinct from the other rows without borrowing a D48 colour. */
.admin-popup__row--simulated .admin-popup__value { color: var(--pm-saffron-dark); font-weight: 700; }

/* ============================================================
   CRÉATEUR SPOT — deux styles VISUELLEMENT PROCHES (gris, italique) mais TEXTE toujours
   différent (§63.5.2). Ne JAMAIS fusionner en un seul style ni un seul libellé (piège
   ARCH-BACKEND §87.15 pt.4). AC-W19REV-6/-7.
   ============================================================ */
.admin-anonymized-label { color: var(--pm-muted); font-style: italic; }
.admin-absent-label     { color: var(--pm-muted); font-style: italic; opacity: 0.7; }

/* ============================================================
   MAP (Écran 1) — conteneur Mapbox admin + panneau toggles/légende
   ============================================================ */
.admin-map-shell {
  display: grid;
  grid-template-columns: 1fr 280px;
  gap: var(--pm-space-4);
  height: calc(100vh - 160px);
  min-height: 480px;
}
.admin-map-container {
  border-radius: var(--pm-r-card);
  overflow: hidden;
  border: 1px solid var(--pm-stroke);
  box-shadow: var(--pm-shadow-card);
  background: var(--pm-map-block);
  position: relative;
}
.admin-map-panel {
  background: var(--pm-surface);
  border: 1px solid var(--pm-stroke);
  border-radius: var(--pm-r-card);
  padding: var(--pm-space-4);
  overflow-y: auto;
  box-shadow: var(--pm-shadow-card);
}
.admin-map-panel h3 {
  font-family: var(--pm-font-display);
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 var(--pm-space-2);
  color: var(--pm-ink);
}
.admin-map-toggles { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--pm-space-4); }
.admin-map-legend { font-size: 12px; color: var(--pm-muted); }
.admin-map-legend__item { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.admin-map-legend__swatch { width: 14px; height: 14px; border-radius: 3px; display: inline-block; }

/* V1-W19.7 — TS-W19.7-M-LEGENDE-01-01 (§65.3, AC-W19.7-02). Légende D48 refaite : la puce est
   RONDE comme le marqueur qu'elle décrit (l'ancien carré arrondi ne ressemblait à rien de ce que la
   carte affiche), et chaque entrée reprend le canal exact du rendu — disque = temps, liseré = PMR,
   opacité = créateur anonymisé, anneau = écoulement. Tokens only (règle grep CI 07 : aucun hex hors
   du bloc :root).
   Legend redone to mirror the real marker: round dot = time, edge = PMR, opacity = anonymised
   creator, ring = elapsed share of the spot's lifetime. Tokens only, no hex outside :root. */
.admin-legend__row { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; }
.admin-legend__dot { width: 14px; height: 14px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
.admin-legend__dot--green { background: var(--pm-spot-free); }
.admin-legend__dot--amber { background: var(--pm-spot-fresh); }
.admin-legend__dot--red   { background: var(--pm-spot-taken); }
.admin-legend__dot--grey  { background: var(--pm-spot-grey); }
/* Liseré PMR : un contour, JAMAIS un remplissage — le bleu --pm-pmr est le canal « identité »
   (D48 canal 3), il s'ajoute à la couleur du temps, il ne la remplace pas.
   PMR edge: an outline, never a fill — the identity channel is additive to the time channel. */
.admin-legend__edge {
  width: 14px; height: 14px; border-radius: 50%; display: inline-block; flex: 0 0 auto;
  background: var(--pm-spot-free); box-sizing: border-box;
}
.admin-legend__edge--pmr { border: 3px solid var(--pm-pmr); }
.admin-legend__opacity {
  width: 14px; height: 14px; border-radius: 50%; display: inline-block; flex: 0 0 auto;
  background: var(--pm-spot-free); opacity: 0.5;
}
/* Anneau : contour seul sur fond transparent — la représentation exacte de buildTtlRingSvg (§65.4). */
.admin-legend__ring {
  width: 14px; height: 14px; border-radius: 50%; display: inline-block; flex: 0 0 auto;
  background: transparent; border: 2px solid var(--pm-forest); box-sizing: border-box;
}

/* V1-W19.7 — TS-W19.7-M-DETAIL-02-02 (§65.6). Grille libellé/valeur du panneau de détail : deux
   colonnes, le libellé cadré à gauche et gris, la valeur en encre pleine — un opérateur balaie la
   colonne de gauche pour trouver le champ, il ne relit pas des phrases. Tokens only.
   Label/value grid for the detail panel: the operator scans the left column, never re-reads prose. */
.admin-detail-grid {
  display: grid;
  grid-template-columns: minmax(140px, max-content) 1fr;
  gap: 6px var(--pm-space-3);
  margin: 0 0 var(--pm-space-4);
  font-size: 13px;
}
.admin-detail-grid dt { color: var(--pm-muted); font-weight: 600; }
.admin-detail-grid dd { margin: 0; color: var(--pm-ink); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.admin-resolved-address { color: var(--pm-forest); font-weight: 600; }

/* Progression d'état D48 (§65.6/§89.5). L'état COURANT est en évidence : les trois horaires décrivent
   ce qui SERAIT arrivé sans court-circuit, ils ne doivent jamais servir à déduire l'état affiché.
   Current state stands out: the three timestamps must never be used to infer the displayed state. */
.admin-ttl-progression {
  background: var(--pm-surface-2, var(--pm-surface));
  border: 1px solid var(--pm-stroke);
  border-radius: var(--pm-r-card);
  padding: var(--pm-space-3);
  font-size: 13px;
}
.admin-ttl-progression p { margin: 0 0 4px; }

/* Pastille d'état D48 sur la liste É2 — DOUBLE ENCODAGE OBLIGATOIRE : la pastille ne vient JAMAIS
   seule, le mot l'accompagne toujours (la couleur seule est inaccessible aux daltoniens, D48).
   D48 double encoding: the dot never appears without the word next to it. */
.admin-ttl-pill {
  width: 10px; height: 10px; border-radius: 50%;
  display: inline-block; margin-right: 6px; vertical-align: middle; flex: 0 0 auto;
}
.admin-ttl-pill--green  { background: var(--pm-spot-free); }
.admin-ttl-pill--yellow { background: var(--pm-spot-fresh); }
.admin-ttl-pill--amber  { background: var(--pm-spot-fresh); }
.admin-ttl-pill--red    { background: var(--pm-spot-taken); }
.admin-ttl-pill--grey   { background: var(--pm-spot-grey); }

/* Compteur du filtre carte (§65.5) — l'effet du filtre doit être LISIBLE, pas seulement visible sur
   la carte : « 12 place(s) affichée(s) sur 240 » vaut mieux que de deviner ce qui a disparu.
   The filter's effect must be readable, not merely visible on the map. */
.admin-map-filter-count { font-size: 11px; margin: var(--pm-space-2) 0 0; }

/* Popup enrichie de la carte (§65.2) — rendue par MapboxAdminInterop.js à partir de champs DÉJÀ
   traduits par Blazor. Densité bureau : une ligne par champ, libellé gris, valeur en encre.
   Enriched map popup, rendered from fields already translated by Blazor. */
.admin-popup { font-family: var(--pm-font-body, Inter, system-ui, sans-serif); font-size: 12px; color: var(--pm-ink); }
.admin-popup__title { font-family: var(--pm-font-display); font-weight: 700; font-size: 13px; margin: 0 0 6px; }
.admin-popup__row { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 3px; }
.admin-popup__label { color: var(--pm-muted); flex: 0 0 auto; }
.admin-popup__value { text-align: right; word-break: break-all; }
.admin-popup__copy {
  margin-left: 6px; padding: 1px 6px; font-size: 11px; cursor: pointer;
  background: transparent; color: var(--pm-forest);
  border: 1px solid var(--pm-stroke); border-radius: 4px;
}
.admin-popup__detail { display: inline-block; margin-top: 6px; color: var(--pm-forest); font-weight: 600; }

/* Timeline panel (Écran 2 détail) */
.admin-timeline-panel {
  background: var(--pm-surface);
  border: 1px solid var(--pm-stroke);
  border-radius: var(--pm-r-card);
  padding: var(--pm-space-4);
  margin-top: var(--pm-space-4);
  box-shadow: var(--pm-shadow-card);
}
.admin-timeline-list { list-style: none; padding: 0; margin: var(--pm-space-2) 0 0; }
.admin-timeline-list li {
  padding: 8px 0;
  border-bottom: 1px solid var(--pm-stroke);
  font-size: 13px;
  color: var(--pm-ink);
  display: flex;
  gap: 12px;
  align-items: baseline;
}
.admin-timeline-list li:last-child { border-bottom: none; }
.admin-timeline-list__at { color: var(--pm-muted); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.admin-timeline-list__type { font-weight: 700; }

/* Autocomplete (Écran 2) */
.admin-autocomplete {
  position: relative;
  min-width: 240px;
}
.admin-autocomplete__list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--pm-surface);
  border: 1px solid var(--pm-stroke);
  border-radius: 12px;
  box-shadow: var(--pm-shadow-card);
  z-index: 20;
  max-height: 280px;
  overflow-y: auto;
  list-style: none;
  padding: 6px;
  margin: 0;
}
.admin-autocomplete__item {
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 13px;
  cursor: pointer;
  color: var(--pm-ink);
}
.admin-autocomplete__item:hover { background: var(--pm-chip-bg); }

/* Bypass shadow-ban card (Écran 3, §63.5.3) — bordure saffron pour marquer le mode dérogatoire */
.admin-bypass-card {
  border: 2px solid var(--pm-saffron);
  background: var(--pm-surface);
  border-radius: var(--pm-r-card);
  padding: var(--pm-space-4);
  margin-top: var(--pm-space-4);
}
.admin-bypass-card__header {
  font-family: var(--pm-font-display);
  font-weight: 700;
  color: var(--pm-forest-dark);
  margin: 0 0 var(--pm-space-2);
  display: flex;
  align-items: center;
  gap: 8px;
}
.admin-bypass-card__hint { font-size: 12px; color: var(--pm-muted); margin: 0 0 var(--pm-space-3); }

/* Motifs à examiner (Écran 8 Karma, §63.9) — bordure --pm-saffron pour matérialiser le mode
   "à surveiller", JAMAIS --pm-spot-taken/rouge (qui impliquerait un verdict, AC-W19REV-9).
   Même patron structurel que .admin-bypass-card (border/background/radius/padding/shadow) ; variante
   sémantique distincte pour ne pas mélanger "mode dérogatoire admin" et "signal à examiner". */
.admin-anomaly-card {
    border: 2px solid var(--pm-saffron);
    background: var(--pm-surface);
    border-radius: var(--pm-r-card);
    padding: var(--pm-space-4);
    box-shadow: var(--pm-shadow-card);
}

/* Placeholder pour section en attente (§63.6, 7ᵉ famille Config bloquée par Lot 2 backend) */
.admin-pending {
  padding: var(--pm-space-4);
  border: 1px dashed var(--pm-stroke);
  border-radius: 12px;
  color: var(--pm-muted);
  font-size: 13px;
  background: var(--pm-chip-bg);
}

/* Barre de progression CSS pure (Écran 7, §63.8) — jamais un hex en dur */
.admin-progress {
  height: 8px;
  background: var(--pm-chip-bg);
  border-radius: 4px;
  overflow: hidden;
  min-width: 120px;
}
.admin-progress__bar {
  height: 100%;
  background: linear-gradient(90deg, var(--pm-forest-light) 0%, var(--pm-forest) 100%);
  border-radius: 4px;
  transition: width var(--pm-t-base);
}

/* Utilities */
.pm-flex-gap-2 { display: flex; gap: var(--pm-space-2); flex-wrap: wrap; }
.pm-flex-gap-3 { display: flex; gap: var(--pm-space-3); flex-wrap: wrap; align-items: center; }
.pm-mt-3 { margin-top: var(--pm-space-3); }
.pm-mt-4 { margin-top: var(--pm-space-4); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition-duration: 120ms !important; }
}

/* V1-W19.7 — TS-W19.7-M-LIBELLES-02-01/-02-03 (§65.8, AC-W19.7-17).
   .pm-tooltip : le ⓘ « référence interne ». Le jargon n'est jamais supprimé du backoffice, il est
   déplacé ici — il relie l'écran à la spécification, et un opérateur qui en a besoin doit pouvoir le
   retrouver sans lire le code. `cursor: help` est le seul signal qu'il y a quelque chose à survoler.
   .admin-actor-id : l'identifiant technique passe en second rang sous l'email, plus petit — présent
   et copiable (c'est lui qui corrèle avec les logs), mais plus jamais la seule chose affichée.
   The jargon is moved to a tooltip, never deleted; the GUID drops to a second line under the email —
   still present and copyable, never again the only thing shown. */
.pm-tooltip { margin-left: 6px; color: var(--pm-muted); cursor: help; font-size: 12px; }
.admin-actor-id { font-size: 11px; }

/* ============================================================
   V1-W22.10 — lot SOC-BO (ARCH-FRONTEND §135.12bis, AC-SOC-31) — « Supprimer ce compte » on the user profile.
   Destructive zone: a card outlined with the danger tone the existing .pm-btn--danger already uses (--pm-spot-taken),
   tokens only. Light theme only, like the whole backoffice (AC-W19REV-10 — no dark theme exists here).
   V1-W22.10 — zone destructive : carte bordée du ton de danger déjà utilisé par .pm-btn--danger, tokens uniquement.
   Thème clair seul, comme tout le backoffice (AC-W19REV-10).
   ============================================================ */
.admin-danger-zone {
    border: 1.5px solid var(--pm-spot-taken);
}
.admin-danger-zone__title {
    color: var(--pm-spot-taken);
    margin-top: 0;
}
.admin-danger-zone__text {
    color: var(--pm-ink);
    line-height: 1.55;
    max-width: 72ch;
}

/* ============================================================
   V1-W22.14 — lot SCOUT-BO (ARCH-FRONTEND §148.4.4) — role pills of the user profile « Rôles » block.
   A STATIC label (no hover, no pointer — .pm-chip is a filter button and .pm-badge carries the D48 spot colours, so
   neither fits). Composed ONLY of three tokens already declared: --pm-chip-bg, --pm-forest-dark, --pm-stroke. Light
   theme only, like the whole backoffice (ADR-F-W2214-06).
   V1-W22.14 — pastilles de rôle de la fiche. Étiquette STATIQUE, composée UNIQUEMENT de trois tokens déjà déclarés.
   ============================================================ */
.admin-role-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 12px;
    padding: 0;
    list-style: none;
}
.admin-role-chip {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 12px;
    border-radius: var(--pm-r-chip);
    background: var(--pm-chip-bg);
    color: var(--pm-forest-dark);
    border: 1px solid var(--pm-stroke);
    font-size: 13px;
    font-weight: 600;
}
