/* ============================================================
   SOLYFONTE DEVIS — Design System
   Thème clair · Apple-inspired · Bootstrap 5 + Tailwind CDN
   ============================================================ */

:root {
  --accent:         #ec481d;
  --accent-soft:    rgba(236,72,29,0.12);
  --accent-hover:   #d63e15;

  /* Hiérarchie de texte — 3 niveaux, pas plus (règle "muted palette") */
  --text-strong:    #0f172a;   /* titres, valeurs clés, éléments actionnables */
  --text-body:      #475569;   /* contenu courant */
  --text-muted:     #94a3b8;   /* métadonnées, labels de colonnes, aides */

  /* Courbe spring Apple (décélération naturelle) */
  --ease-spring:    cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out:       cubic-bezier(0.25, 0.1, 0.25, 1);

  /* Système de shadows ambiant */
  --shadow-xs:  0 0 0 1px rgba(0,0,0,.03), 0 1px 2px rgba(0,0,0,.04);
  --shadow-sm:  0 0 0 1px rgba(0,0,0,.03), 0 2px 4px rgba(0,0,0,.05),
                0 8px 16px rgba(0,0,0,.04);
  --shadow-md:  0 0 0 1px rgba(0,0,0,.04), 0 4px 8px rgba(0,0,0,.06),
                0 16px 32px rgba(0,0,0,.06), 0 32px 48px rgba(0,0,0,.03);
  --shadow-lg:  0 0 0 1px rgba(0,0,0,.04), 0 8px 16px rgba(0,0,0,.07),
                0 24px 48px rgba(0,0,0,.08), 0 48px 64px rgba(0,0,0,.04);
}

/* ---------- Base ---------- */
html {
  position: relative;
  min-height: 100%;
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
@media (min-width: 768px) { html { font-size: 16px; } }

body {
  background-color: #f0f2f5;
  color: #0f172a;
  font-family: 'Inter', system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: -0.01em;
}

/* ---------- Animation d'entrée de page ---------- */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; }   /* ← pas de transform ici : évite le stacking context */
}

/* opacity:0 initial = pas de flash avant que l'animation démarre */
main[role="main"] {
  opacity: 0;
  animation: fadeUp 420ms var(--ease-spring) forwards;
}

/* Sans transform dans "to", fill-mode:forwards ne crée pas de stacking context
   → les modals Bootstrap position:fixed restent ancrées sur la viewport */
@media (prefers-reduced-motion: reduce) {
  main[role="main"] { animation: none; opacity: 1; }
}

/* ---------- Liens ---------- */
a {
  color: var(--accent);
  text-decoration: none;
  transition: color 150ms var(--ease-out);
}
a:hover { color: var(--accent-hover); text-decoration: underline; }

/* ---------- Composant Panel (carte principale élevée) ---------- */
.panel {
  background: #ffffff;
  border-radius: 18px;
  border: 1px solid rgba(0,0,0,.055);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: box-shadow 250ms var(--ease-spring),
              transform  250ms var(--ease-spring);
}

.panel:hover {
  box-shadow: var(--shadow-md);
}

/* ---------- Cards Bootstrap ---------- */
.card {
  border: 1px solid rgba(0,0,0,.07);
  border-radius: 14px;
  box-shadow: var(--shadow-xs);
  background-color: #fff;
  transition: box-shadow 250ms var(--ease-spring),
              transform  250ms var(--ease-spring);
}

.card:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

.card-header {
  background-color: #f8fafc;
  border-bottom: 1px solid rgba(0,0,0,.06);
}

/* ---------- Boutons ---------- */
.btn {
  transition: transform 150ms var(--ease-spring),
              box-shadow 150ms var(--ease-spring),
              opacity    150ms ease;
}

.btn-primary {
  --bs-btn-bg:             var(--accent);
  --bs-btn-border-color:   var(--accent);
  --bs-btn-hover-bg:       var(--accent-hover);
  --bs-btn-hover-border-color: var(--accent-hover);
  --bs-btn-active-bg:      var(--accent-hover);
  border-radius: 8px;
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(236,72,29,.25), 0 3px 8px rgba(236,72,29,.15);
}

.btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(236,72,29,.3), 0 8px 20px rgba(236,72,29,.2);
}

.btn-primary:active { transform: translateY(0) scale(0.99); }

.btn-secondary,
.btn-outline-secondary,
.btn-info,
.btn-outline-light {
  border-radius: 8px;
}

/* ---------- Focus ---------- */
.form-control:focus,
.form-select:focus,
textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.btn:focus-visible,
.form-check-input:focus {
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}

/* ---------- Champs désactivés ---------- */
.form-control:disabled,
.form-control[readonly],
.form-select:disabled,
textarea:disabled,
textarea[readonly] {
  background-color: #f1f5f9 !important;
  color: #64748b;
  cursor: not-allowed;
  opacity: 1 !important;
}

/* ---------- Tables ---------- */
.table thead th {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #94a3b8;
  border-bottom-color: rgba(0,0,0,.06);
}

/* ---------- Badges ---------- */
.badge {
  border-radius: 999px;
  padding-inline: 0.7rem;
  padding-block: 0.3rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}

/* ---------- text-white-50 en thème clair ---------- */
.text-white-50 { color: #94a3b8 !important; }
.bg-dark .text-white-50,
.modal-content.bg-dark .text-white-50 { color: rgba(255,255,255,.5) !important; }

/* ---------- Alertes Bootstrap ---------- */
.alert {
  border-radius: 12px;
  border-width: 1px;
}

/* ---------- Formulaires ---------- */
.form-control,
.form-select,
textarea {
  border-radius: 8px;
  border-color: rgba(0,0,0,.12);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

/* ---------- Select "pilule" (même DA que le bouton "Comparer à" du date-picker) ---------- */
.select-pill {
  appearance: none;
  -webkit-appearance: none;
  height: 38px;
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 14px;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  padding: 0 32px 0 12px;
  font-size: .875rem;
  font-weight: 500;
  color: #334155;
  box-shadow: 0 1px 2px rgba(0,0,0,.04);
  transition: background-color 150ms ease;
  cursor: pointer;
}
.select-pill:hover { background-color: #f8fafc; }
.select-pill:disabled { background-color: #f1f5f9; color: #94a3b8; opacity: .7; cursor: not-allowed; }

/* Champ obligatoire vide (validation) : voir « Bandeau d'erreurs de formulaire » plus bas,
   où .js-invalid / .input-validation-error / .field-error partagent le même liseré rouge. */

/* ---------- Menus déroulants de navigation (même DA que les pills du menu) ---------- */
header .dropdown-menu {
  padding: 6px;
  margin-top: 6px;
  border: 1px solid rgba(0,0,0,.06);
  border-radius: 14px;
  box-shadow: 0 10px 30px rgba(0,0,0,.10), 0 1px 2px rgba(0,0,0,.04);
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  font-family: 'Inter', system-ui, sans-serif;
}

header .dropdown-item {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 9px;
  font-size: .875rem;              /* text-sm */
  font-weight: 500;
  color: #64748b;                  /* slate-500 */
  transition: color 150ms ease, background-color 150ms ease;
}
header .dropdown-item:hover,
header .dropdown-item:focus {
  color: #0f172a;                  /* slate-900 */
  background-color: rgba(0,0,0,.05);
}
header .dropdown-item.active,
header .dropdown-item:active {
  color: #ea580c;                  /* orange-600 */
  background-color: #fff7ed;       /* orange-50 */
}

header .dropdown-header {
  padding: 6px 12px 4px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #94a3b8;                  /* slate-400 */
  font-weight: 600;
}

/* ============================================================
   PATTERNS SaaS — divulgation progressive & densité maîtrisée
   ============================================================ */

/* ---------- Actions révélées au survol de la ligne ----------
   Les actions secondaires d'une ligne (Modifier, Dupliquer, Supprimer…)
   sont estompées par défaut et n'apparaissent qu'au survol / focus clavier.
   Sur écran tactile (pas de hover), elles restent toujours visibles. */
.hover-row .row-actions {
  opacity: 0;
  transform: translateX(4px);
  transition: opacity 130ms var(--ease-out), transform 130ms var(--ease-out);
}
.hover-row:hover .row-actions,
.hover-row:focus-within .row-actions {
  opacity: 1;
  transform: translateX(0);
}
@media (hover: none) {
  .hover-row .row-actions { opacity: 1; transform: none; }
}

/* ---------- Chiffres : alignés à droite, colonnes de largeur stable ---------- */
.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- État vide accueillant ---------- */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 56px 24px;
  color: #94a3b8;
}
.empty-state svg { height: 44px; width: 44px; color: #cbd5e1; margin-bottom: 14px; }
.empty-state .es-title { font-size: .9rem; font-weight: 600; color: #64748b; }
.empty-state .es-hint  { font-size: .78rem; color: #94a3b8; margin-top: 4px; max-width: 380px; }
.empty-state .es-cta   { margin-top: 16px; }

/* ---------- Bloc repliable de filtres (divulgation progressive) ---------- */
.disclosure summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .78rem;
  font-weight: 600;
  color: #64748b;
  padding: 4px 10px;
  border-radius: 8px;
  transition: background-color 130ms ease, color 130ms ease;
  user-select: none;
}
.disclosure summary::-webkit-details-marker { display: none; }
.disclosure summary:hover { background: rgba(0,0,0,.05); color: #0f172a; }
.disclosure summary .disc-chevron { transition: transform 160ms var(--ease-out); }
.disclosure[open] summary .disc-chevron { transform: rotate(90deg); }
.disclosure > .disc-body { animation: discIn 180ms var(--ease-out); }
@keyframes discIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- Variante « outil » du bloc repliable ----------
   Le style discret ci-dessus convient à un filtre posé dans un bandeau : gris sur blanc, il se
   remarque parce que rien autour ne lui dispute la place. Au milieu d'un formulaire de chiffrage,
   le même gris se noie dans les libellés de champs et l'outil disparaît. D'où un vrai bouton bordé,
   repris de la couleur du panneau qu'il ouvre (ciel), pour qu'on le voie sans qu'il concurrence les
   boutons d'action de la page — qui, eux, sont orange pleins. */
.disclosure-tool summary {
  font-size: .82rem;
  gap: 8px;
  padding: 7px 13px;
  border-radius: 10px;
  color: #0369a1;
  background: #f0f9ff;
  border: 1px solid #bae6fd;
  transition: background-color 130ms ease, border-color 130ms ease, color 130ms ease;
}
.disclosure-tool summary:hover {
  color: #075985;
  background: #e0f2fe;
  border-color: #7dd3fc;
}
.disclosure-tool summary .disc-chevron { color: #38bdf8; }

/* ---------- Page en consultation seule ----------
   Le <fieldset disabled> du layout suffit fonctionnellement, mais par défaut il apporte une bordure,
   une marge et un `min-inline-size` qui casseraient la mise en page : on le remet à plat. Reste à
   FAIRE VOIR que c'est verrouillé — sans quoi on croit à une panne et on clique dix fois sur un
   bouton mort. D'où les champs grisés et le curseur « interdit » sur ce qui aurait été cliquable. */
.readonly-zone {
  border: 0;
  margin: 0;
  padding: 0;
  min-inline-size: auto;
}
.readonly-zone .form-control:disabled,
.readonly-zone .form-select:disabled,
.readonly-zone input:disabled,
.readonly-zone select:disabled,
.readonly-zone textarea:disabled {
  background-color: #f8fafc;
  color: #64748b;
  cursor: not-allowed;
}
.readonly-zone button:disabled,
.readonly-zone [type="submit"]:disabled {
  opacity: .45;
  cursor: not-allowed;
  filter: grayscale(.35);
}

/* ---------- Champ obligatoire ----------
   Une étoile rouge plutôt qu'un « (obligatoire) » écrit en toutes lettres : c'est la convention
   que tout le monde connaît, et ça n'allonge pas le libellé. Corollaire assumé : ce qui est
   facultatif ne porte AUCUNE mention — l'absence d'étoile suffit à le dire. */
.req {
  color: #ef4444;
  font-weight: 700;
  margin-left: 2px;
}

/* ---------- Bandeau d'erreurs de formulaire ----------
   Un formulaire de devis fait plusieurs écrans de haut : un message d'erreur discret en tête de
   page passe inaperçu, l'utilisateur croit avoir enregistré. D'où le triptyque : un bandeau rouge
   qui ne peut pas se confondre avec le reste, un retour automatique en haut de page (voir
   _ValidationBanner.cshtml), et l'encadrement en rouge des champs fautifs pour ne pas avoir à
   chercher lesquels. Même dispositif à la création du devis et à la validation d'un pôle. */
.form-error-banner {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 20px;
  padding: 16px 18px;
  border: 2px solid #ef4444;
  border-radius: 14px;
  background: #fef2f2;
  box-shadow: 0 10px 25px -12px rgba(239, 68, 68, .55);
  animation: febIn 260ms var(--ease-out);
  scroll-margin-top: 16px;
}
.form-error-banner:focus { outline: none; }
@keyframes febIn {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}
.form-error-banner .feb-icon {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #ef4444;
  color: #fff;
  font-weight: 800;
  font-size: .95rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.form-error-banner .feb-title {
  margin: 0 0 6px;
  font-size: .9rem;
  font-weight: 700;
  color: #991b1b;
}
.form-error-banner .feb-list {
  margin: 0;
  padding-left: 18px;
  font-size: .82rem;
  line-height: 1.55;
  color: #b91c1c;
}
.form-error-banner .feb-list li + li { margin-top: 2px; }

/* Champ fautif : le liseré rouge se voit à la volée en parcourant le formulaire. Trois classes
   pour la même chose, selon qui la pose — .input-validation-error vient des tag helpers asp-for,
   .js-invalid du contrôle JS avant envoi, .field-error du ModelState sur les champs à `name=`
   brut (les indices y sont réécrits par le JS, les tag helpers ne peuvent pas les gérer). */
.field-error,
.js-invalid,
.input-validation-error {
  border-color: #dc2626 !important;
  background-color: #fef2f2;
  box-shadow: 0 0 0 3px rgba(220, 38, 38, .18) !important;
}
.field-error:focus,
.js-invalid:focus,
.input-validation-error:focus {
  border-color: #dc2626 !important;
  box-shadow: 0 0 0 3px rgba(220, 38, 38, .3) !important;
}
/* Bloc fautif (une pièce, une étape) : un liseré à gauche pour repérer la zone concernée
   quand le champ en cause est une case à cocher ou un ensemble de champs. */
.block-error {
  border-color: #fca5a5 !important;
  box-shadow: inset 3px 0 0 0 #ef4444;
}

/* ---------- Tarif devis d'une étape ----------
   Une seule case, éditable, comme sur les étapes manuelles : elle affiche le montant calculé tant
   qu'on n'y touche pas, et se fige dès qu'un montant est saisi. Le bloc vire alors à l'orange et
   rappelle le calcul dessous — un prix qui ne suit plus la formule est une décision commerciale,
   elle doit se repérer au premier coup d'œil. */
.price-field {
  display: inline-block;
  border: 1px dashed #cbd5e1;
  border-radius: 12px;
  padding: 6px 10px;
  background: #f8fafc;
  transition: border-color 150ms ease, background-color 150ms ease;
}
.price-field-head {
  display: flex;
  align-items: center;
  gap: 7px;
}
.price-field-label {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #64748b;
  white-space: nowrap;
}
/* « € / pièce » accolé au libellé : l'unité est la même sur toutes les étapes, elle doit se lire
   sans effort mais ne pas concurrencer le libellé — d'où le gris clair et l'absence de majuscules. */
.price-field-unit-hint {
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: #94a3b8;
}
.price-field-input {
  width: 92px;
  font-weight: 600;
  text-align: right;
}
.price-field-unit { font-size: .8rem; font-weight: 600; color: #94a3b8; }

/* La flèche de réinitialisation n'apparaît que s'il y a quelque chose à réinitialiser. */
.price-field-reset {
  display: none;
  align-items: center;
  border: 0;
  background: transparent;
  padding: 0;
  line-height: 0;
  color: #c2410c;
  cursor: pointer;
  flex-shrink: 0;
}
.price-field-reset:hover { color: #9a3412; }

.price-field-hint {
  display: block;
  font-size: .68rem;
  font-style: italic;
  color: #94a3b8;
  margin-top: 4px;
  text-align: right;
}
/* Sans arrondi, pas de ligne réservée : une ligne vide rendrait la boîte plus haute que son
   contenu visible et la désalignerait de ce qui est affiché à côté. */
.price-field-hint:empty { display: none; }

.price-field.is-active {
  border-style: solid;
  border-color: #fdba74;
  background: rgba(255, 237, 213, .5);
}
.price-field.is-active .price-field-label { color: #c2410c; }
.price-field.is-active .price-field-input { border-color: #fdba74; color: #9a3412; }
.price-field.is-active .price-field-hint { color: #c2410c; }
.price-field.is-active .price-field-reset { display: inline-flex; }

/* ---------- Focus clavier visible partout (accessibilité) ---------- */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ---------- Scrollbars fines et discrètes ---------- */
* { scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 8px; }
*::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
*::-webkit-scrollbar-track { background: transparent; }

/* ---------- Ligne cliquable de liste (hover + zebra unifiés) ---------- */
.list-row { transition: background-color 110ms ease; }
.list-row:hover { background-color: rgba(2, 6, 23, .045); }
.list-row.zebra-alt { background-color: rgba(2, 6, 23, .022); }
.list-row.zebra-alt:hover { background-color: rgba(2, 6, 23, .055); }

/* ---------- Toasts de confirmation (remplacent les bandeaux) ---------- */
.toast-stack {
  position: fixed;
  bottom: 22px;
  right: 22px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}
.app-toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 11px;
  background: #fff;
  border: 1px solid rgba(0,0,0,.07);
  border-radius: 14px;
  padding: 12px 14px 12px 12px;
  box-shadow: var(--shadow-md);
  font-size: .85rem;
  font-weight: 500;
  color: #0f172a;
  min-width: 260px;
  max-width: 400px;
  animation: toastIn 260ms var(--ease-spring);
  transition: opacity 220ms ease, transform 220ms ease;
}
.app-toast.hide { opacity: 0; transform: translateY(8px); }
.toast-ico {
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.toast-ok  .toast-ico { color: #059669; background: #ecfdf5; }
.toast-err .toast-ico { color: #dc2626; background: #fef2f2; }
.toast-close {
  margin-left: auto;
  border: 0; background: transparent; color: #94a3b8;
  width: 24px; height: 24px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0;
  transition: background-color 120ms ease, color 120ms ease;
}
.toast-close:hover { background: rgba(0,0,0,.06); color: #334155; }
@keyframes toastIn {
  from { opacity: 0; transform: translateY(12px) scale(.98); }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .app-toast { animation: none; } }

/* ---------- Tables longues : en-tête collant au scroll ---------- */
.scroll-table { overflow: auto; max-height: 72vh; }
.scroll-table thead th {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(255,255,255,.97);
  backdrop-filter: blur(4px);
  box-shadow: 0 1px 0 rgba(0,0,0,.07);
}

/* ---------- Filtre live de la trame de prestations (Création devis) ----------
   .filter-hide masque les nœuds sans correspondance ; .filter-open force
   l'ouverture des branches contenant un résultat (prioritaire sur d-none),
   uniquement pendant la frappe (.trame-filtering). */
.filter-hide { display: none !important; }
.trame-filtering .submenu-container.filter-open,
.trame-filtering .leaf-container.filter-open { display: block !important; }

/* ---------- Sidebar : indicateur d'item actif ---------- */
.side-item { position: relative; }
.side-item.active::before {
  content: "";
  position: absolute;
  left: -12px;                 /* dans la gouttière du nav (px-3) */
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 60%;
  border-radius: 3px;
  background: var(--accent);
}
