/* ==========================================================================
   WS-Audit — Reset, typography, app shell
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* `hidden` always wins. A plain <div hidden> stays hidden because nothing
   else styles it — but the moment it also carries a class that sets
   `display` (.ws-field, .ws-check, .ws-alert…), that author rule outranks
   the browser's own `[hidden] { display: none }` and the element renders
   anyway. Found live on three unrelated screens : the question form's
   choice list showing under every answer type, the storage-driver warning
   in Paramètres always visible, the same pattern waiting in every future
   .ws-field or .ws-check marked hidden. One rule closes all of them. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--ws-font);
  font-size: var(--ws-text-body);
  line-height: var(--ws-lh-body);
  color: var(--ws-ink);
  background: var(--ws-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }

img, svg { max-width: 100%; display: block; }

/* Tabular numerals everywhere numbers must align: tables, metadata, badges. */
table, .ws-meta, .ws-badge, time, .ws-num { font-variant-numeric: tabular-nums; }

:where(a) { color: var(--ws-blue); text-decoration: underline; text-underline-offset: 2px; }
:where(a):hover { color: var(--ws-blue-deep); }

/* Focus — visible on every interactive element, never removed. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--ws-focus);
  outline-offset: var(--ws-focus-offset);
  border-radius: var(--ws-radius-field);
}

/* --- Type scale --------------------------------------------------------- */
.ws-title-page {
  font-size: var(--ws-text-page);
  font-weight: var(--ws-weight-semi);
  line-height: var(--ws-lh-tight);
  letter-spacing: -0.02em;
}
.ws-title-section {
  font-size: var(--ws-text-section);
  font-weight: var(--ws-weight-semi);
  line-height: var(--ws-lh-tight);
  letter-spacing: -0.01em;
}
.ws-subtitle {
  font-size: var(--ws-text-sub);
  font-weight: var(--ws-weight-med);
  color: var(--ws-ink);
}
.ws-meta {
  font-size: var(--ws-text-meta);
  font-weight: var(--ws-weight-med);
  letter-spacing: 0.01em;
  color: var(--ws-muted);
}
.ws-muted { color: var(--ws-muted); }
.ws-prose { max-width: var(--ws-prose-max); }

/* --- Accessibility helpers ---------------------------------------------- */
.ws-sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.ws-skip-link {
  position: absolute; left: var(--ws-2); top: -100px;
  z-index: var(--ws-z-overlay);
  padding: var(--ws-2) var(--ws-4);
  background: var(--ws-surface);
  border: var(--ws-border);
  border-radius: var(--ws-radius-field);
  text-decoration: none;
  font-weight: var(--ws-weight-med);
}
.ws-skip-link:focus { top: var(--ws-2); }

/* --- App shell ----------------------------------------------------------
   Sidebar + topbar + scrollable main. The shell never scrolls; main does. */
.ws-shell {
  display: grid;
  /* minmax(0, 1fr) et non 1fr.
     `1fr` vaut `minmax(auto, 1fr)`, et ce minimum `auto` se résout à la largeur
     min-content de la colonne : un seul enfant rigide — la barre du haut, dont
     la recherche et les boutons sont en nowrap — et la colonne s'élargit au
     lieu de contraindre son contenu. La grille cessait alors de tenir dans le
     viewport et toute l'application débordait horizontalement sur mobile. */
  grid-template-columns: var(--ws-sidebar-w) minmax(0, 1fr);
  grid-template-rows: var(--ws-topbar-h) 1fr;
  grid-template-areas: "brand topbar" "nav main";
  height: 100vh;
  height: 100dvh;
}

/* Même piège, un cran plus bas : un enfant de grille ou de flex a
   `min-width: auto` par défaut et refuse de passer sous sa taille min-content. */
.ws-topbar, .ws-main { min-width: 0; }

.ws-brand {
  grid-area: brand;
  display: flex; align-items: center;
  gap: var(--ws-2);
  padding: 0 var(--ws-4);
  background: var(--ws-surface);
  border-right: var(--ws-border);
  border-bottom: var(--ws-border);
}
.ws-brand img { height: 22px; width: auto; }

.ws-topbar {
  grid-area: topbar;
  display: flex; align-items: center;
  gap: var(--ws-3);
  padding: 0 var(--ws-6);
  background: var(--ws-surface);
  border-bottom: var(--ws-border);
}
.ws-topbar-spacer { flex: 1; }

.ws-nav {
  grid-area: nav;
  background: var(--ws-surface);
  border-right: var(--ws-border);
  padding: var(--ws-3) var(--ws-2);
  overflow-y: auto;
}
.ws-nav-group + .ws-nav-group { margin-top: var(--ws-4); }
.ws-nav-label {
  padding: 0 var(--ws-2) var(--ws-1);
  font-size: var(--ws-text-meta);
  font-weight: var(--ws-weight-semi);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ws-muted);
}
.ws-nav ul { list-style: none; }
.ws-nav a {
  display: flex; align-items: center;
  gap: var(--ws-2);
  min-height: var(--ws-touch-min);
  padding: 0 var(--ws-2);
  border-radius: var(--ws-radius-field);
  color: var(--ws-ink);
  text-decoration: none;
  font-size: var(--ws-text-body);
  transition: background var(--ws-motion);
}
.ws-nav a:hover { background: var(--ws-row-hover); }
.ws-nav a[aria-current="page"] {
  background: var(--ws-blue-wash);
  color: var(--ws-blue-deep);
  font-weight: var(--ws-weight-med);
}
.ws-nav a svg { flex: none; color: var(--ws-muted); }
.ws-nav a[aria-current="page"] svg { color: var(--ws-blue); }

.ws-main {
  grid-area: main;
  overflow-y: auto;
  padding: var(--ws-6);
}
/* Toute page, sans exception : panneaux et en-têtes vont bord à bord.
   Essayé dans l'autre sens (plafonné par défaut, exemption au cas par cas
   pour les pages à tableau) — ça a raté chaque nouvelle page qui n'avait ni
   .ws-table ni .ws-filters au moment du chargement (liste vide, page de
   détail...), avec un en-tête plafonné au-dessus d'un panneau qui ne l'est
   plus. Plus simple et plus sûr : personne n'est plafonné. Le garde-fou est
   ailleurs — sur les champs de saisie eux-mêmes, juste en dessous. */
.ws-main > * { max-width: none; margin-left: 0; margin-right: 0; }
/* Un <input> ne devient pas plus facile à lire à 1800px qu'à 640px — le
   plafond de lecture qui existait au niveau de la page se pose ici, sur le
   champ lui-même, pour qu'une page pleine largeur n'étire pas chaque champ
   de formulaire sur toute la largeur de l'écran. */
.ws-input, .ws-select, .ws-textarea { max-width: 640px; }
.ws-input[type="checkbox"], .ws-input[type="radio"] { max-width: none; }

.ws-page-head {
  display: flex; align-items: flex-start;
  gap: var(--ws-4);
  margin-bottom: var(--ws-6);
}
.ws-page-head-text { flex: 1; min-width: 0; }
.ws-page-head-actions { display: flex; gap: var(--ws-2); flex: none; }

/* --- Panel — the only content container. Not a floating card. ----------- */
.ws-panel {
  background: var(--ws-surface);
  border: var(--ws-border);
  border-radius: var(--ws-radius-box);
}
.ws-panel + .ws-panel { margin-top: var(--ws-4); }
.ws-panel-head {
  display: flex; align-items: center;
  gap: var(--ws-3);
  padding: var(--ws-3) var(--ws-4);
  border-bottom: var(--ws-border);
}
.ws-panel-head .ws-title-section { flex: 1; min-width: 0; }
/* A leading icon marks the section — it is not decoration, so it carries the
   brand blue. Icons deeper in the head (a badge, a button) keep their own. */
.ws-panel-head > svg:first-child { flex: none; color: var(--ws-blue); }
.ws-panel-body { padding: var(--ws-4); }

/* --- Responsive: tablet portrait and below ------------------------------
   Sidebar collapses to an off-canvas drawer. Touch targets grow. */
@media (max-width: 1024px) {
  .ws-shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "topbar" "main";
  }
  .ws-brand { display: none; }
  .ws-nav {
    position: fixed; inset: var(--ws-topbar-h) auto 0 0;
    z-index: var(--ws-z-overlay);
    width: var(--ws-sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--ws-motion);
    box-shadow: var(--ws-shadow-overlay);
  }
  .ws-shell[data-nav="open"] .ws-nav { transform: none; }
  .ws-main { padding: var(--ws-4); }
}

/* --- Responsive: téléphone ----------------------------------------------
   720px est le point de rupture déjà utilisé par components.css ; on le
   réutilise plutôt que d'en inventer un troisième. */
@media (max-width: 720px) {
  /* Le titre de page et ses actions ne tiennent pas côte à côte : le titre se
     faisait écraser à ~120px et se cassait en trois lignes sous les boutons.
     En colonne, le titre garde toute la largeur et les actions passent
     dessous, où elles restent atteignables au pouce. */
  .ws-page-head {
    flex-direction: column;
    align-items: stretch;
    gap: var(--ws-3);
    margin-bottom: var(--ws-4);
  }
  .ws-page-head-actions { flex-wrap: wrap; }
  .ws-page-head-actions > * { flex: 1 1 auto; justify-content: center; }

  /* La barre du haut répète le titre affiché juste en dessous en H1. Sur
     téléphone cette redondance coûte deux lignes dans une barre de 56px. */
  .ws-topbar > .ws-title-section { display: none; }

  /* Le nom complet dans le menu utilisateur pousse la barre hors de l'écran ;
     le chevron seul suffit à désigner le menu, le nom est répété dans le menu
     ouvert. Cette règle ciblait <details><summary> — remplacé depuis par un
     bouton JS (#userBtn) sans que la règle suive, d'où le débordement horizontal
     resté invisible jusqu'à un vrai passage à 375px. */
  .ws-topbar-username { display: none; }

  /* Une carte reste une carte : on réduit le nombre de colonnes, pas l'air
     intérieur. */
  .ws-panel-body { padding: var(--ws-4) var(--ws-3); }
}
/* Specificity must beat .ws-btn's display:inline-flex — components.css loads
   after this file. */
@media (min-width: 1025px) {
  .ws-shell .ws-nav-toggle { display: none; }
}
