/* ============================================================================
   Vinted Tracker — Design system
   Aucune dépendance réseau : pas de CDN, pas de build step.
   ========================================================================= */

/* ─── Tokens ─────────────────────────────────────────────────────────────── */

:root {
    /* Surfaces étagées */
    --bg:            #0a0e14;
    --surface-1:     #111721;
    --surface-2:     #161e2a;
    --surface-3:     #1d2734;
    --surface-sunk:  #0d131b;

    /* Bordures. `--border` et `--border-strong` séparent des blocs : elles
       n'ont rien à porter comme information, leur contraste n'est pas soumis
       à un seuil. `--border-control` en a un, et c'est un autre métier : c'est
       le seul trait qui dit « ceci est un champ, ceci est un bouton ».

       Il tient 3:1 (WCAG 1.4.11) sur les cinq surfaces, pas seulement sur
       celles qui portent un contrôle au repos : mesuré 4,09 · 3,95 · 3,80 ·
       3,55 · 3,19, le pire cas étant `--surface-3`. Cette surface-là compte
       parce que `.btn-secondary:hover` s'en remplit — s'en tenir aux fonds de
       repos aurait laissé le survol sous le seuil sans que rien ne le dise.
       Les contrôles empruntaient avant `--border-strong`, qui plafonne à 1,68
       et tombe à 1,31 : la bordure était là, mais elle ne délimitait rien. */
    --border:         #1f2937;
    --border-strong:  #2d3a4c;
    --border-control: #607590;

    /* Texte.
       Les quatre paliers passent 4,5:1 sur `--surface-3`, la plus claire des
       surfaces qui portent du texte — donc sur toutes les autres. Mesuré :
       12,80 · 7,56 · 5,58 · 4,55.

       `--text-muted` a été éclairci alors qu'il passait déjà (5,88). C'est une
       conséquence, pas un caprice : remonter `--text-subtle` à 5,58 sans
       toucher à `--muted` aurait rendu les deux paliers indiscernables. Une
       échelle dont deux échelons se confondent ne hiérarchise plus rien. */
    --text:          #e7edf4;
    --text-muted:    #acb9c8;
    --text-subtle:   #8e9fb4;
    --text-faint:    #7b8fa7;

    /* Sémantique — teal : accent, succès, bénéfice */
    --accent:        #14b8a6;
    --accent-hover:  #2dd4bf;
    --accent-soft:   rgba(20, 184, 166, 0.12);
    --accent-text:   #5eead4;

    /* Bleu : information, compte */
    --info:          #3b82f6;
    --info-soft:     rgba(59, 130, 246, 0.12);
    --info-text:     #93c5fd;

    /* Orange : attention, action requise */
    --warn:          #f59e0b;
    --warn-soft:     rgba(245, 158, 11, 0.12);
    --warn-text:     #fcd34d;

    /* Rouge : erreur réelle uniquement */
    --danger:        #ef4444;
    --danger-soft:   rgba(239, 68, 68, 0.12);
    --danger-text:   #fca5a5;

    /* Gris : secondaire, neutre */
    --neutral-soft:  rgba(148, 163, 184, 0.10);

    /* Formes */
    --radius-sm: 6px;
    --radius:    10px;
    --radius-lg: 14px;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.30);
    --shadow:    0 4px 16px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.55);

    --sidebar-w: 248px;
    --header-h:  60px;

    --ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);

    --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, "Liberation Mono", monospace;
}

/* ─── Reset ──────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    overflow: hidden;
}

h1, h2, h3, h4, p, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
    font: inherit;
    color: inherit;
}

button { background: none; border: none; cursor: pointer; }

svg { display: block; flex: none; }

[x-cloak] { display: none !important; }

:focus { outline: none; }
:focus-visible { box-shadow: var(--ring); border-radius: var(--radius-sm); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--surface-3);
    border-radius: 99px;
    border: 3px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }

/* ─── Typographie ────────────────────────────────────────────────────────── */

.page-title    { font-size: 20px;   font-weight: 650; letter-spacing: -0.02em; color: var(--text); }
.section-title { font-size: 13px;   font-weight: 600; color: var(--text); }
.eyebrow       { font-size: 11px;   font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-faint); }
.metric        { font-size: 26px;   font-weight: 650; letter-spacing: -0.02em; color: var(--text); font-variant-numeric: tabular-nums; }
.metric-sm     { font-size: 18px;   font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.label         { font-size: 12px;   font-weight: 500; color: var(--text-muted); }
.helper        { font-size: 12px;   color: var(--text-subtle); line-height: 1.45; }
.muted         { color: var(--text-muted); }
.subtle        { color: var(--text-subtle); }
.faint         { color: var(--text-faint); }
.num           { font-variant-numeric: tabular-nums; }
.mono          { font-family: var(--mono); font-size: 12px; }
.strong        { font-weight: 600; }
.text-accent   { color: var(--accent-text); }
.text-info     { color: var(--info-text); }
.text-warn     { color: var(--warn-text); }
.text-danger   { color: var(--danger-text); }

.truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ─── Primitives de mise en page ─────────────────────────────────────────── */

.row  { display: flex; align-items: center; gap: 10px; }
.row-top { display: flex; align-items: flex-start; gap: 10px; }
.col  { display: flex; flex-direction: column; }
.wrap { flex-wrap: wrap; }
.between { justify-content: space-between; }
.center  { justify-content: center; }
.end     { justify-content: flex-end; }
.grow    { flex: 1; min-width: 0; }
.none    { flex: none; }
.push    { margin-left: auto; }

/* Sans cette règle, `.wrap` ne sert à rien dès qu'un `.grow` est sur la ligne.
   `.grow` vaut `min-width: 0` pour permettre l'ellipse ; conséquence, il peut
   rétrécir indéfiniment, la ligne ne déborde donc jamais et `flex-wrap` ne se
   déclenche pas. Mesuré sur l'en-tête de /comptes à 375 px : le bloc de titre
   était comprimé à 115 px à côté d'un bouton de 214 px — « Comptes connectés »
   cassé en deux lignes et son sous-titre en trois, alors que la barre était
   explicitement déclarée `wrap`.
   Le plancher rend le repli possible : il se déclenche sur la largeur réelle
   disponible, pas sur un palier d'écran choisi à la main. `min()` le borne à
   la largeur du conteneur, pour qu'un conteneur plus étroit que 12 rem se
   contente de tout prendre au lieu de déborder.

   `:not(:empty)` n'est pas un détail. `.grow` sert aussi de simple cale —
   `<div class="grow"></div>` pousse un bouton vers la droite, on en compte 16
   dans les gabarits. Leur imposer un plancher les fait réclamer 12 rem de
   vide : mesuré sur les cartes de /comptes à 1440 px, la barre « Synchroniser
   / Tester / Renommer » passait de 28 à 64 px de haut, la corbeille chassée à
   la ligne suivante. Une cale n'a rien à disposer, elle n'a pas de largeur
   minimale à défendre. */
.row.wrap > .grow:not(:empty),
.row-top.wrap > .grow:not(:empty) { min-width: min(12rem, 100%); }

.gap-0  { gap: 0; }
.gap-1  { gap: 4px; }
.gap-2  { gap: 8px; }
.gap-3  { gap: 12px; }
.gap-4  { gap: 16px; }
.gap-5  { gap: 20px; }
.gap-6  { gap: 24px; }

.mt-1 { margin-top: 4px; }
.mt-2 { margin-top: 8px; }
.mt-3 { margin-top: 12px; }
.mt-4 { margin-top: 16px; }
.mt-5 { margin-top: 20px; }
.mt-6 { margin-top: 24px; }
.mb-1 { margin-bottom: 4px; }
.mb-2 { margin-bottom: 8px; }
.mb-3 { margin-bottom: 12px; }
.mb-4 { margin-bottom: 16px; }
.mb-5 { margin-bottom: 20px; }
.mb-6 { margin-bottom: 24px; }

.text-center { text-align: center; }

.stack     > * + * { margin-top: 12px; }
.stack-lg  > * + * { margin-top: 20px; }
.stack-xl  > * + * { margin-top: 28px; }

.w-full { width: 100%; }
.right  { text-align: right; }
.hide   { display: none !important; }

/* ─── App shell ──────────────────────────────────────────────────────────── */

.app-shell {
    display: flex;
    height: 100vh;
    overflow: hidden;
}

.app-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.app-content {
    flex: 1;
    overflow-y: auto;
    padding: 24px 28px 64px;
}

.page {
    max-width: 1280px;
    margin: 0 auto;
}

/* ─── Sidebar ────────────────────────────────────────────────────────────── */

.sidebar {
    width: var(--sidebar-w);
    flex: none;
    background: var(--surface-sunk);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    z-index: 40;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    height: var(--header-h);
    padding: 0 16px;
    flex: none;
    border-bottom: 1px solid var(--border);
}

.brand-mark {
    width: 30px;
    height: 30px;
    flex: none;
    border-radius: 8px;
    /* Le bout sombre du dégradé est le fond le plus défavorable pour l'initiale.
       Il descendait à #0f766e, où la lettre tombait à 3,12:1 ; remonté au teal
       600, elle tient 4,57:1. Le dégradé reste un dégradé, il part juste de
       moins loin. */
    background: linear-gradient(140deg, var(--accent) 0%, #0d9488 100%);
    color: #04201c;
    font-weight: 800;
    font-size: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.brand-text { line-height: 1.2; min-width: 0; }
.brand-name { font-size: 13px; font-weight: 650; color: var(--text); }
.brand-sub  { font-size: 11px; color: var(--text-faint); }

.sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: 14px 10px;
}

.nav-group + .nav-group { margin-top: 18px; }

.nav-group-title {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-faint);
    padding: 0 10px 6px;
}

.nav-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 500;
    transition: background-color 0.12s, color 0.12s;
}

.nav-item + .nav-item { margin-top: 2px; }
.nav-item:hover { background: var(--surface-2); color: var(--text); }

.nav-item.active {
    background: var(--surface-2);
    color: var(--text);
}

.nav-item.active::before {
    content: "";
    position: absolute;
    left: -10px;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 18px;
    border-radius: 0 3px 3px 0;
    background: var(--accent);
}

.nav-item.active svg { color: var(--accent-text); }

.nav-badge {
    margin-left: auto;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 99px;
    background: var(--warn-soft);
    color: var(--warn-text);
    font-size: 11px;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sidebar-foot {
    flex: none;
    padding: 12px 14px;
    border-top: 1px solid var(--border);
}

/* ─── Header ─────────────────────────────────────────────────────────────── */

.app-header {
    flex: none;
    height: var(--header-h);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 20px 0 28px;
    background: rgba(10, 14, 20, 0.85);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--border);
    z-index: 30;
}

.header-title { font-size: 15px; font-weight: 600; color: var(--text); line-height: 1.2; }
.header-desc  { font-size: 12px; color: var(--text-subtle); line-height: 1.2; }

.search-trigger {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 32px;
    padding: 0 10px;
    min-width: 200px;
    border-radius: var(--radius-sm);
    background: var(--surface-1);
    border: 1px solid var(--border-control);
    color: var(--text-subtle);
    font-size: 13px;
    transition: border-color 0.12s, color 0.12s;
}
.search-trigger:hover { border-color: var(--text-subtle); color: var(--text-muted); }

.kbd {
    font-family: var(--font);
    font-size: 10px;
    font-weight: 600;
    padding: 2px 5px;
    border-radius: 4px;
    background: var(--surface-3);
    border: 1px solid var(--border-strong);
    color: var(--text-subtle);
    line-height: 1.3;
    white-space: nowrap;
}

.icon-btn {
    width: 32px;
    height: 32px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    transition: background-color 0.12s, color 0.12s;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }

.menu-btn { display: none; }

/* ─── Boutons ────────────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 34px;
    padding: 0 13px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 550;
    border: 1px solid transparent;
    white-space: nowrap;
    transition: background-color 0.12s, border-color 0.12s, color 0.12s, opacity 0.12s;
}

.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-primary {
    background: var(--accent);
    color: #042f2a;
    font-weight: 600;
}
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); }

.btn-secondary {
    background: var(--surface-2);
    border-color: var(--border-control);
    color: var(--text);
}
.btn-secondary:hover:not(:disabled) { background: var(--surface-3); }

.btn-ghost { color: var(--text-muted); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

.btn-danger {
    background: var(--danger-soft);
    border-color: rgba(239, 68, 68, 0.35);
    color: var(--danger-text);
}
.btn-danger:hover:not(:disabled) { background: rgba(239, 68, 68, 0.2); }

.btn-sm { height: 28px; padding: 0 10px; font-size: 12px; }
.btn-icon { width: 34px; padding: 0; }
.btn-block { width: 100%; }

/* ─── Cartes ─────────────────────────────────────────────────────────────── */

.card {
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.card-pad { padding: 18px; }

.card-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
}

.card-body { padding: 18px; }

.card-foot {
    padding: 12px 18px;
    border-top: 1px solid var(--border);
}

.section-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
}

/* ─── KPI ────────────────────────────────────────────────────────────────── */

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
}

.kpi {
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.kpi-label {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-muted);
}

.kpi-value { font-size: 24px; font-weight: 650; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }

.kpi-foot { font-size: 12px; color: var(--text-subtle); display: flex; align-items: center; gap: 6px; }

.delta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 99px;
    font-variant-numeric: tabular-nums;
}
.delta-up   { background: var(--accent-soft); color: var(--accent-text); }
.delta-down { background: var(--danger-soft); color: var(--danger-text); }
.delta-flat { background: var(--neutral-soft); color: var(--text-subtle); }

/* ─── Badges & statuts ───────────────────────────────────────────────────── */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: 99px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.6;
    white-space: nowrap;
}

.badge-accent  { background: var(--accent-soft);  color: var(--accent-text); }
.badge-info    { background: var(--info-soft);    color: var(--info-text); }
.badge-warn    { background: var(--warn-soft);    color: var(--warn-text); }
.badge-danger  { background: var(--danger-soft);  color: var(--danger-text); }
.badge-neutral { background: var(--neutral-soft); color: var(--text-muted); }

.status-dot {
    width: 7px;
    height: 7px;
    flex: none;
    border-radius: 99px;
    background: var(--text-faint);
}
.status-dot.ok      { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.status-dot.warn    { background: var(--warn);   box-shadow: 0 0 0 3px var(--warn-soft); }
.status-dot.error   { background: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }
.status-dot.syncing { background: var(--info);   box-shadow: 0 0 0 3px var(--info-soft); animation: pulse 1.4s ease-in-out infinite; }

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

.spin { animation: spin 0.9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ─── Bandeau santé ──────────────────────────────────────────────────────── */

.health {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface-1);
    flex-wrap: wrap;
}
.health.is-warn  { border-color: rgba(245, 158, 11, 0.3); background: linear-gradient(90deg, var(--warn-soft), transparent 55%), var(--surface-1); }
.health.is-error { border-color: rgba(239, 68, 68, 0.3); background: linear-gradient(90deg, var(--danger-soft), transparent 55%), var(--surface-1); }

.health-sep { width: 1px; height: 22px; background: var(--border); flex: none; }

/* ─── Actions requises ───────────────────────────────────────────────────── */

.action-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface-1);
    transition: border-color 0.12s;
}
.action-item:hover { border-color: var(--border-strong); }

.action-icon {
    width: 32px;
    height: 32px;
    flex: none;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* La sévérité se pose soit sur le conteneur, soit sur l'icône elle-même
   (liste d'alertes) : les deux formes doivent teinter la pastille. */
.sev-error .action-icon, .action-icon.sev-error, .empty-icon.sev-error { background: var(--danger-soft); color: var(--danger-text); }
.sev-warn  .action-icon, .action-icon.sev-warn,  .empty-icon.sev-warn  { background: var(--warn-soft);   color: var(--warn-text); }
.sev-info  .action-icon, .action-icon.sev-info,  .empty-icon.sev-info  { background: var(--info-soft);   color: var(--info-text); }
/* Teal, conformément à la convention : accent, succès, bénéfice. Le vert ne
   revient pas par cette porte. Sévérité rare — un « rien à faire » se dit le
   plus souvent en neutre ; elle sert quand une action destructive a abouti et
   qu'il faut le confirmer sans ambiguïté. */
.sev-ok    .action-icon, .action-icon.sev-ok,    .empty-icon.sev-ok    { background: var(--accent-soft);  color: var(--accent-text); }

/* Le liseré reste réservé au conteneur : sur l'icône il ajouterait un trait parasite. */
.action-item.sev-error { border-left: 2px solid var(--danger); }
.action-item.sev-warn  { border-left: 2px solid var(--warn); }
.action-item.sev-info  { border-left: 2px solid var(--info); }
.action-item.sev-ok    { border-left: 2px solid var(--accent); }

/* ─── Tableaux ───────────────────────────────────────────────────────────── */

.table-wrap {
    overflow-x: auto;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface-1);
}

table.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.table thead th {
    position: sticky;
    top: 0;
    background: var(--surface-2);
    color: var(--text-subtle);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    text-align: left;
    padding: 9px 14px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
    z-index: 1;
}

.table tbody td {
    padding: 11px 14px;
    border-top: 1px solid var(--border);
    color: var(--text);
    vertical-align: middle;
}

.table tbody tr { transition: background-color 0.1s; }
.table tbody tr:hover { background: var(--surface-2); }
.table tbody tr:first-child td { border-top: none; }

.table .col-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table .col-tight { width: 1%; white-space: nowrap; }

/* En-tête triable. `all: unset` aurait aussi supprimé l'anneau de focus. */
.th-sort {
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    cursor: pointer;
    border-radius: 3px;
}
.th-sort:hover { color: var(--text); }
.col-num .th-sort { width: 100%; text-align: right; }

/* ─── Formulaires ────────────────────────────────────────────────────────── */

.input, .select, .textarea {
    width: 100%;
    height: 34px;
    padding: 0 10px;
    background: var(--surface-sunk);
    border: 1px solid var(--border-control);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: 13px;
    transition: border-color 0.12s, box-shadow 0.12s;
}

.textarea { height: auto; padding: 8px 10px; min-height: 72px; resize: vertical; }

.input::placeholder, .textarea::placeholder { color: var(--text-faint); }

.input:focus, .select:focus, .textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Champ refusé par le serveur. On s'accroche à `aria-invalid` plutôt qu'à une
   classe maison : l'attribut est déjà ce qui prévient les lecteurs d'écran,
   le styler évite deux sources de vérité qui finiraient par diverger. */
.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"] { border-color: var(--danger); }

.input[aria-invalid="true"]:focus,
.select[aria-invalid="true"]:focus,
.textarea[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--danger-soft); }

.select {
    appearance: none;
    padding-right: 28px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23acb9c8' stroke-width='3'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 9px center;
}
.select option { background: var(--surface-2); color: var(--text); }

.input-affix { position: relative; }
.input-affix .affix {
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 12px;
    color: var(--text-subtle);
    pointer-events: none;
}
.input-affix .input { padding-right: 34px; }

.field-label {
    display: block;
    font-size: 12px;
    font-weight: 550;
    color: var(--text-muted);
    margin-bottom: 5px;
}

.search-input {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.5-3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 10px center;
    padding-left: 31px;
}

/* ─── Onglets & segments ─────────────────────────────────────────────────── */

.segmented {
    display: inline-flex;
    padding: 2px;
    gap: 2px;
    background: var(--surface-sunk);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}

.segmented button {
    padding: 4px 11px;
    border-radius: 5px;
    font-size: 12px;
    font-weight: 550;
    color: var(--text-subtle);
    transition: background-color 0.12s, color 0.12s;
    white-space: nowrap;
}
.segmented button:hover { color: var(--text); }
.segmented button.active { background: var(--surface-3); color: var(--text); }

.tabs {
    display: flex;
    gap: 2px;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
}

.tabs button {
    position: relative;
    padding: 8px 12px;
    font-size: 13px;
    font-weight: 550;
    color: var(--text-subtle);
    white-space: nowrap;
    transition: color 0.12s;
}
.tabs button:hover { color: var(--text); }
.tabs button.active { color: var(--text); }
.tabs button.active::after {
    content: "";
    position: absolute;
    left: 8px;
    right: 8px;
    bottom: -1px;
    height: 2px;
    border-radius: 2px;
    background: var(--accent);
}

.tab-count {
    margin-left: 6px;
    font-size: 11px;
    color: var(--text-faint);
    font-variant-numeric: tabular-nums;
}

/* ─── Timeline ───────────────────────────────────────────────────────────── */

.timeline { position: relative; padding-left: 26px; }

.timeline::before {
    content: "";
    position: absolute;
    left: 10px;
    top: 6px;
    bottom: 6px;
    width: 1px;
    background: var(--border);
}

.tl-item { position: relative; padding: 7px 0; }

.tl-dot {
    position: absolute;
    left: -21px;
    top: 11px;
    width: 9px;
    height: 9px;
    border-radius: 99px;
    background: var(--surface-3);
    border: 2px solid var(--bg);
    box-shadow: 0 0 0 1px var(--border-strong);
}
.tl-dot.accent { background: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.tl-dot.info   { background: var(--info);   box-shadow: 0 0 0 1px var(--info); }
.tl-dot.warn   { background: var(--warn);   box-shadow: 0 0 0 1px var(--warn); }
.tl-dot.danger { background: var(--danger); box-shadow: 0 0 0 1px var(--danger); }

.day-sep {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 18px 0 6px;
}
.day-sep::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* ─── Listes / lignes d'activité ─────────────────────────────────────────── */

.list-row {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 14px;
    border-top: 1px solid var(--border);
    transition: background-color 0.1s;
}
.list-row:first-child { border-top: none; }
a.list-row:hover, button.list-row:hover { background: var(--surface-2); }
button.list-row { width: 100%; text-align: left; }

.avatar {
    width: 28px;
    height: 28px;
    flex: none;
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    background: var(--surface-3);
    color: var(--text-muted);
}

/* ─── Empty state / skeleton ─────────────────────────────────────────────── */

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 40px 24px;
    gap: 6px;
}

.empty-icon {
    width: 40px;
    height: 40px;
    border-radius: 11px;
    background: var(--surface-2);
    color: var(--text-faint);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 4px;
}

.empty-title { font-size: 14px; font-weight: 600; color: var(--text); }
.empty-desc  { font-size: 13px; color: var(--text-subtle); max-width: 380px; }

.skeleton {
    background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.3s linear infinite;
    border-radius: var(--radius-sm);
    height: 12px;
}

@keyframes shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ─── Drawer ─────────────────────────────────────────────────────────────── */

.overlay {
    position: fixed;
    inset: 0;
    background: rgba(2, 5, 9, 0.66);
    backdrop-filter: blur(2px);
    z-index: 60;
}

/* Le voile du drawer n'a de sens qu'en mobile. Sans cette règle, élargir la
   fenêtre menu ouvert laisse un voile plein écran qu'on ne peut plus fermer :
   le bouton menu, lui, disparaît au-delà de 760 px. */
.overlay-nav { display: none; }

.drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 480px;
    max-width: 100vw;
    background: var(--surface-1);
    border-left: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    z-index: 61;
    display: flex;
    flex-direction: column;
}

.drawer-head {
    flex: none;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--border);
}

.drawer-body { flex: 1; overflow-y: auto; padding: 18px; }

.drawer-foot {
    flex: none;
    display: flex;
    gap: 8px;
    padding: 14px 18px;
    border-top: 1px solid var(--border);
    background: var(--surface-sunk);
}

/* ─── Modal ──────────────────────────────────────────────────────────────── */

.modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 420px;
    max-width: calc(100vw - 32px);
    background: var(--surface-1);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 61;
    padding: 20px;
}

/* ─── Palette de commandes ───────────────────────────────────────────────── */

.palette {
    position: fixed;
    top: 12vh;
    left: 50%;
    transform: translateX(-50%);
    width: 580px;
    max-width: calc(100vw - 24px);
    max-height: 66vh;
    background: var(--surface-1);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 61;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.palette-input {
    width: 100%;
    height: 48px;
    padding: 0 16px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border);
    font-size: 14px;
}
/* L'anneau global entoure un champ pleine largeur collé aux bords du panneau :
   il bave sur les coins arrondis. On le remplace, on ne le retire pas — la
   version précédente posait `box-shadow: none` et le champ n'indiquait alors
   plus rien du tout. Le trait du bas suffit ici : c'est la seule bordure du
   champ, la faire passer à l'accent est un changement lisible. Le champ est
   `transparent` : le trait se mesure donc sur le fond du panneau,
   `--surface-1`, où l'accent vaut 7,22:1. */
.palette-input:focus {
    box-shadow: none;
    border-bottom-color: var(--accent);
    border-bottom-width: 2px;
    padding-bottom: 0;
}

.palette-list { overflow-y: auto; padding: 6px; }

.palette-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    text-align: left;
    font-size: 13px;
    color: var(--text-muted);
}
.palette-item.sel { background: var(--surface-3); color: var(--text); }

.palette-group {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-faint);
    padding: 10px 10px 4px;
}

/* ─── Toasts ─────────────────────────────────────────────────────────────── */

.toast-host {
    position: fixed;
    bottom: 18px;
    right: 18px;
    z-index: 90;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-end;
    pointer-events: none;
}

.toast {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 260px;
    max-width: 380px;
    padding: 11px 14px;
    border-radius: var(--radius);
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    box-shadow: var(--shadow);
    font-size: 13px;
}
.toast.ok    { border-left: 3px solid var(--accent); }
.toast.error { border-left: 3px solid var(--danger); }
.toast.warn  { border-left: 3px solid var(--warn); }
.toast.info  { border-left: 3px solid var(--info); }

/* ─── Graphique ──────────────────────────────────────────────────────────── */

.chart-wrap { position: relative; height: 280px; }

/* ─── Console de logs ────────────────────────────────────────────────────── */

.console {
    background: var(--surface-sunk);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-family: var(--mono);
    font-size: 12px;
    line-height: 1.6;
    overflow: auto;
    height: calc(100vh - 250px);
    min-height: 320px;
    padding: 10px 0;
}

.log-line {
    display: flex;
    gap: 10px;
    padding: 1px 14px;
    white-space: pre-wrap;
    word-break: break-word;
}
.log-line:hover { background: var(--surface-1); }
.log-ts     { color: var(--text-faint); flex: none; }
.log-level  { flex: none; width: 62px; font-weight: 700; }
.log-module { color: var(--text-faint); flex: none; }

/* La couleur porte sur la colonne de niveau, pas sur le message : une console
   entièrement colorée redevient illisible dès qu'il y a du volume. */
.log-line { color: var(--text-muted); }
.lv-ERROR, .lv-CRITICAL { color: var(--text); }
.lv-ERROR .log-level, .lv-CRITICAL .log-level { color: var(--danger-text); }
.lv-WARNING .log-level { color: var(--warn-text); }
.lv-INFO .log-level    { color: var(--info-text); }
.lv-DEBUG              { color: var(--text-faint); }
.log-line.is-ERROR,
.log-line.is-CRITICAL { background: rgba(239, 68, 68, 0.06); }

/* ─── Divers ─────────────────────────────────────────────────────────────── */

/* Vinted n'expose aucune image dans ses emails : le placeholder est un parti
   pris assumé, pas un fallback d'image cassée. */
.thumb-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        linear-gradient(135deg, var(--surface-2) 0%, var(--surface-3) 100%);
    color: var(--text-faint);
    border-radius: var(--radius-sm);
    flex: none;
    width: 56px;
    height: 56px;
}

.thumb-wide { width: 100%; height: 104px; }

/* ─── Divulgation (options avancées) ─────────────────────────────────────── */

details > summary {
    cursor: pointer;
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    user-select: none;
}
details > summary::-webkit-details-marker { display: none; }
details > summary::before {
    content: "▸";
    font-size: 10px;
    color: var(--text-faint);
    transition: transform 0.15s ease;
}
details[open] > summary::before { transform: rotate(90deg); }
details > summary:hover { color: var(--text-muted); }

/* ─── Cases à cocher ─────────────────────────────────────────────────────── */

input[type="checkbox"] {
    accent-color: var(--accent);
    width: 14px;
    height: 14px;
    flex: none;
    cursor: pointer;
}

.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
}

.two-col {
    display: grid;
    grid-template-columns: 1.35fr 1fr;
    gap: 16px;
    align-items: start;
}

/* Sans cette ligne, les paliers responsive qui ramènent ces grilles à `1fr`
   ne servent à rien.
   Un élément de grille vaut `min-width: auto` par défaut, ce qui l'empêche de
   descendre sous sa largeur min-content — et une piste `1fr` ne peut pas
   rétrécir en dessous de ce que son élément exige. Mesuré à 375 px : la piste
   de `.card-grid` se résolvait à 462,9 px dans un conteneur de 337, et les
   cartes de comptes débordaient de 126 px, rognées et invisibles. La règle
   `grid-template-columns: 1fr` du palier 760 px était bien appliquée ; elle
   était simplement sans effet.
   `min-width: 0` rend l'arbitrage à la piste. Relevé après correction : piste
   à 337 px, plus aucun débordement sur la page. */
.card-grid > *,
.two-col > * { min-width: 0; }

.divider { height: 1px; background: var(--border); }

.dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; font-size: 13px; }
.dl dt { color: var(--text-subtle); }
.dl dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

/* ─── Pied de sidebar : santé + compte ───────────────────────────────────── */

.foot-strong {
    display: block;
    font-size: 12px;
    font-weight: 550;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.foot-health { padding-bottom: 10px; }

.account-menu { position: relative; }

.account-trigger {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 8px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    color: var(--text-muted);
    transition: background .12s ease, border-color .12s ease;
}

.account-trigger:hover {
    background: var(--surface-2);
    border-color: var(--border);
}

.account-trigger .avatar {
    width: 26px;
    height: 26px;
    font-size: 11px;
    font-weight: 650;
    background: var(--accent-soft);
    color: var(--accent-text);
}

/* Le menu s'ouvre **vers le haut** : il est ancré en bas de la sidebar, une
   ouverture vers le bas sortirait de la fenêtre. */
.account-pop {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 30;
    padding: 5px;
    border-radius: var(--radius);
    border: 1px solid var(--border-strong);
    background: var(--surface-2);
    box-shadow: var(--shadow-lg);
}

.account-head {
    padding: 8px 9px 9px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border);
}

.account-link {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 9px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text-muted);
    text-align: left;
    transition: background .12s ease, color .12s ease;
}

.account-link:hover { background: var(--surface-3); color: var(--text); }
.account-link.danger:hover { background: var(--danger-soft); color: var(--danger-text); }

/* ─── Bandeaux (essai, paiement, résiliation) ────────────────────────────── */

.banner {
    display: flex;
    align-items: center;
    gap: 11px;
    margin-bottom: 18px;
    padding: 11px 14px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface-1);
    font-size: 13px;
    color: var(--text-muted);
}

.banner strong { color: var(--text); font-weight: 600; margin-right: 5px; }
.banner span { margin-right: 5px; }
.banner-icon { display: flex; flex: none; }

.banner-info   { border-color: rgba(59, 130, 246, .35);  background: var(--info-soft); }
.banner-info   .banner-icon { color: var(--info-text); }
.banner-warn   { border-color: rgba(245, 158, 11, .35);  background: var(--warn-soft); }
.banner-warn   .banner-icon { color: var(--warn-text); }
.banner-danger { border-color: rgba(239, 68, 68, .40);   background: var(--danger-soft); }
.banner-danger .banner-icon { color: var(--danger-text); }

/* ─── Jauge d'utilisation ────────────────────────────────────────────────── */

/*
  Barre de consommation des droits (comptes utilisés / autorisés).

  La largeur du remplissage est écrite en style inline par le gabarit, à partir
  d'un ratio calculé côté serveur. Une jauge n'est rendue que lorsqu'une limite
  existe : sur une offre illimitée il n'y a rien à remplir, et un barreau à 0 %
  comme à 100 % raconterait la même contre-vérité.
*/
.gauge {
    height: 7px;
    border-radius: 99px;
    background: var(--surface-sunk);
    border: 1px solid var(--border);
    /* Sans ce rognage, les angles droits du remplissage dépasseraient des
       extrémités arrondies de la piste. */
    overflow: hidden;
}

.gauge-fill {
    height: 100%;
    border-radius: 99px;
    background: var(--accent);
    transition: width .25s ease;
}

/* Limite atteinte : la jauge pleine passe en orange. C'est un état à traiter
   (connecter un compte de plus demande un changement d'offre), pas une erreur
   — le rouge est réservé à ce qui est cassé. La couleur ne porte jamais
   l'information seule : le texte au-dessus dit « Limite atteinte ». */
.gauge-fill.is-full { background: var(--warn); }

/* ─── Choix d'offre ──────────────────────────────────────────────────────── */

/*
  `auto-fit` plutôt qu'un nombre de colonnes figé : la grille suit le catalogue.
  Ajouter ou retirer une offre dans `plans.py` ne doit pas obliger à retoucher
  la feuille de style, et le repli sur une ou deux colonnes en écran étroit
  découle de la même règle — aucune media query à maintenir en double.
*/
.plan-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 14px;
}

.plan-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: var(--surface-1);
}

/* L'offre en cours se distingue par sa bordure, pas par sa taille : des cartes
   de hauteurs différentes désaligneraient les prix et rendraient justement
   pénible la comparaison qu'on vient faire ici. */
.plan-card.is-current {
    border-color: var(--accent);
    background: var(--accent-soft);
}

/* Le descriptif porte `.grow` : il absorbe la hauteur restante et pousse les
   boutons sur une même ligne d'une carte à l'autre, quelle que soit la
   longueur des textes. */
.plan-price {
    display: flex;
    align-items: baseline;
    gap: 4px;
}

/* ─── Étapes d'installation ──────────────────────────────────────────────── */

.step {
    display: flex;
    align-items: flex-start;
    gap: 14px;
}

/* Pastille de numéro d'étape. `flex: none` est indispensable : sans lui, le
   cercle serait comprimé en ovale par le texte voisin dès qu'il s'allonge. */
.step-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    background: var(--surface-2);
    color: var(--text-subtle);
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.step-mark.is-done {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent-text);
}

/* Une étape terminée recule d'un cran : son intitulé passe en gris de texte
   courant plutôt qu'en blanc. Il reste parfaitement lisible — on ne masque
   pas ce qui a été fait, on cesse simplement de le réclamer. */
.step.is-done .strong { color: var(--text-muted); }

/* ─── Responsive ─────────────────────────────────────────────────────────── */

@media (max-width: 1150px) {
    .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .two-col  { grid-template-columns: 1fr; }
}

/* Tablette : sidebar réduite aux icônes */
@media (max-width: 1000px) {
    .sidebar { width: 62px; }

    /* Repliée, la sidebar ne montre plus que des icônes. Les libellés ne sont
       pas *supprimés* mais retirés à l'œil seul : `display: none` les sortait
       aussi de l'arbre d'accessibilité, et chaque entrée devenait un lien sans
       nom. Mesuré à 900 px avant correction : 7 liens sur 8 muets, et le
       huitième s'annonçait « 2 » — le compteur du badge tenant lieu de
       destination. Le pictogramme, lui, est décoratif : il ne peut pas
       nommer quoi que ce soit. */
    .sidebar .nav-label,
    .sidebar .brand-text,
    .sidebar .nav-group-title,
    .sidebar .foot-label,
    .foot-health > div,
    .account-trigger > span:not(.avatar) {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }
    .nav-item { justify-content: center; padding: 9px 0; }
    .nav-item.active::before { left: -10px; }
    .nav-badge {
        position: absolute;
        top: 2px;
        right: 6px;
        margin: 0;
        min-width: 15px;
        height: 15px;
        font-size: 9px;
    }
    .sidebar-brand { justify-content: center; padding: 0; }

    /* Sidebar réduite : il ne reste la place que du point de santé et de
       l'avatar. Le menu de compte s'ouvre alors en débordant vers la droite,
       sinon il ferait 62 px de large et serait illisible. */
    .sidebar-foot { padding: 12px 0; text-align: center; }
    .foot-health { justify-content: center; padding-bottom: 8px; }
    /* Le chevron, lui, n'annonce rien : le masquer ne retire aucune
       information. */
    .account-trigger > svg { display: none; }
    .account-trigger { justify-content: center; padding: 6px 0; }
    .account-pop { left: 8px; right: auto; width: 232px; }

    .app-content { padding: 20px 18px 56px; }
    .app-header { padding: 0 14px 0 18px; }
    .header-desc { display: none; }
}

/* Mobile : sidebar en drawer */
@media (max-width: 760px) {
    .sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        width: var(--sidebar-w);
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: var(--shadow-lg);
    }
    .sidebar.open { transform: translateX(0); }
    .overlay-nav { display: block; }

    /* En drawer la sidebar retrouve sa largeur pleine : les libellés
       redeviennent visibles. On annule le repli du palier tablette plutôt que
       de forcer un `display`, pour retomber exactement sur le rendu large. */
    .sidebar .nav-label,
    .sidebar .brand-text,
    .sidebar .nav-group-title,
    .sidebar .foot-label,
    .foot-health > div,
    .account-trigger > span:not(.avatar) {
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        overflow: visible;
        clip: auto;
        white-space: normal;
    }
    .nav-item { justify-content: flex-start; padding: 8px 10px; }
    .nav-badge { position: static; margin-left: auto; min-width: 18px; height: 18px; font-size: 11px; }
    .sidebar-brand { justify-content: flex-start; padding: 0 16px; }

    /* En drawer, la sidebar retrouve sa largeur pleine : on rétablit tout ce
       que le palier tablette avait replié. */
    .sidebar-foot { padding: 12px 14px; text-align: left; }
    .foot-health { justify-content: flex-start; padding-bottom: 10px; }
    .account-trigger > svg { display: block; }
    .account-trigger { justify-content: flex-start; padding: 7px 8px; }
    .account-pop { left: 0; right: 0; width: auto; }

    .banner { flex-wrap: wrap; }

    .menu-btn { display: flex; }
    .search-trigger .kbd,
    .search-trigger span { display: none; }
    .search-trigger { min-width: 0; width: 32px; padding: 0; justify-content: center; }
    .header-title { font-size: 14px; }
    .app-content { padding: 16px 14px 48px; }
    .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .kpi { padding: 13px; }
    .kpi-value { font-size: 20px; }
    .drawer { width: 100%; }
    .btn-label-sm { display: none; }
    .card-grid { grid-template-columns: 1fr; }
    .console { height: calc(100vh - 290px); }
}

@media (max-width: 460px) {
    .kpi-grid { grid-template-columns: 1fr; }
}

/* ─── Accessibilité ──────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
    .sidebar { transition: none; }
}

.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;
}

/* Hors écran tant qu'il n'a pas le focus : premier arrêt de tabulation, il
   évite de traverser toute la sidebar à chaque page. */
.skip-link {
    position: absolute;
    left: 12px;
    top: -60px;
    z-index: 100;
    padding: 9px 14px;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: #042f2a;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    transition: top .15s ease;
}

.skip-link:focus {
    top: 12px;
}
