/* PiTech-Link v5 - tier web (increment 2). Palette reprise du socle v4 (#0F1E33). */
:root {
    --navy: #0F1E33;
    --navy-2: #16294a;
    --bg: #f4f6fa;
    --card: #ffffff;
    --border: #e2e7f0;
    --text: #1b2536;
    --muted: #6b7689;
    --green: #16a34a;
    --green-bg: #dcfce7;
    --red: #dc2626;
    --red-bg: #fee2e2;
    --amber: #b45309;
    --amber-bg: #fef3c7;
    --accent: #2563eb;
}

* { box-sizing: border-box; }
body {
    margin: 0;
    font-family: 'Inter', system-ui, sans-serif;
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
}
a { color: var(--accent); text-decoration: none; }

/* --- En-tete --- */
.app-header { background: var(--navy); color: #fff; }
.app-shell { max-width: 1180px; margin: 0 auto; padding: 0 20px; }
.app-header-inner { display: flex; align-items: center; gap: 24px; height: 58px; }
.app-brand { display: inline-flex; align-items: center; gap: 8px; color: #fff; font-weight: 700;
    font-size: 1.05rem; letter-spacing: .3px; }
.app-logo { height: 34px; width: auto; display: block; }
.app-brand-tag { color: #7aa7ff; font-weight: 600; font-size: .82rem; }
.app-nav { display: flex; gap: 18px; flex: 1; }
.app-nav a { color: #b9c4d8; font-weight: 500; padding: 4px 2px; border-bottom: 2px solid transparent; }
.app-nav a.is-active, .app-nav a:hover { color: #fff; border-color: #7aa7ff; }
.app-env-badge { font-size: .72rem; color: #9fb0cc; text-transform: uppercase; letter-spacing: .5px; }

.app-main { padding: 24px 20px 48px; }

/* --- En-tete de page --- */
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
.page-title { font-size: 1.5rem; margin: 0 0 2px; }
.page-subtitle { color: var(--muted); margin: 0; font-size: .9rem; }
.page-meta { display: flex; align-items: center; gap: 8px; font-size: .82rem; color: var(--muted); white-space: nowrap; }
.back-link { font-size: .82rem; color: var(--muted); display: inline-block; margin-bottom: 6px; }
.back-link:hover { color: var(--accent); }

/* --- Tables --- */
.table-wrap { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; background: var(--card); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.data-table th { text-align: left; font-size: .72rem; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); background: #fafbfe; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.data-table td { padding: 11px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tbody tr:last-child td { border-bottom: none; }
.site-row { cursor: pointer; transition: background .12s; }
.site-row:hover { background: #f0f5ff; }
.cell-strong { font-weight: 600; }

/* --- Badges --- */
.badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: .76rem; font-weight: 600; }
.badge.is-online { color: var(--green); background: var(--green-bg); }
.badge.is-offline { color: var(--red); background: var(--red-bg); }
.badge.is-prepared { color: var(--amber); background: var(--amber-bg); }

/* --- Cartes --- */
.cards-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; margin-bottom: 18px; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 16px 18px; margin-bottom: 16px; }
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.card-title { font-size: 1rem; margin: 0 0 10px; }
.card-head .card-title { margin: 0; }
.card-head-link { color: var(--navy); font-weight: 600; font-size: .85rem; text-decoration: none; white-space: nowrap; }
.card-head-link:hover { text-decoration: underline; }
.card-foot-note { color: var(--muted); font-size: .82rem; margin: 10px 0 0; }
.card-foot-note a { color: var(--navy); }
.card-muted { background: #fafbfe; }
.card-placeholder { color: var(--muted); font-size: .86rem; font-style: italic; margin: 0; }
/* Boutons/formulaires colles au texte descriptif au-dessus : on les decolle un peu
   (cartes « Compte technicien (IHM) » et « VPN » de la fiche site). */
#ihm-reset-card .card-placeholder + button,
#vpn-card .card-placeholder + .btn,
#vpn-card .card-placeholder + form { margin-top: .85rem; }
.empty { color: var(--muted); }

.info-list { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0; }
.info-list dt { color: var(--muted); font-size: .82rem; }
.info-list dd { margin: 0; font-weight: 500; }

/* Logo partenaire (page Infos) centré */
.info-logo { text-align: center; margin: 12px 0; }
.info-logo img { height: 60px; max-width: 100%; display: inline-block; }

/* --- Indicateur temps reel --- */
.rt-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--muted); }
.rt-dot.rt-on { background: var(--green); box-shadow: 0 0 0 3px var(--green-bg); }
.rt-dot.rt-off { background: var(--red); box-shadow: 0 0 0 3px var(--red-bg); }
.rt-mini { font-size: .78rem; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }

/* --- Carte Santé Synchronic : lignes de service + voyant (carte pleine largeur) --- */
.svc-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; padding: 8px 0;
    border-top: 1px solid var(--border); }
.svc-row:first-child { border-top: none; }
.svc-row .led { width: 11px; height: 11px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
.svc-row.ok .led { background: var(--green); }
.svc-row.ko .led { background: var(--red); }
.svc-row.na .led { background: var(--muted); }
.svc-name { min-width: 0; flex: 1 1 200px; }
.svc-name strong { display: block; font-size: .9rem; }
.svc-name small { color: var(--muted); font-size: .8rem; }
#synchro-updated { margin-top: 10px; }

/* Boutons de contrôle des services Synchronic (admin) + message de verdict.
   flex-wrap + margin-left:auto : les 3 boutons restent à droite et passent à la ligne
   plutôt que de déborder de la carte sur les largeurs étroites. */
.svc-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-left: auto; flex: 0 0 auto; }
.svc-actions .btn-sm { padding: 4px 9px; font-size: .76rem; }
.svc-msg { margin: 8px 0 0; font-size: .82rem; min-height: 1em; }
/* Vide (aucune action lancee) : ne pas reserver d'espace sous le bouton. */
.svc-msg:empty { display: none; }
.svc-msg.is-pending { color: var(--muted); }
.svc-msg.is-ok { color: var(--green); }
.svc-msg.is-ko { color: var(--red); }

/* --- Grande carte « Services du poste » : sections Synchronic + VPN dans la même carte --- */
.svc-section { padding-top: 14px; margin-top: 14px; border-top: 2px solid var(--border); }
.svc-section:first-of-type { padding-top: 0; margin-top: 0; border-top: none; }
.svc-section-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    margin-bottom: 4px; }
.svc-section-title { margin: 0; font-size: .95rem; }
#vpn-updated { margin-top: 10px; }

/* Ligne d'event qui vient d'arriver (flash) */
.row-new { animation: flash-in 1.4s ease-out; }
@keyframes flash-in { from { background: #fff7cc; } to { background: transparent; } }

/* --- Boutons --- */
.btn { display: inline-block; cursor: pointer; font: inherit; font-weight: 600; font-size: .86rem;
    padding: 8px 16px; border-radius: 8px; border: 1px solid transparent; background: var(--accent);
    color: #fff; }
.btn:hover { background: #1d4fd1; }
.btn-ghost { background: transparent; color: var(--accent); border-color: var(--border); }
.btn-ghost:hover { background: #f0f4ff; }
.btn:disabled { opacity: .6; cursor: default; }
.btn-sm { padding: 6px 12px; font-size: .8rem; }

/* --- Tests & actions : ELEMENTS DU BUS (fiche site, docs/09 §11) --- */
.card-subtle { font-weight: 500; font-size: .8rem; color: var(--muted); }
.badge.is-mode { color: var(--navy); background: #eef2fa; border: 1px solid var(--border); }
.badge.is-eject { color: #92600c; background: #fde68a; }   /* jaune : zone ejectee (neutralisee) */
.badge.is-stale { color: var(--muted); background: #eef1f5; }   /* gris : poste hors ligne, etat non a jour */
.badge.is-neutral { color: var(--navy); background: #eef2fa; }  /* bleu doux : evenement neutre (page, demo) */

/* Pagination serveur (journal des acces) */
.pager { display: flex; align-items: center; justify-content: center; gap: 14px; padding: 14px 0 4px; }
.pager-info { color: var(--muted); font-size: .88rem; }
.btn.is-disabled { opacity: .45; pointer-events: none; }

/* Categorie repliable (Acces / Sorties / Entrees / Groupes) */
.elem-cat { border-top: 1px solid var(--border); }
.elem-cat:first-of-type { border-top: none; }
.elem-cat > summary { cursor: pointer; padding: 10px 2px; font-weight: 600; font-size: .92rem;
    list-style-position: inside; }
.elem-cat > summary:hover { color: var(--accent); }
.elem-count { color: var(--muted); font-weight: 500; font-size: .82rem; margin-left: 4px; }
.elem-list { padding: 2px 0 8px; }

/* Fleche maitre : deplier / replier toutes les categories d'un coup. */
.elem-toggle-all { display: inline-flex; align-items: center; gap: 6px; background: none;
    border: none; cursor: pointer; color: var(--muted); font-size: .82rem; font-weight: 600;
    padding: 8px 2px; margin-bottom: 2px; font-family: inherit; }
.elem-toggle-all:hover { color: var(--accent); }
.elem-toggle-all .caret { display: inline-block; transition: transform .15s ease; }
.elem-toggle-all.is-open .caret { transform: rotate(90deg); }

/* --- Regroupement par UG (centrale) : accordeon partage par la vue exploitation et la fiche
   site admin (static/js/ug_group.js). Sur un gros site (12 UG, 200+ portes) la liste a plat
   est inexploitable : chaque UG est repliee par defaut, son etat est memorise. --- */
.ug-group { border: 1px solid var(--border); border-radius: 10px; background: var(--card);
    margin-bottom: 10px; overflow: hidden; }
/* .ug-head est soit un <button> pilote en JS (vue exploitation, fiche site : rendu dynamique
   depuis le catalogue), soit un <summary> de <details> natif (page des droits : rendu Jinja,
   sans JS). D'ou les deux jeux de selecteurs -> .is-open (JS) et [open] (natif). */
.ug-head { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
    background: #f4f7fc; border: none; border-bottom: 1px solid transparent; cursor: pointer;
    font-family: inherit; font-size: .9rem; font-weight: 700; color: var(--text);
    padding: 11px 14px; list-style: none; }
.ug-head::-webkit-details-marker { display: none; }  /* masque le triangle natif du <summary> */
.ug-head::marker { content: ""; }
.ug-head:hover { color: var(--accent); }
.ug-group.is-open > .ug-head, .ug-group[open] > .ug-head { border-bottom-color: var(--border); }
.ug-caret { display: inline-block; color: var(--muted); font-size: 1.05rem; line-height: 1;
    transition: transform .15s ease; }
.ug-group.is-open .ug-caret, .ug-group[open] > .ug-head .ug-caret { transform: rotate(90deg); }
.ug-label { flex: 1; min-width: 0; }
.ug-count { color: var(--muted); font-weight: 600; font-size: .78rem; background: #fff;
    border: 1px solid var(--border); border-radius: 8px; padding: 1px 8px; }
/* Page des droits : cases maitresses limitees a une categorie x une UG, dans l'en-tete de
   l'accordeon. `font-weight:400` : l'en-tete est en gras, pas ces commandes secondaires. */
.ug-btns { display: flex; align-items: center; font-weight: 400; cursor: default; }
.ug-body { padding: 12px 14px; }
/* Le corps porte parfois .dev-grid (display:grid) : sans cette regle, le display l'emporterait
   sur l'attribut HTML `hidden` et le groupe ne se replierait jamais (gotcha connu, suite 7). */
.ug-body[hidden] { display: none; }
/* Fiche admin : les lignes vivent deja dans un cadre -> pas de double rembourrage lateral. */
.elem-list .ug-body { padding: 0 14px 4px; }

/* Barre « Par centrale » (page des droits d'un utilisateur) : un raccourci Voir/Piloter qui
   porte sur TOUTES les categories d'une UG a la fois. Sur un site a 12 centrales (UPPA) c'est
   la granularite reelle d'attribution des droits. */
.perm-cu-bar { border: 1px solid var(--border); border-radius: 10px; background: #f4f7fc;
    padding: 10px 14px; margin-bottom: 18px; }
.perm-cu-title { font-size: .78rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .06em; color: #444; margin-bottom: 8px; }
.perm-cu-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 5px 0; border-top: 1px solid var(--border); }
.perm-cu-row:first-of-type { border-top: none; }
.perm-cu-name { flex: 1; min-width: 160px; display: flex; align-items: center; gap: 8px;
    font-size: .9rem; font-weight: 700; }

/* Paire de cases maitresses « Voir / Piloter » (barre par centrale, en-tetes de categorie et
   d'UG). Une maitresse INDETERMINEE = portee partiellement accordee : c'est l'information que
   des boutons Tout/Rien ne donnaient pas. */
.perm-master { display: flex; align-items: center; gap: 14px; font-size: .78rem;
    font-weight: 400; color: var(--muted); white-space: nowrap; }
.perm-master label { display: flex; align-items: center; gap: 5px; cursor: pointer; }
.perm-master input { width: 15px; height: 15px; cursor: pointer; margin: 0; }
.perm-master input:disabled { cursor: default; }
.perm-master label:has(input:disabled) { opacity: .45; cursor: default; }

.ug-search { margin-bottom: 12px; }
.ug-search-input { width: 100%; max-width: 420px; padding: 9px 12px; font-family: inherit;
    font-size: 16px; /* >=16px : evite le zoom automatique du champ sur iOS */
    border: 1px solid var(--border); border-radius: 8px; background: #fff; color: var(--text); }
.ug-search-input:focus { outline: none; border-color: var(--accent); }

.elem-row { border-top: 1px solid var(--border); padding: 12px 0; }
.elem-row:first-child { border-top: none; }
.elem-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.elem-head strong { display: block; font-size: .92rem; }
.elem-head small { color: var(--muted); font-size: .8rem; }
.elem-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.elem-verdict { display: block; margin-top: 8px; font-size: .82rem; min-height: 1em; }
.elem-verdict.is-pending { color: var(--muted); }
.elem-verdict.is-ok { color: var(--green); }
.elem-verdict.is-ko { color: var(--red); }

/* Envoi de telecommande GTC (saisie manuelle) */
.tlc-fields { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-top: 8px; }
.tlc-field { display: flex; flex-direction: column; gap: 4px; font-size: .82rem; color: var(--muted); }
.tlc-field select, .tlc-field input { font: inherit; color: var(--text); padding: 7px 9px;
    border: 1px solid var(--border); border-radius: 7px; background: #fff; min-width: 160px; }
.tlc-actions { display: flex; gap: 8px; align-items: center; }

/* Flux d'evenements (fiche site) : hauteur bornee + scroll, en-tete collant */
.events-scroll { max-height: 440px; overflow-y: auto; }
.events-scroll thead th { position: sticky; top: 0; z-index: 1; }

/* --- Journal : barre de filtres --- */
.filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-bottom: 16px;
    background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; }
.filter-field { display: flex; flex-direction: column; gap: 4px; }
.filter-field > span { font-size: .72rem; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); }
.filter-field input, .filter-field select { font: inherit; padding: 7px 9px; border: 1px solid var(--border);
    border-radius: 7px; background: #fff; color: var(--text); min-width: 130px; }
.filter-field input:focus, .filter-field select:focus { outline: none; border-color: var(--accent); }
.filter-grow { flex: 1; min-width: 180px; }
.filter-grow input { width: 100%; }
.filter-actions { display: flex; gap: 8px; margin-left: auto; }

/* --- Journal : details d'un event + charger plus --- */
.evt-more summary { cursor: pointer; color: var(--accent); font-size: .82rem; }
.evt-detail { display: grid; grid-template-columns: max-content 1fr; gap: 2px 12px; margin: 8px 0 2px;
    font-size: .82rem; }
.evt-detail dt { color: var(--muted); }
.evt-detail dd { margin: 0; word-break: break-word; }
.evt-detail code { font-size: .8rem; background: #f4f6fa; padding: 1px 5px; border-radius: 4px; }
.load-more-wrap { text-align: center; margin-top: 14px; }
.journal-link { font-size: .82rem; margin-right: 12px; }

/* --- Barre utilisateur (header) --- */
.app-user-bar { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.app-user-email { color: #b9c4d8; font-size: .82rem; }
.app-logout { color: #9fb0cc; font-size: .82rem; }
.app-logout:hover { color: #fff; }

/* --- Alertes --- */
.alert { padding: 10px 14px; border-radius: 8px; font-size: .88rem; margin-bottom: 14px; }
.alert-ok { background: var(--green-bg); color: var(--green); border: 1px solid #bbf7d0; }
.alert-error { background: var(--red-bg); color: var(--red); border: 1px solid #fecaca; }

/* --- Boutons nommés (admin) --- */
.btn-primary { display: inline-block; cursor: pointer; font: inherit; font-weight: 600; font-size: .86rem;
    padding: 8px 16px; border-radius: 8px; border: none; background: var(--accent); color: #fff; }
.btn-primary:hover { background: #1d4fd1; color: #fff; }
.btn-secondary { display: inline-block; cursor: pointer; font: inherit; font-weight: 600; font-size: .86rem;
    padding: 8px 16px; border-radius: 8px; border: 1px solid var(--border);
    background: var(--card); color: var(--text); }
.btn-secondary:hover { border-color: var(--accent); color: var(--accent); }
.btn-sm { display: inline-block; cursor: pointer; font: inherit; font-size: .8rem; font-weight: 500;
    padding: 5px 10px; border-radius: 6px; border: 1px solid var(--border);
    background: var(--card); color: var(--text); }
.btn-sm:hover { border-color: var(--accent); color: var(--accent); }
.btn-ok { border-color: #bbf7d0; color: var(--green); background: var(--green-bg); }
.btn-ok:hover { background: #bbf7d0; }
.btn-warn { border-color: #fecaca; color: var(--red); background: var(--red-bg); }
.btn-warn:hover { background: #fecaca; }

/* --- Section Administration : barre d'onglets (façon vue exploitation) --- */
.admin-menu { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 20px; padding-bottom: 8px;
    border-bottom: 1px solid var(--border); }
.admin-menu a { color: var(--muted); font-weight: 500; font-size: .9rem; padding: 7px 14px;
    border-radius: 8px; }
.admin-menu a:hover { background: #eef2fa; color: var(--text); }
.admin-menu a.is-active { background: var(--navy); color: #fff; }

/* Menus deroulants de la barre Administration (regroupement des onglets) */
.admin-menu { align-items: center; }
.admin-group { position: relative; }
.admin-group-btn { display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
    background: none; border: 0; font: inherit; color: var(--muted); font-weight: 500;
    font-size: .9rem; padding: 7px 14px; border-radius: 8px; }
.admin-group-btn:hover { background: #eef2fa; color: var(--text); }
.admin-group-btn .caret { font-size: 1.15rem; line-height: 1; transition: transform .15s ease; }
.admin-group:hover .admin-group-btn .caret,
.admin-group.is-open .admin-group-btn .caret { transform: rotate(180deg); }
.admin-group.is-active .admin-group-btn { background: var(--navy); color: #fff; }
.admin-submenu { position: absolute; top: 100%; left: 0; z-index: 40; display: none;
    min-width: 190px; flex-direction: column; gap: 2px; margin-top: 4px; padding: 6px;
    background: #fff; border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 10px 28px rgba(15, 23, 42, .14); }
.admin-group:hover .admin-submenu,
.admin-group:focus-within .admin-submenu,
.admin-group.is-open .admin-submenu { display: flex; }
.admin-submenu a { padding: 8px 12px; border-radius: 7px; white-space: nowrap; }

/* --- Tableau de bord admin : cartes chiffres + accès rapides + santé --- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px;
    margin-bottom: 18px; }
.stat-card { background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 16px 18px; }
.stat-label { font-size: .74rem; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); }
.stat-value { font-size: 1.9rem; font-weight: 700; line-height: 1.1; margin-top: 4px; }
.stat-frac { font-size: 1rem; font-weight: 600; color: var(--muted); }
.stat-sub { font-size: .78rem; color: var(--muted); margin-top: 2px; }

.dash-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.health-list { display: flex; flex-direction: column; }
.health-row { display: flex; align-items: center; gap: 10px; padding: 9px 0;
    border-top: 1px solid var(--border); color: var(--text); }
.health-row:first-child { border-top: none; }
.health-row:hover { color: var(--accent); }
.health-led { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); flex: 0 0 auto; }
.health-led.ko { background: var(--red); }
.health-name { font-weight: 500; }
.health-name small { color: var(--muted); font-weight: 400; }
.health-meta { margin-left: auto; font-size: .8rem; color: var(--muted); }
.health-ok { color: var(--green); font-size: .88rem; margin: 6px 0 0; }

/* --- Formulaires admin --- */
.admin-form .form-group { margin-bottom: 12px; }
.admin-form .form-group label { display: block; font-size: .82rem; font-weight: 500; color: var(--muted); margin-bottom: 4px; }
.admin-form .form-group input, .admin-form .form-group select, .admin-form .form-group textarea {
    width: 100%; font: inherit; font-size: .9rem; padding: 7px 10px;
    border: 1px solid var(--border); border-radius: 7px; background: var(--bg); color: var(--text); }
.admin-form .form-group input:focus, .admin-form .form-group select:focus { outline: none; border-color: var(--accent); }
/* Cases a cocher / radios : garder leur taille naturelle (sinon width:100% les etire en gros blocs). */
.admin-form .form-group input[type=radio], .admin-form .form-group input[type=checkbox] {
    width: auto; padding: 0; margin-right: 6px; vertical-align: middle; }
.hint { font-size: .75rem; color: var(--muted); font-weight: 400; }
.actions-cell { white-space: nowrap; }

/* Formulaires inline (table utilisateurs) */
.inline-details { display: inline-block; position: relative; }
.inline-details > summary { list-style: none; }
.inline-details > summary::-webkit-details-marker { display: none; }
.inline-form { display: flex; gap: 6px; align-items: center; margin-top: 6px;
    background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; }
.inline-form input, .inline-form select { font: inherit; font-size: .82rem; padding: 4px 7px;
    border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); }

/* --- Formulaire « Créer un client VPN » + actions par ligne (page /admin/vpn) --- */
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px;
    align-items: end; }
.form-grid label { display: flex; flex-direction: column; gap: 4px; font-size: .82rem;
    font-weight: 600; color: var(--muted); }
.form-grid input, .form-grid select { font: inherit; font-size: .88rem; padding: 7px 9px;
    border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); }
.form-actions { display: flex; align-items: end; }
.vpn-row-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.vpn-row-actions .inline-form { margin-top: 0; }

/* --- Champs mot de passe : bouton afficher/masquer (password_toggle.js) --- */
.pw-wrap { position: relative; display: inline-block; }
.pw-toggle { position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    background: none; border: none; cursor: pointer; padding: 2px; margin: 0;
    color: var(--muted); line-height: 0; }
.pw-toggle:hover { color: var(--accent); }
.pw-toggle svg { width: 18px; height: 18px; display: block; }

/* Barre d'actions groupees (item ⑥) : sur les listes admin (utilisateurs, orgs, sites, actions). */
.bulk-bar { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;
    margin-bottom: 0.8rem; padding: 0.6rem 0.8rem; background: var(--bg);
    border: 1px solid var(--border); border-radius: 8px; }
.bulk-lbl { font-size: 0.85rem; color: var(--muted); font-weight: 600; }
.bulk-bar select { padding: 0.35rem 0.5rem; }
.bulk-del { background: #dc2626; border-color: #dc2626; color: #fff; }
.bulk-del:hover { opacity: 0.9; }

/* --- Vue EXPLOITATION (non-admin) : menu d'onglets (façon v4, desktop) --- */
.user-menu { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 20px; padding-bottom: 8px;
    border-bottom: 1px solid var(--border); }
.user-menu a { color: var(--muted); font-weight: 500; font-size: .9rem; padding: 7px 14px;
    border-radius: 8px; }
.user-menu a:hover { background: #eef2fa; color: var(--text); }
.user-menu a.is-active { background: var(--navy); color: #fff; }
.user-menu .user-menu-switch { margin-left: auto; color: var(--accent); }
.user-menu .user-menu-switch:hover { background: #eef4ff; }

/* --- Hamburger + tiroir de navigation mobile (non-admin) --- */
/* Par défaut (desktop) : hamburger et tiroir masqués ; la barre d'onglets sert de nav. */
.app-burger { display: none; background: transparent; border: none; color: #fff; cursor: pointer;
    font-size: 1.5rem; line-height: 1; width: 42px; height: 42px; padding: 0; }
.app-drawer { position: fixed; top: 0; left: -320px; width: 270px; height: 100%; background: var(--card);
    border-right: 1px solid var(--border); box-shadow: 0 10px 30px rgba(0, 0, 0, .18); z-index: 2000;
    transition: left .25s ease; overflow-y: auto; padding: 14px; }
.app-drawer.is-open { left: 0; }
.app-drawer-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.app-drawer-head span { font-weight: 700; color: var(--muted); text-transform: uppercase;
    font-size: .74rem; letter-spacing: .5px; }
.app-drawer-close { background: none; border: none; font-size: 1.4rem; color: var(--muted); cursor: pointer;
    line-height: 1; padding: 0 4px; }
.app-drawer-nav a { display: block; padding: 13px 14px; border: 1px solid var(--border); border-radius: 12px;
    color: var(--text); font-weight: 500; font-size: .98rem; margin-bottom: 9px; background: #f7f9fd; }
.app-drawer-nav a.is-active { background: var(--navy); color: #fff; border-color: var(--navy); }
.app-drawer-nav .app-drawer-switch { color: var(--accent); background: #eef4ff; }
/* Déconnexion en bas du tiroir : séparée, discrète (rouge sobre). */
.app-drawer-nav .app-drawer-logout { margin-top: 14px; border-color: #fecaca; color: var(--red);
    background: var(--red-bg); }
.app-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .38); z-index: 1500; display: none; }
.app-overlay.is-open { display: block; }

/* Cases à cocher (Paramètres) */
.user-check { display: flex; align-items: center; gap: 9px; padding: 8px 0; font-size: .9rem; }
.user-check input { width: 16px; height: 16px; }

/* --- Vue EXPLOITATION (non-admin) : cartes friendly par élément (aspect v4) --- */
.user-offline-banner { background: var(--red-bg); color: var(--red); border: 1px solid #fecaca;
    border-radius: 8px; padding: 10px 14px; font-size: .88rem; font-weight: 600; margin-bottom: 16px; }
.user-readonly-note { background: var(--amber-bg); color: var(--amber); border: 1px solid #fde68a;
    border-radius: 8px; padding: 10px 14px; font-size: .86rem; margin-bottom: 16px; }

.user-cat { margin-bottom: 24px; }
.user-cat-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; }
.user-cat-head h2 { font-size: 1.1rem; margin: 0; }
.user-cat-count { color: var(--muted); font-size: .85rem; }

.dev-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 14px; }
.dev-grid .card-placeholder { grid-column: 1 / -1; }
.dev-card { background: var(--card); border: 1px solid var(--border); border-radius: 10px;
    padding: 14px 16px; display: flex; flex-direction: column; }
.dev-card.is-alert { border-color: #fca5a5; box-shadow: 0 0 0 1px #fca5a5 inset; }
/* Liseres d'etat (decision Al) : Portes bloque=rouge/libre=vert ; Groupes arme=rouge/desarme=vert ;
   Zones exclu=orange/alarme=rouge. Definis apres .is-alert pour l'emporter (meme specificite). */
.dev-card.edge-red { border-color: var(--red); box-shadow: 0 0 0 2px var(--red) inset; }
.dev-card.edge-green { border-color: var(--green); box-shadow: 0 0 0 2px var(--green) inset; }
.dev-card.edge-amber { border-color: #f59e0b; box-shadow: 0 0 0 2px #f59e0b inset; }
.dev-name { font-size: .98rem; margin: 0 0 10px; display: flex; align-items: baseline; gap: 8px;
    flex-wrap: wrap; }
.dev-tag { font-size: .72rem; font-weight: 500; color: var(--muted); background: #eef2fa;
    border: 1px solid var(--border); border-radius: 8px; padding: 1px 7px; }
/* Page « Actions personnalisees » (vue exploitation) : description + reference TLC discrete. */
.dev-desc { font-size: .85rem; color: var(--muted); margin: 0 0 10px; }
.dev-tlc-ref { font-size: .76rem; color: var(--muted); margin: 0 0 10px; opacity: .8; }

.dev-state { background: #f4f7fc; border: 1px solid var(--border); border-radius: 8px;
    padding: 10px 12px; margin-bottom: 12px; }
.dev-state-title { font-size: .7rem; text-transform: uppercase; letter-spacing: .4px;
    color: var(--muted); margin-bottom: 3px; }
.dev-state-value { font-size: 1.05rem; font-weight: 700; }
.dev-state-value.s-green { color: var(--green); }
.dev-state-value.s-red { color: var(--red); }
.dev-state-value.s-amber { color: var(--amber); }
.dev-state-value.s-muted { color: var(--text); }

.dev-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: auto; }
.dev-btns .btn { width: 100%; text-align: center; }
.dev-btns .btn.is-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.dev-btns .btn.is-primary:hover { background: #1d4fd1; color: #fff; }
.dev-verdict { margin-top: 8px; font-size: .8rem; min-height: 1em; }
.dev-verdict.is-pending { color: var(--muted); }
.dev-verdict.is-ok { color: var(--green); }
.dev-verdict.is-ko { color: var(--red); }

/* Derniers événements (vue user) : liste compacte */
.user-events { max-height: 360px; overflow-y: auto; }
.user-event-line { display: grid; grid-template-columns: 1fr 2fr auto; gap: 10px; align-items: baseline;
    padding: 7px 0; border-top: 1px solid var(--border); font-size: .84rem; }
.user-event-line:first-child { border-top: none; }
.user-event-line .ev-cu { color: var(--muted); }
.user-event-line .ev-time { color: var(--muted); font-size: .78rem; white-space: nowrap; }

/* --- Responsive (mobile : vue exploitation utilisable au smartphone) --- */
@media (max-width: 900px) {
    /* Onglets exploitation ET administration : barre scrollable horizontalement plutôt
       qu'un retour à la ligne (9 onglets admin tenaient sur 2-3 lignes sur mobile). */
    .user-menu, .admin-menu { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
        gap: 2px; padding-bottom: 6px; scrollbar-width: none; }
    .user-menu::-webkit-scrollbar, .admin-menu::-webkit-scrollbar { display: none; }
    .user-menu a, .admin-menu a { white-space: nowrap; }
    .user-menu a { padding: 7px 12px; }
    .user-menu .user-menu-switch { margin-left: 0; }
    /* Barre admin : on GARDE les 3 deroulants sur mobile (6 entrees seulement, ouverture au tap).
       Elle repasse en flex-wrap : l'overflow-x scrollable couperait les popups absolus. */
    .admin-menu { flex-wrap: wrap; overflow: visible; }
    .admin-submenu { min-width: 180px; max-width: calc(100vw - 24px); }
}

/* Mobile : la barre d'onglets disparaît au profit du menu hamburger (tiroir).
   Le header se réduit au logo + hamburger : email/rôle/déconnexion partent dans le tiroir. */
@media (max-width: 768px) {
    .user-menu { display: none; }
    .app-burger { display: inline-flex; align-items: center; justify-content: center; }
    /* La barre user (email + Déconnexion) n'est masquée QUE lorsqu'un hamburger la remplace
       (le tiroir contient alors la Déconnexion). Sur les pages admin pures il n'y a pas de
       hamburger : on garde la barre visible, sinon l'admin ne peut plus se déconnecter au
       téléphone. */
    .has-burger .app-user-bar { display: none; }
}

@media (max-width: 640px) {
    /* Marges resserrées pour gagner de la largeur utile sur petit écran. */
    .app-shell { padding: 0 14px; }
    .app-main { padding: 18px 14px 40px; }

    /* Éléments un peu plus grands au doigt (cartes / états / boutons / titres). */
    .page-title { font-size: 1.4rem; }
    .dev-card { padding: 16px 18px; }
    .dev-name { font-size: 1.08rem; }
    .dev-state { padding: 12px 14px; }
    .dev-state-value { font-size: 1.18rem; }
    .dev-btns { gap: 10px; }
    .dev-btns .btn { padding: 12px; font-size: .95rem; }
    .user-event-line { font-size: .9rem; }
    .card-title { font-size: 1.08rem; }

    /* En-tête mobile : logo (gauche) + hamburger (droite) ; le reste part dans le tiroir. */
    .app-header-inner { gap: 12px; }
    .app-logo { height: 34px; }
    .app-env-badge { display: none; }
    /* Barre user admin (pages sans hamburger) : on garde « Déconnexion » mais on masque
       l'email pour ne pas encombrer l'en-tête sur très petit écran. */
    .app-user-email { display: none; }

    /* En-têtes de page + grilles passent en colonne unique. */
    .page-header { flex-direction: column; }
    .cards-grid { grid-template-columns: 1fr; gap: 12px; }
    .dev-grid { grid-template-columns: 1fr; gap: 12px; }
    .info-list { grid-template-columns: 1fr; gap: 2px 0; }
    .info-list dd { margin-bottom: 8px; }

    /* Tables : on laisse défiler horizontalement (.table-wrap = overflow-x:auto) plutôt que
       de masquer silencieusement une colonne — aucune donnée n'est cachée, comportement
       cohérent sur toutes les tables (admin comme exploitation). */

    /* Filtres du journal : champs pleine largeur, actions alignées à gauche. */
    .filter-field, .filter-grow { flex: 1 1 100%; }
    .filter-field input, .filter-field select { min-width: 0; width: 100%; }
    .filter-actions { margin-left: 0; }

    /* Éléments du bus (fiche site admin) : action et états empilés. */
    .elem-top { flex-direction: column; }
    .elem-actions .btn { flex: 1 1 calc(50% - 4px); }
    .tlc-field, .tlc-field select, .tlc-field input { min-width: 0; width: 100%; }
    .tlc-fields { flex-direction: column; align-items: stretch; }

    /* Saisie de formulaire : police >= 16px pour éviter le zoom auto iOS. */
    .admin-form .form-group input, .admin-form .form-group select,
    .admin-form .form-group textarea { font-size: 16px; }
}

/* ── Page Sécurité (posture + Fail2ban) ── */
.sec-group { background: var(--card-bg, #fff); }
.sec-group-title { margin: 0 0 10px; font-size: .95rem; font-weight: 600; color: var(--navy); }
.sec-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.sec-item { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.sec-pill { flex: 0 0 auto; min-width: 20px; text-align: center; padding: 2px 7px; }
.sec-text { display: flex; flex-direction: column; }
.sec-label { font-weight: 600; font-size: .86rem; }
.sec-detail { color: var(--muted); font-size: .8rem; }
/* Bouton d'acquittement d'une alerte « agent refuse » (suite 40) : pousse a droite de la
   ligne, revient sous le texte quand la place manque (.sec-item est flex-wrap). */
.sec-ack { margin-left: auto; flex: 0 0 auto; align-self: center; }
.sec-jail { margin-top: 16px; }
.sec-jail-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.sec-jailname { font-size: .76rem; color: var(--muted); background: #f3f4f6; padding: 2px 7px; border-radius: 5px; font-weight: 500; }
.sec-jail-stats { margin: 14px 0; }
.sec-ip { font-weight: 600; color: var(--red); }

/* Bouton d'aide « ? » (dans un card-head) + fenetre modale d'aide */
.help-btn { flex: none; width: 24px; height: 24px; border-radius: 50%; border: 1px solid var(--border);
    background: var(--bg); color: var(--muted); font-weight: 700; font-size: .85rem; line-height: 1;
    cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.help-btn:hover { color: var(--accent); border-color: var(--accent); }

.modal-overlay { position: fixed; inset: 0; background: rgba(15, 30, 51, .55); z-index: 1000;
    display: flex; align-items: flex-start; justify-content: center; padding: 24px 16px; overflow-y: auto; }
.modal-overlay[hidden] { display: none; }
.modal { background: var(--card); border-radius: 12px; max-width: 640px; width: 100%;
    box-shadow: 0 20px 50px rgba(15, 30, 51, .35); margin: auto; }
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 16px 20px; border-bottom: 1px solid var(--border); }
.modal-head h3 { margin: 0; font-size: 1.02rem; }
.modal-close { background: none; border: none; font-size: 1.5rem; line-height: 1; color: var(--muted);
    cursor: pointer; padding: 0 4px; }
.modal-close:hover { color: var(--text); }
.modal-body { padding: 16px 20px 22px; font-size: .9rem; line-height: 1.5; }
.modal-body h4 { margin: 18px 0 6px; font-size: .92rem; }
.modal-body h4:first-child { margin-top: 0; }
.modal-body ol, .modal-body ul { margin: 6px 0; padding-left: 20px; }
.modal-body li { margin: 5px 0; }
.modal-body code { background: var(--bg); padding: 1px 5px; border-radius: 4px; font-size: .84em; }
.modal-note { background: var(--amber-bg); border-radius: 8px; padding: 12px 14px; margin-top: 16px; }
.modal-note h4 { margin-top: 0; }
/* Barre de boutons d'une modale de formulaire (ex. confirmation de suppression). */
.modal-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; margin-top: 16px; }

/* ---------------------------------------------------------------------------
   LICENCE (suite 33, calque v4) - badge ambre, banniere d'avertissement,
   page bloquante « Acces suspendu », page /admin/licences.
   --------------------------------------------------------------------------- */

/* Badge « expire bientot » (ambre). Les 3 autres statuts reutilisent des classes
   existantes : is-online (valide), is-offline (expiree), is-neutral (illimitee). */
.badge.is-warn { color: var(--amber); background: var(--amber-bg); }

/* Banniere NON bloquante (<= 30 j avant echeance), sous le header, pages d'exploitation. */
.lic-banner { display: flex; align-items: center; gap: 12px; margin: 14px auto 0;
    padding: 10px 14px; border-radius: 8px; font-size: .88rem;
    background: var(--amber-bg); color: var(--amber); border: 1px solid #fde68a; }
.lic-banner-txt { flex: 1; }
.lic-banner-close { background: none; border: none; color: inherit; font-size: 1.3rem;
    line-height: 1; cursor: pointer; padding: 0 4px; opacity: .7; }
.lic-banner-close:hover { opacity: 1; }

/* Page bloquante (403) servie a la place de l'exploitation d'un site a licence echue. */
.lic-suspended { max-width: 560px; margin: 8vh auto; text-align: center; background: var(--card);
    border: 1px solid var(--border); border-radius: 12px; padding: 40px 28px; }
.lic-suspended-icon { font-size: 2.6rem; line-height: 1; margin-bottom: 10px; }
.lic-suspended .page-title { margin: 0 0 14px; }
.lic-suspended-lead { font-size: .98rem; line-height: 1.6; margin: 0 0 12px; }
.lic-suspended-note { font-size: .88rem; color: var(--muted); line-height: 1.6; margin: 0 0 24px; }
.lic-suspended-actions { display: flex; gap: 10px; justify-content: center; align-items: center; }

/* Page /admin/licences : bandeau de synthese (compteurs par statut). */
.lic-summary { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.lic-summary-item { flex: 1; min-width: 120px; background: var(--card); border: 1px solid var(--border);
    border-radius: 10px; padding: 12px 14px; }
.lic-summary-n { font-size: 1.5rem; font-weight: 700; line-height: 1.1; }
.lic-summary-l { font-size: .8rem; color: var(--muted); margin-top: 2px; }
.lic-summary-item.is-alert .lic-summary-n { color: var(--red); }
.lic-summary-item.is-warn .lic-summary-n { color: var(--amber); }

/* Formulaire d'echeance par ligne (date + raccourcis de duree). */
.lic-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.lic-form input[type=date] { width: 148px; }
.lic-days { font-size: .8rem; color: var(--muted); white-space: nowrap; }
