/* ============================================================
   CLIENT PORTAL — petzerhiel.lu
   Dark/blur theme matching the main site aesthetic
   ============================================================ */

/* ─── Base ───────────────────────────────────────────────── */
/* Sprint 65 R2 hotfix v6 : --pz-primary et --pz-secondary supprimés ici
   (redondance avec tokens.css qui les définit + bascule via body.portal-page).
   Bug : portal.css :root écrasait silencieusement tokens.css :root + cassait
   cohérence avec <style id="pzUserColors"> en mode AUTO sans data-theme. */
* { margin: 0; padding: 0; box-sizing: border-box; }

/* Sprint 76 V1bis (hotfix iPad/Safari) : html background harmonisé clair/sombre.
 * Bug Arnaud : sur iPad, quand on tire la page (rubber-band overscroll iOS),
 * Safari révèle le fond <html> qui était par défaut blanc → flash blanc en
 * mode sombre. Fix : <html> hérite du même var(--pz-bg-body) que <body>.
 * `:has()` (Safari iOS 15.4+, mai 2022) bascule en mode clair. Fallback
 * @media prefers-color-scheme pour navigateurs older.
 * `overscroll-behavior: none` désactive aussi le scroll-chaining qui peut
 * faire rebondir la page derrière le clavier mobile. */
html {
    background-color: var(--pz-bg-body);
    /* Empêche le rubber-band scroll sur iOS hors zones scrollables internes. */
    overscroll-behavior: none;
}
html:has(body.light-mode) {
    background-color: var(--pz-bg-body, #f8fafc);
}
@media (prefers-color-scheme: light) {
    html:not(:has(body:not(.light-mode))) {
        background-color: var(--pz-bg-body, #f8fafc);
    }
}

body.portal-page {
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    min-height: 100vh;
    /* S210 (Q-FOOTER-STICKY) — colonne flex : le footer (margin-top:auto) se cale en bas du
       viewport même quand le contenu est court (page d'accueil courte = retour Arnaud). */
    display: flex;
    flex-direction: column;
    /* Sprint 65 R3 : --pz-text-primary bascule auto via tokens.css selon mode.
       --pz-bg-body personnalisable par user via Settings > Affichage. */
    color: var(--pz-text-primary, #fff);
    background: var(--pz-bg-body);
    background-image:
        radial-gradient(ellipse at 20% 50%, color-mix(in srgb, var(--pz-primary, #0ea5e9) 8%, transparent) 0%, transparent 60%),
        radial-gradient(ellipse at 80% 20%, rgba(0, 80, 120, 0.1) 0%, transparent 50%);
    /* Sprint 76 V1bis : empêche le rubber-band qui révélait le blanc html sur iPad. */
    overscroll-behavior-y: none;
}

/* ─── Liens de contenu (S153 — directive Arnaud « plus de liens bleus sur fond sombre ») ──
   Un <a> de CONTENU sans couleur héritait le bleu navigateur (#0000EE), illisible sur fond sombre.
   ⚠️ S153 fix Arnaud « du bleu PARTOUT » : la 1ère version ciblait TOUS les <a>, donc repeignait
   les COMPOSANTS liens (tuiles KPI mode=link, cartes cockpit, modules compta, tuiles panorama) en
   bleu via héritage (.pz-kpi-value{color:inherit}). On cible désormais UNIQUEMENT les liens de
   contenu SANS classe (`a:not([class])`) : les composants ont tous une classe → jamais touchés. */
body.portal-page a:not([class]),
body.admin-body a:not([class]) {
    color: var(--pz-link, #60a5fa);
}
body.portal-page a:not([class]):hover,
body.admin-body a:not([class]):hover {
    color: var(--pz-primary-hover, #0369a1);
}
/* Exceptions : éléments qui portent déjà leur propre couleur (boutons, nav, tuiles cliquables,
   badges) ne doivent pas être repeints en couleur de lien. */
body.portal-page a.btn-primary,
body.portal-page a.btn-sm,
body.portal-page a.btn-secondary,
body.portal-page a.btn-danger,
body.portal-page a.btn-outline,
body.portal-page a.pz-dt-action,
/* S183 V_A.5 (retour Arnaud) — a.pz-dt-row-action RETIRÉ du neutralize `color:inherit` :
   le bouton œil <a> héritait la couleur de cellule (blanc) au lieu de la couleur du
   composant (.pz-dt-row-action = var(--pz-primary) vert, comme le bouton edit <button>).
   Règle de lien de base = a:not([class]) (l.55) → pas de repeint bleu. Œil-lien vert partout. */
body.portal-page a[class*="-pill"],
body.admin-body a.btn-primary,
body.admin-body a.btn-sm,
body.admin-body a.pz-dt-action,
/* S153 retour Arnaud — la CHROME (topbar/sidebar/bottombar/dropdowns/picker) garde ses propres
   couleurs (issues du color picker Sidney) : la règle de lien de CONTENU ne doit pas la repeindre
   en bleu. On neutralise tous les liens des conteneurs de navigation. */
body.portal-page .pz-topbar a, body.admin-body .pz-topbar a,
body.portal-page .portal-topbar a,
body.portal-page .pz-sidebar a, body.admin-body .pz-sidebar a,
body.portal-page .sidebar-nav a, body.admin-body .sidebar-nav a,
body.portal-page .pz-bottombar a, body.admin-body .pz-bottombar a,
body.portal-page .pz-dropdown a, body.admin-body .pz-dropdown a,
body.portal-page a.pz-dropdown-item, body.admin-body a.pz-dropdown-item,
body.portal-page a.pz-bb-item, body.admin-body a.pz-bb-item {
    color: inherit;
}

/* ─── Topbar ─────────────────────────────────────────────── */
.portal-topbar {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 52px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 28px;
    z-index: 200;
    gap: 16px;
}
.topbar-left {
    display: flex;
    align-items: center;
    gap: 20px;
    min-width: 0;
}
/* Topbar logo — uniform "petzerhiel.lu" in lowercase white, medium-semibold weight */
.topbar-logo {
    text-decoration: none;
    display: inline-flex;
    align-items: baseline;
    font-size: 1.2rem;
    font-weight: 600;
    color: var(--pz-text-on-primary, #fff);
    text-transform: lowercase;
    letter-spacing: -0.3px;
}

.topbar-nav {
    display: flex;
    align-items: center;
    gap: 14px;
    font-size: .85rem;
    line-height: 1;
}
/* Breadcrumb contexte — Sprint 08 hotfix : aligné sur le bord droit de la
   sidebar (280px) pour créer une grille visuelle cohérente avec le contenu. */
.topbar-ctx-nav {
    position: absolute;
    left: 280px;
    top: 0;
    height: 52px;
    display: flex;
    align-items: center;
    gap: 14px;
    padding-left: 20px;
    font-size: .85rem;
    line-height: 1;
    pointer-events: none;
}
.topbar-ctx-nav > * { pointer-events: auto; }
.topbar-ctx-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: .85rem;
    font-weight: 500;
    color: var(--pz-primary, #0ea5e9);
    padding: 4px 4px;
    text-decoration: none;
    transition: color .15s, opacity .15s;
    opacity: 0.9;
}
.topbar-ctx-link:hover {
    color: var(--pz-text-on-primary, #fff);
    opacity: 1;
}
.topbar-ctx-chev {
    display: inline-block;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.7;
    transform: translateY(-1px);
}
.topbar-ctx-sep {
    color: rgba(255, 255, 255, 0.45);
    font-size: .85rem;
    font-weight: 300;
}
.topbar-ctx-current {
    color: rgba(255, 255, 255, 0.7);
    font-size: .85rem;
    font-weight: 500;
    letter-spacing: 0.1px;
}

/* Topbar right — liens typographiques (pas de boutons) alignés verticalement */
.topbar-right { display: flex; align-items: center; gap: 22px; }
.topbar-link {
    display: inline-flex;
    align-items: center;
    font-family: inherit;
    font-size: .85rem;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.7);
    text-decoration: none;
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    cursor: pointer;
    letter-spacing: 0.1px;
    line-height: 1;
    transition: color .15s;
}
.topbar-link:hover { color: var(--pz-text-on-primary, #fff); }
/* 'Accueil' : lien principal de retour, blanc franc — hiérarchie plus forte
   que 'Syndic' qui est un breadcrumb métier. */
.topbar-link-home {
    color: var(--pz-text-on-primary, #fff);
    font-weight: 500;
}
.topbar-link-home:hover { color: var(--pz-text-on-primary, #fff); opacity: 0.85; }
.topbar-link-home.active { color: var(--pz-primary, #0ea5e9); }
.topbar-link-user {
    color: rgba(255, 255, 255, 0.85);
}
.topbar-link-user:hover { color: var(--pz-primary, #0ea5e9); }
.topbar-link-logout {
    color: var(--pz-urgent, #f87171);
}
.topbar-link-logout:hover { color: var(--pz-urgent-soft, #fca5a5); }

/* Settings panel */
.settings-panel {
    position: fixed;
    top: 52px;
    right: -320px;
    width: 300px;
    max-height: calc(100vh - 52px);
    background: rgba(15, 23, 42, 0.97);
    backdrop-filter: blur(12px);
    border-left: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    box-shadow: -4px 0 20px rgba(0,0,0,0.3);
    z-index: 210;
    transition: right .25s ease;
    overflow-y: auto;
    padding: 0;
}
.settings-panel.open { right: 0; }
.settings-panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 18px;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    color: var(--pz-text-primary, #e2e8f0);
    font-weight: 700;
    font-size: .95rem;
}
.settings-close {
    background: none; border: none; color: var(--pz-text-muted); font-size: 1.4rem; cursor: pointer;
    padding: 0 4px; line-height: 1;
}
.settings-close:hover { color: var(--pz-text-on-primary, #fff); }
.settings-section {
    padding: 14px 18px;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
}
.settings-label {
    display: block;
    color: var(--pz-text-muted);
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-bottom: 10px;
}
.settings-theme-row {
    display: flex;
    gap: 8px;
}
.settings-theme-opt {
    flex: 1;
    padding: 8px 10px;
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-radius: var(--pz-radius-card, 6px);
    background: color-mix(in srgb, var(--pz-text-primary) 4%, transparent);
    color: var(--pz-border-soft);
    font-size: .82rem;
    cursor: pointer;
    transition: all .15s;
    text-align: center;
}
.settings-theme-opt:hover { border-color: color-mix(in srgb, var(--pz-text-primary) 20%, transparent); background: color-mix(in srgb, var(--pz-text-primary) 8%, transparent); }
.settings-theme-opt.active { border-color: var(--pz-primary, #0ea5e9); color: var(--pz-primary, #0ea5e9); background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 10%, transparent); }
.settings-color-row {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.settings-color-swatch {
    width: 32px; height: 32px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    transition: transform .15s, border-color .15s;
    padding: 0;
}
.settings-color-swatch:hover { transform: scale(1.15); }
.settings-color-swatch.active { border-color: var(--pz-text-on-primary, #fff); transform: scale(1.1); }

/* Org logo in topbar */
.topbar-org-logo {
    height: 28px;
    max-width: 120px;
    object-fit: contain;
    border-radius: var(--pz-radius-sm, 4px);
    flex-shrink: 0;
}

/* Color picker inputs */
.settings-color-picker-row {
    display: flex;
    gap: 20px;
}
.settings-color-group {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    flex: 1;
}
.settings-color-label {
    font-size: .72rem;
    color: var(--pz-text-muted);
    font-weight: 500;
}
.settings-color-input {
    width: 52px;
    height: 36px;
    border: 2px solid color-mix(in srgb, var(--pz-text-primary) 15%, transparent);
    border-radius: var(--pz-radius-md, 8px);
    cursor: pointer;
    background: none;
    padding: 2px;
}
.settings-color-input::-webkit-color-swatch-wrapper { padding: 0; }
.settings-color-input::-webkit-color-swatch { border: none; border-radius: var(--pz-radius-card, 6px); }
.settings-color-input::-moz-color-swatch { border: none; border-radius: var(--pz-radius-card, 6px); }
.settings-color-input:hover { border-color: color-mix(in srgb, var(--pz-text-primary) 30%, transparent); }

/* Reset button */
.settings-reset-btn {
    width: 100%;
    padding: 8px 14px;
    background: color-mix(in srgb, var(--pz-text-primary) 6%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-radius: var(--pz-radius-card, 6px);
    color: var(--pz-text-muted);
    font-size: .8rem;
    cursor: pointer;
    transition: all .15s;
}
.settings-reset-btn:hover { background: color-mix(in srgb, var(--pz-text-primary) 10%, transparent); color: var(--pz-text-primary, #e2e8f0); }

/* Light mode overrides for new elements */
.light-mode .settings-color-input { border-color: var(--pz-border, #e2e8f0); }
.light-mode .settings-color-input:hover { border-color: var(--pz-text-muted); }
.light-mode .settings-color-label { color: var(--pz-text-muted); }
.light-mode .settings-reset-btn { background: color-mix(in srgb, var(--pz-text-primary) 4%, transparent); border-color: var(--pz-border, #e2e8f0); color: var(--pz-text-muted); }
.light-mode .settings-reset-btn:hover { background: color-mix(in srgb, var(--pz-text-primary) 8%, transparent); color: var(--pz-text-primary); }

/* ─── Accueil (role cards page) ──────────────────────────── */
.portal-accueil {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    /* Sprint 55 hotfix UI debug : compense topbar 52px + footer/bottombar ~48px
       pour que le bloc soit vraiment centré entre les 2 (espace top = espace bottom). */
    min-height: calc(100vh - 100px);
    padding: 20px;
}
.accueil-title {
    font-size: 2rem;
    font-weight: 600;
    /* S178 — « Bonjour {prénom} » de la page index suit la couleur « Texte principal »
       du picker user (canon --pz-text-primary). Avant : --pz-text-on-primary qui pouvait
       être quasi-invisible si le picker brand était proche du fond shell (retour Arnaud). */
    color: var(--pz-text-primary, #f1f5f9);
    margin-bottom: 8px;
}
.accueil-subtitle {
    color: var(--pz-text-muted);
    font-size: 1rem;
    margin-bottom: 40px;
}
.accueil-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 20px;
    max-width: 900px;
    width: 100%;
}
.accueil-card {
    /* Sprint 65 R3 : .accueil-card consomme --pz-secondary (shell card user-customisable). */
    background: var(--pz-secondary, rgba(30, 41, 59, 0.8));
    color: var(--pz-secondary-text, #fff);
    border: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 6%, transparent));
    border-radius: var(--pz-radius-lg, 12px);
    padding: 32px 24px;
    text-decoration: none;
    transition: transform .2s, border-color .2s, box-shadow .2s;
    text-align: center;
}
.accueil-card:hover {
    transform: translateY(-4px);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 30%, transparent);
    box-shadow: 0 8px 30px color-mix(in srgb, var(--pz-primary, #0ea5e9) 12%, transparent);
}
.accueil-card-icon { font-size: 2.5rem; margin-bottom: 12px; }
.accueil-card h3 { font-size: 1.15rem; font-weight: 600; margin-bottom: 8px; }
.accueil-card p { color: var(--pz-text-muted); font-size: .85rem; line-height: 1.4; }

/* ─── S198 D5 — Vision déléguée (impersonation admin read-only) ───────────── */
.accueil-impersonation { margin-top: 36px; }
.accueil-imp-form { display: contents; }
.accueil-card-imp { width: 100%; cursor: pointer; font: inherit; }
.accueil-imp-photo { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; }
.pz-impersonation-banner {
    position: sticky;
    top: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 8px 14px;
    background: color-mix(in srgb, var(--pz-warn, #f59e0b) 18%, var(--pz-bg-base, #0f172a));
    border-bottom: 1px solid color-mix(in srgb, var(--pz-warn, #f59e0b) 45%, transparent);
    color: var(--pz-text-primary, #e2e8f0);
    font-size: .85rem;
}
.pz-imp-eye { display: inline-flex; align-items: center; }
.pz-imp-quit-form { display: inline-flex; margin: 0; }
.pz-imp-quit-btn {
    border: 1px solid color-mix(in srgb, var(--pz-warn, #f59e0b) 60%, transparent);
    background: transparent;
    color: inherit;
    border-radius: var(--pz-radius-sm, 6px);
    padding: 3px 10px;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.pz-imp-quit-btn:hover { background: color-mix(in srgb, var(--pz-warn, #f59e0b) 25%, transparent); }

/* ─── Layout ─────────────────────────────────────────────── */
.portal-wrapper {
    display: flex;
    min-height: 100vh;
}

/* ─── Sidebar ────────────────────────────────────────────── */
.portal-sidebar {
    width: 280px;
    min-width: 280px;
    /* Sprint 65 R3 : sidebar consomme --pz-secondary (shell user-customisable).
       backdrop-filter conservé pour effet glassmorphism subtil sur fond body. */
    background: var(--pz-secondary, rgba(0, 0, 0, 0.55));
    color: var(--pz-secondary-text);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-right: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-secondary-text) 8%, transparent));
    display: flex;
    flex-direction: column;
    position: fixed;
    /* S185 retour Arnaud — +3px en haut pour rapprocher la sidebar de la top bar (gap réduit). */
    top: 49px;
    /* Sprint 97 V_A bis 5 — sidebar collée à la bottombar 52px (gap supprimé). */
    bottom: 52px;
    left: 0;
    z-index: 100;
    overflow: hidden;
}

/* S120 V_A.6 — Sidebar canon « Picker prime + sidebar contextuelle » (Q6=A Arnaud).
   Pattern Slack workspace switcher : la sidebar montre daily items pour la résidence
   active (via picker topbar). Mode portfolio = message hint vers picker. Scale infini. */
.sidebar-scope-active {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 12px; margin: 0 12px 8px;
    background: color-mix(in srgb, var(--pz-secondary-text) 28%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    border-left: 3px solid var(--pz-primary, #0284c7);
    border-radius: 0;
    font-size: .82rem;
    color: var(--pz-secondary-text);
    color: var(--pz-secondary-text);
}
.sidebar-scope-active .scope-icon {
    flex-shrink: 0;
    color: var(--pz-primary, #0284c7);
    display: inline-flex; align-items: center;
}
.sidebar-scope-active .scope-name {
    flex: 1; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar-portfolio-mode {
    margin: 0 12px 8px;
    padding: 14px 12px;
    background: color-mix(in srgb, var(--pz-secondary-text) 28%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    border-radius: 0;
    text-align: center;
}
.sidebar-portfolio-mode .portfolio-mode-icon {
    color: var(--pz-primary, #0284c7);
    margin-bottom: 6px;
    display: inline-flex; align-items: center; justify-content: center;
}
.sidebar-portfolio-mode .portfolio-mode-title {
    font-weight: 600; font-size: .9rem; margin-bottom: 6px;
    color: var(--pz-secondary-text);
    color: var(--pz-secondary-text);
}
.sidebar-portfolio-mode .portfolio-mode-hint {
    font-size: .76rem; line-height: 1.45;
    color: var(--pz-text-shell-soft);
}
.sidebar-portfolio-mode .portfolio-mode-hint strong {
    color: var(--pz-text-shell-strong);
    font-weight: 600;
}
.light-mode .sidebar-scope-active,
.light-mode .sidebar-portfolio-mode {
    background: var(--pz-bg-raised, #f8fafc);
    border-color: var(--pz-border, #e2e8f0);
    color: var(--pz-text-primary);
}
.light-mode .sidebar-portfolio-mode .portfolio-mode-title { color: var(--pz-text-primary); }
.light-mode .sidebar-portfolio-mode .portfolio-mode-hint { color: var(--pz-text-muted); }
.light-mode .sidebar-portfolio-mode .portfolio-mode-hint strong { color: var(--pz-text-primary); }

/* Bloc profil sidebar — composition verticale centrée (référence Arnaud hotfix #5) :
   logo X-Consulting en haut (grand, visible) → photo (centrée) → nom → rôle */
.sidebar-profile {
    flex-shrink: 0;
    /* S123 V_0.4 retour Arnaud #4 — padding bottom + margin réduits pour
       supprimer gap excessif entre profile et "GESTION QUOTIDIENNE" section title. */
    /* S150 retour Arnaud — top réduit pour que la sidebar « touche » la topbar (plus de bande vide moche en haut). */
    padding: 8px 20px 6px;
    margin-bottom: 4px;
    text-align: center;
    position: relative;
}
/* Séparateur élégant : ligne horizontale fine avec dégradé latéral, centrée.
   S70 V_A.2 — couleur séparateur dérivée de --pz-secondary-text (couplé fond shell). */
.sidebar-profile::after {
    content: '';
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 0;
    height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        color-mix(in srgb, var(--pz-secondary-text) 18%, transparent) 20%,
        color-mix(in srgb, var(--pz-secondary-text) 22%, transparent) 50%,
        color-mix(in srgb, var(--pz-secondary-text) 18%, transparent) 80%,
        transparent 100%);
}

.sidebar-profile-org {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 16px;
}
.sidebar-profile-org img {
    max-height: 58px;
    max-width: 90%;
    object-fit: contain;
    opacity: 0.96;
}
/* S177 — toggle logo dark/light selon le mode UI actif. Par défaut (mode sombre) le logo
   « dark » est visible ; en mode clair (body.light-mode), on bascule sur le logo « light ».
   Si un seul logo est uploadé, sidebar.php le rend pour les 2 modes (donc toujours visible). */
.sidebar-profile-org-logo-light { display: none; }
body.light-mode .sidebar-profile-org-logo-dark { display: none; }
body.light-mode .sidebar-profile-org-logo-light { display: block; }
/* Fallback texte si pas de fichier logo : nom de la société en label sobre */
.sidebar-profile-org-text {
    font-size: .9rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: color-mix(in srgb, var(--pz-secondary-text) 75%, transparent);
    text-transform: none;
    padding: 0 8px;
    line-height: 1.2;
}

.sidebar-profile-photo {
    width: 88px;
    height: 88px;
    /* S122 V_A.1 retour Arnaud #21 — photo ronde RESTAURÉE (revert #20 erroné).
       Seuls les boutons/containers UI sont carrés ; la PHOTO reste ronde canon. */
    border-radius: 50%;
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 25%, transparent);
    border: 2px solid color-mix(in srgb, var(--pz-primary, #0ea5e9) 50%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 12px;
    font-size: 2rem;
    color: var(--pz-primary-text, #fff);
    overflow: hidden;
}
.sidebar-profile-photo.has-photo {
    background: transparent;
    padding: 0;
}
.sidebar-profile-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Photo ronde maintenue (cohérent .sidebar-profile-photo). */
    border-radius: 50%;
    display: block;
}

.sidebar-profile-name {
    color: var(--pz-secondary-text);
    font-size: 1.1rem;
    line-height: 1.2;
    margin: 0 0 4px;
    font-weight: 600;
    letter-spacing: -0.2px;
}

.sidebar-profile .profile-role {
    color: color-mix(in srgb, var(--pz-secondary-text) 60%, transparent);
    font-size: 0.82rem;
    line-height: 1.3;
}

.sidebar-admin-btn {
    display: block;
    margin: 14px auto 0;
    padding: 10px 18px;
    /* S70 V_A.3 — bouton danger admin = sémantique canonique fixe (rouge urgent). */
    background: var(--pz-urgent, #dc2626);
    color: var(--pz-text-on-primary, #fff);
    font-size: 0.85rem;
    font-weight: 700;
    border-radius: var(--pz-radius-md, 8px);
    text-decoration: none;
    text-align: center;
    transition: background 0.2s, transform 0.15s;
    letter-spacing: 0.02em;
}
.sidebar-admin-btn:hover {
    background: var(--pz-urgent-hover, #b91c1c);
    transform: translateY(-1px);
}

.sidebar-roles {
    padding: 12px 16px;
    border-top: 1px solid color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    margin-top: 8px;
}
.sidebar-roles-title {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: color-mix(in srgb, var(--pz-secondary-text) 40%, transparent);
    margin-bottom: 8px;
}
.sidebar-role-item {
    display: flex;
    flex-direction: column;
    padding: 4px 0;
}
.sidebar-role-label {
    font-size: 0.8rem;
    color: color-mix(in srgb, var(--pz-secondary-text) 75%, transparent);
    font-weight: 500;
}
.sidebar-role-scope {
    font-size: 0.7rem;
    color: var(--pz-primary, #0ea5e9);
}

.sidebar-property {
    padding: 16px 20px;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-secondary-text) 10%, transparent);
}

.sidebar-property .prop-name {
    color: var(--pz-secondary-text);
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 4px;
}

.sidebar-property .prop-ref {
    color: color-mix(in srgb, var(--pz-secondary-text) 60%, transparent);
    font-size: 0.78rem;
    margin-bottom: 6px;
}

.sidebar-property .prop-address {
    color: color-mix(in srgb, var(--pz-secondary-text) 75%, transparent);
    font-size: 0.82rem;
    line-height: 1.4;
}

/* Navigation — scroll interne pour garder MASTER DATA toujours visible en bas.
 * Sprint 74 audit fix : `scrollbar-gutter: stable` réserve TOUJOURS la largeur
 * de la scrollbar (~17px), même quand le contenu n'overflow pas. Sans ça, la
 * scrollbar apparaît/disparaît selon la longueur des labels nav traduits
 * (FR « Ma comptabilité » vs EN « My accounting » plus court) → la sidebar
 * « bouge » de 17px à chaque changement de langue (CLS jarring signalé Arnaud).
 * Fallback older browsers : utilise overflow-y: auto. Supported Chrome 94+,
 * Firefox 97+, Safari 14+ (mai 2024 baseline). */
.sidebar-nav {
    padding: 12px 0;
    flex: 1 1 auto;
    overflow-y: auto;
    scrollbar-gutter: stable;
    min-height: 0;
}

/* Sprint 54 fix specificity — règle legacy `.sidebar-nav a` (avant Sprint 33)
 * écrasait `.pz-nav-label` et `.pz-nav-badge` via specificity (0,1,1) > (0,1,0)
 * et leur imposait `padding: 12px 24px`. Aujourd'hui aucun `<a>` n'est enfant
 * direct de `.sidebar-nav` (tout passe par `.pz-nav-row` ou `.sidebar-tree-*`).
 * Scopage à `> a` neutralise la règle sans casser de cas existant. */
.sidebar-nav > a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 24px;
    color: color-mix(in srgb, var(--pz-secondary-text) 75%, transparent);
    text-decoration: none;
    font-size: 0.92rem;
    transition: all 0.2s;
    border-left: 3px solid transparent;
}

.sidebar-nav > a:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 7%, transparent);
    color: var(--pz-secondary-text);
}

.sidebar-nav > a.active {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 15%, transparent);
    /* S178 retour Arnaud — item actif = canon « Texte principal » (--pz-text-primary
       picker-réactif). Avant fix S178 commit ce5c11b : --pz-secondary-text (perçu trop
       pâle, « le texte secondaire »). L'item actif doit ÉCLATER (highlight = bold +
       primary text + accent border-left). */
    color: var(--pz-text-primary);
    border-left-color: var(--pz-primary, #009FCB);
    font-weight: 600;
}

.sidebar-nav > a .nav-icon {
    width: 20px;
    text-align: center;
    font-size: 1.1rem;
    flex-shrink: 0;
}

.sidebar-nav-divider {
    height: 1px;
    background: color-mix(in srgb, var(--pz-secondary-text) 10%, transparent);
    margin: 8px 20px;
}

.sidebar-section-title {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    /* S70 V_A.2 — sidebar text consomme --pz-secondary-text (couplé fond shell --pz-secondary).
       Variants soft/medium via color-mix() — bascule auto avec mode + thème user. */
    color: color-mix(in srgb, var(--pz-secondary-text) 35%, transparent);
    /* S123 V_0.4 retour Arnaud #4 — padding-top réduit 16→6 (gap profile/section minimal). */
    padding: 6px 18px 4px 23px;
    font-weight: 600;
}

/* Sidebar tree navigation */
.sidebar-tree-node {
    margin: 0;
}
.sidebar-tree-parent {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 18px 7px 3px;
    font-size: .82rem;
    font-weight: 600;
    color: color-mix(in srgb, var(--pz-secondary-text) 80%, transparent);
    text-decoration: none;
    cursor: pointer;
    transition: background .15s, color .15s;
    border-left: 3px solid transparent;
}
.sidebar-tree-parent:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    color: var(--pz-secondary-text);
}
.sidebar-tree-parent.expanded { color: var(--pz-primary, #0ea5e9); }
.tree-arrow {
    font-size: .7rem;
    width: 16px;
    text-align: center;
    transition: transform .15s;
    flex-shrink: 0;
}
.sidebar-tree-children {
    padding-left: 14px;
}
.sidebar-tree-leaf {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 20px 5px 26px;
    font-size: .78rem;
    color: color-mix(in srgb, var(--pz-secondary-text) 60%, transparent);
    text-decoration: none;
    transition: background .15s, color .15s;
    border-left: 3px solid transparent;
}
.sidebar-tree-leaf:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 6%, transparent);
    color: var(--pz-secondary-text);
}
.sidebar-tree-leaf.active {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 12%, transparent);
    /* S178 retour Arnaud — feuille active = canon « Texte principal » (idem .sidebar-nav>a.active). */
    color: var(--pz-text-primary);
    border-left-color: var(--pz-primary, #0ea5e9);
    font-weight: 600;
}

/* Data management complex group */
.data-complex-group {
    margin-bottom: 24px;
}
.data-complex-header {
    font-size: 1rem;
    font-weight: 700;
    color: var(--pz-secondary-text);
    padding: 8px 0;
    margin-bottom: 8px;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
}

/* Light mode — topbar + accueil */
.light-mode .portal-topbar { background: rgba(255,255,255,0.9); border-bottom-color: var(--pz-border, #e2e8f0); }
.light-mode .topbar-logo { color: var(--pz-text-primary); }
.light-mode .topbar-link { color: var(--pz-text-secondary); }
.light-mode .topbar-link:hover { color: var(--pz-text-primary); }
.light-mode .topbar-link-home { color: var(--pz-text-primary); font-weight: 600; }
.light-mode .topbar-link-home:hover { color: var(--pz-text-primary); opacity: 0.7; }
.light-mode .topbar-link-home.active { color: var(--pz-primary, #0284c7); }
.light-mode .topbar-link-user { color: var(--pz-text-primary); }
.light-mode .topbar-link-user:hover { color: var(--pz-primary, #0284c7); }
.light-mode .topbar-link-logout { color: var(--pz-urgent, #dc2626); }
.light-mode .topbar-link-logout:hover { color: var(--pz-urgent-hover, #b91c1c); }
.light-mode .topbar-ctx-link { color: var(--pz-primary, #0284c7); }
.light-mode .topbar-ctx-link:hover { color: var(--pz-text-primary); }
.light-mode .topbar-ctx-current { color: var(--pz-border, #334155); }
.light-mode .topbar-ctx-sep { color: var(--pz-text-muted); }
.light-mode .settings-panel { background: rgba(255,255,255,0.97); border-left-color: var(--pz-border, #e2e8f0); box-shadow: -4px 0 20px rgba(0,0,0,0.08); }
.light-mode .settings-panel-header { color: var(--pz-text-primary); border-bottom-color: var(--pz-border, #e2e8f0); }
.light-mode .settings-close { color: var(--pz-text-muted); }
.light-mode .settings-section { border-bottom-color: var(--pz-border-soft, #f1f5f9); }
.light-mode .settings-label { color: var(--pz-text-muted); }
.light-mode .settings-theme-opt { color: var(--pz-text-secondary); background: color-mix(in srgb, var(--pz-text-primary) 3%, transparent); border-color: var(--pz-border, #e2e8f0); }
.light-mode .settings-theme-opt:hover { background: color-mix(in srgb, var(--pz-text-primary) 6%, transparent); }
.light-mode .settings-theme-opt.active { border-color: var(--pz-primary, #0284c7); color: var(--pz-primary, #0284c7); }
.light-mode .topbar-theme-btn { color: var(--pz-text-muted); }
.light-mode .topbar-greeting { color: var(--pz-text-primary); }
.light-mode .accueil-title { color: var(--pz-text-primary); }
.light-mode .accueil-subtitle { color: var(--pz-text-muted); }
/* Sprint 65 R3 hotfix : background hardcoded NEUTRALISÉ — laisse var(--pz-secondary)
   user-customisable s'appliquer en mode clair. border-color reste hardcoded
   tant que --pz-border n'est pas dans le set user (tokens.css le bascule auto). */
.light-mode .accueil-card { border-color: var(--pz-border, #e2e8f0); }
.light-mode .accueil-card:hover { border-color: var(--pz-primary, #0284c7); box-shadow: 0 8px 30px color-mix(in srgb, var(--pz-primary, #0284c7) 10%, transparent); }
/* h3 + p héritent maintenant de var(--pz-secondary-text) sur la card parent */

/* S197 décision Arnaud (reco Léa audit mobile) — FAB bleu .sidebar-toggle (S61 hotfix v2)
   SUPPRIMÉ : le burger Modules vit dans la bottombar (.pz-bb-burger, layout/bottombar.php). */

/* ─── Main Content ───────────────────────────────────────── */
/* S122 V_A.1 retour Arnaud #18+#19 — zoom 90% repensé :
   - retour #18 `zoom: 0.9` créait espace inutile droite/bas (viewport reste 100%
     mais contenu rendu à 90% = 10% vide cross-écran).
   - retour #19 fix : `html { font-size: 14.4px }` (90% de 16px default). Tous
     les rem/em réduisent → typo + spacing compactés. Les widths px hardcoded
     restent ; contenu remplit le viewport sans espace mort.
   Arnaud directive « on garde [90%] mais il faut travailler sur l'espace inutile ». */
html {
    font-size: 14.4px;
}
/* S122 V_A.1 retour Arnaud #21 — checkboxes + radios canon accent vert Sidney
   (vs bleu browser default). `accent-color` natif supporté Chrome/Edge/Firefox/Safari. */
input[type="checkbox"], input[type="radio"] {
    accent-color: var(--pz-accent, #a1b81c);
}
.portal-content {
    flex: 1;
    margin-left: 280px;
    /* Sprint 98 V_A canon master — padding réduit 60→20 bottom, 15→12 top,
       40→32 sides. Cumul B15 + canon "carré pro" Arnaud V_0.1 : viewport
       100% sans scroll, layout serré professionnel.
       S99 Round 8 — padding-bottom 20→80px : garantit espace pour bottombar
       fixed (52px) + breathing room, sinon pagination/dernier élément masqués. */
    padding: 12px 32px 80px;
    min-height: calc(100vh - 104px);
    /* S122 V_A.1 retour Arnaud #16 — min-width:0 force shrink flex-child sous
       contenu naturel (vs `min-width: auto` default qui force 2757px header). */
    min-width: 0;
    max-width: calc(100vw - 280px);
    box-sizing: border-box;
}
/* S167 T1 — Calendrier plein écran (exigence Arnaud démo Sidney 11/06) :
   wrapper qui compense le padding 32px latéral du parent .portal-content pour
   que la table semaine + vue mois + filtres remplissent 100% de la largeur utile.
   Mobile : restitution du padding standard. */
.calendar-fullwidth {
    /* S231 (retour live Arnaud) — le calendrier prend la LARGEUR DE LA BANNIÈRE (= largeur de contenu),
       plus le débordement « plein écran » -32px qui sortait sur les côtés. margin neutralisé. */
    margin: 0;
    padding: 0;
}
/* S231 — la ligne onglets + bouton « Créer un rendez-vous » : réserve l'espace à droite pour le bouton
   absolu (les onglets ne passent pas dessous) et resserre l'écart bannière↔calendrier. */
.cal-tabs-row { padding-right: 200px; margin-top: 4px; }
@media (max-width: 700px) {
    .cal-tabs-row { padding-right: 0; }
    .cal-tabs-row .cal-new-btn { position: static !important; display: inline-flex; margin: 8px 0; }
}

.portal-page-title {
    /* S178 retour Arnaud — H1 du titre d'écran courant (Calendrier / Tableau de bord syndic /
       etc.) utilisait --pz-text-on-primary (texte SUR fond primary) qui peut être quasi-invisible
       si picker brand proche du fond shell (cas Sidney vert olive sur dark). Fix canon
       --pz-text-primary (canal « Texte principal » du picker mig 171). Le light-mode override
       ligne 1722 utilise déjà --pz-text-primary (cohérent). */
    color: var(--pz-text-primary, #fff);
    /* Sprint 97 V_A bis 5 — compactage titre (1.6→1.25rem, margin 24→10px) pour gain hauteur fold. */
    font-size: 1.25rem;
    font-weight: 600;
    margin: 0 0 10px;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    gap: 10px;
}

.portal-page-title .title-icon {
    font-size: 1.1rem;
}

/* ─── Cards / Boxes ──────────────────────────────────────── */
/* Sprint 98 V_A canon master "carré pro" — padding 24→16, margin 20→12,
   border-radius 12→6 (carré pro vs arrondi consumer). Décision Arnaud
   V_0.1 : "les tables carrées ça fait plus pro". Économie verticale
   ~24px par card × 5-6 cards visibles = ~150px gagnés (résout B15
   viewport overflow + harmonise canon OWNER+SYNDIC+ADMIN). */
.portal-card {
    background: color-mix(in srgb, var(--pz-text-primary) 28%, transparent);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    border-radius: var(--pz-radius-card, 0); /* S141 : carré canon (token S140) — portal-card codait 6px en dur */
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    padding: 16px;
    margin-bottom: 12px;
    /* S217 (Q-PORTAL-CARD-LIGHT, reco Léa A81/A86) — le fond est un color-mix NEUTRE de --pz-text-primary
       (28 %), JAMAIS --pz-primary pur → le texte doit suivre --pz-text-primary (inversé clair/sombre), pas
       --pz-text-on-primary (toujours blanc = illisible sur carte claire / thème custom clair sans .light-mode).
       Sombre : #fff → #f1f5f9 (imperceptible). Clair/custom-clair : texte enfin lisible. Rend redondant
       le `.light-mode .portal-card{color}` (S177, conservé inoffensif). */
    color: var(--pz-text-primary);
}

.portal-card h3 {
    font-size: 1.1rem;
    margin: 0 0 16px;
    font-weight: 600;
    color: var(--pz-text-primary); /* S217 Q-PORTAL-CARD-LIGHT — idem (était --pz-text-on-primary, illisible en clair) */
}

/* ─── Dashboard Cards Grid ───────────────────────────────── */
.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
    margin-bottom: 30px;
}

.dash-stat {
    text-align: center;
    padding: 30px 24px;
}

.dash-stat .stat-value {
    font-size: 2rem;
    font-weight: 700;
    color: var(--pz-primary, #0ea5e9);
    margin-bottom: 6px;
}

.dash-stat .stat-label {
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.88rem;
}

/* Manager info card */
.manager-card {
    display: flex;
    align-items: center;
    gap: 16px;
}

.manager-avatar {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 20%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    flex-shrink: 0;
}

.manager-info h4 {
    margin: 0 0 4px;
    font-size: 1rem;
    color: var(--pz-text-on-primary, #fff);
}

.manager-info p {
    margin: 0;
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.7);
}

.manager-info a {
    color: var(--pz-primary, #0ea5e9);
    text-decoration: none;
}

.manager-info a:hover {
    text-decoration: underline;
}

/* ─── Tables ─────────────────────────────────────────────── */
/* S70 V_A.5 — tables consomment thème syndic (--pz-secondary-text couplé fond
   shell). Variants opacity via color-mix(). Bascule auto mode + thème user.
   .amount.negative/positive consomment couleurs sémantiques canoniques fixes. */
.portal-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

.portal-table thead th {
    text-align: left;
    padding: 12px 14px;
    color: color-mix(in srgb, var(--pz-secondary-text) 60%, transparent);
    font-weight: 600;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-secondary-text) 12%, transparent);
}

.portal-table tbody td {
    padding: 12px 14px;
    color: var(--pz-secondary-text);
    border-bottom: 1px solid color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
}

.portal-table tbody tr:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 6%, transparent);
}

.portal-table .amount {
    font-weight: 600;
    text-align: right;
    white-space: nowrap;
}

.portal-table .amount.negative {
    color: var(--pz-urgent, #dc2626);
}

.portal-table .amount.positive {
    color: var(--pz-success, #10b981);
}

/* ─── Status badges ──────────────────────────────────────── */
.badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: var(--pz-radius-full, 9999px);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.badge-open {
    background: rgba(59, 130, 246, 0.2);
    color: var(--pz-info-hover, #60a5fa);
    border: 1px solid rgba(59, 130, 246, 0.3);
}

.badge-in_progress {
    background: rgba(251, 191, 36, 0.2);
    color: var(--pz-warning, #fbbf24);
    border: 1px solid rgba(251, 191, 36, 0.3);
}

.badge-closed {
    background: rgba(74, 222, 128, 0.2);
    color: var(--pz-success, #4ade80);
    border: 1px solid rgba(74, 222, 128, 0.3);
}

.badge-upcoming {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 20%, transparent);
    color: var(--pz-primary, #0ea5e9);
    border: 1px solid color-mix(in srgb, var(--pz-primary, #0ea5e9) 30%, transparent);
}

.badge-completed {
    background: rgba(74, 222, 128, 0.2);
    color: var(--pz-success, #4ade80);
    border: 1px solid rgba(74, 222, 128, 0.3);
}

.badge-cancelled {
    background: rgba(248, 113, 113, 0.2);
    color: var(--pz-urgent, #f87171);
    border: 1px solid rgba(248, 113, 113, 0.3);
}

/* ─── Document Category Grid ─────────────────────────────── */
.doc-categories {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 16px;
}

.doc-cat-card {
    background: color-mix(in srgb, var(--pz-text-primary) 28%, transparent);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-lg, 12px);
    padding: 24px 20px;
    text-align: center;
    text-decoration: none;
    color: var(--pz-text-on-primary, #fff);
    transition: all 0.25s;
    cursor: pointer;
    display: block;
}

.doc-cat-card:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 12%, transparent);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 30%, transparent);
    transform: translateY(-2px);
}

.doc-cat-card .cat-icon {
    font-size: 2.2rem;
    margin-bottom: 12px;
    display: block;
    color: var(--pz-primary, #0ea5e9);
}

.doc-cat-card .cat-label {
    font-size: 0.88rem;
    font-weight: 600;
    margin-bottom: 8px;
    line-height: 1.3;
}

.doc-cat-card .cat-updated {
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.55);
}

/* Document list within a category */
.doc-list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 0;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
}

.doc-list-item:last-child {
    border-bottom: none;
}

.doc-list-info {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    min-width: 0;
}

.doc-list-info .doc-icon {
    font-size: 1.3rem;
    color: var(--pz-primary, #0ea5e9);
    flex-shrink: 0;
}

.doc-list-info .doc-title {
    font-size: 0.9rem;
    color: var(--pz-text-on-primary, #fff);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.doc-list-info .doc-date {
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.55);
    margin-top: 2px;
}

.doc-download-btn {
    padding: 6px 14px;
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 20%, transparent);
    color: var(--pz-primary, #0ea5e9);
    border: 1px solid color-mix(in srgb, var(--pz-primary, #0ea5e9) 30%, transparent);
    border-radius: var(--pz-radius-card, 6px);
    text-decoration: none;
    font-size: 0.8rem;
    font-weight: 600;
    transition: all 0.2s;
    white-space: nowrap;
}

.doc-download-btn:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 35%, transparent);
}

/* ─── Request Thread ─────────────────────────────────────── */
.request-thread {
    margin-top: 20px;
}

.thread-message {
    padding: 16px 20px;
    margin-bottom: 12px;
    border-radius: var(--pz-radius-card-lg, 10px);
    border-left: 3px solid;
}

.thread-message.msg-client {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 8%, transparent);
    border-left-color: var(--pz-primary, #0ea5e9);
}

.thread-message.msg-manager {
    background: rgba(74, 222, 128, 0.08);
    border-left-color: var(--pz-success-soft, #4ade80);
}

.thread-message .msg-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    font-size: 0.82rem;
}

.thread-message .msg-sender {
    font-weight: 600;
    color: var(--pz-text-on-primary, #fff);
}

.thread-message .msg-date {
    color: rgba(255, 255, 255, 0.55);
}

.thread-message .msg-body {
    color: rgba(255, 255, 255, 0.85);
    font-size: 0.9rem;
    line-height: 1.6;
}

.thread-attachment {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 10px;
    padding: 6px 12px;
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border-radius: var(--pz-radius-card, 6px);
    color: var(--pz-primary, #0ea5e9);
    font-size: 0.82rem;
    text-decoration: none;
}

.thread-attachment:hover {
    background: color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
}

/* ─── Property Cards ─────────────────────────────────────── */
.property-card {
    margin-bottom: 20px;
}

.property-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 16px;
}

.property-header h3 {
    margin: 0;
}

.property-header .prop-ref-badge {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 15%, transparent);
    color: var(--pz-primary, #0ea5e9);
    padding: 4px 12px;
    border-radius: var(--pz-radius-full, 9999px);
    font-size: 0.78rem;
    font-weight: 600;
}

.lots-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}

.lot-card {
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-md, 8px);
    padding: 14px;
}

.lot-card .lot-number {
    font-weight: 600;
    font-size: 1rem;
    margin-bottom: 8px;
    color: var(--pz-primary, #0ea5e9);
}

.lot-card .lot-detail {
    font-size: 0.82rem;
    color: rgba(255, 255, 255, 0.7);
    margin-bottom: 3px;
}

/* ─── Forms ──────────────────────────────────────────────── */
.portal-form {
    max-width: 600px;
}

.portal-form .form-group {
    margin-bottom: 18px;
}

/* S70 V_A.5 — forms consomment thème syndic. Label = secondary-text 75%,
   input bg/border/color = thème syndic via color-mix() pour contraste/distinction. */
.portal-form label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.85rem;
    color: color-mix(in srgb, var(--pz-secondary-text) 75%, transparent);
    font-weight: 600;
}

.portal-form input[type="text"],
.portal-form input[type="email"],
.portal-form input[type="password"],
.portal-form select,
.portal-form textarea {
    width: 100%;
    padding: 10px 14px;
    background: var(--pz-secondary, rgba(0, 0, 0, 0.35));
    border: 1px solid color-mix(in srgb, var(--pz-secondary-text) 18%, transparent);
    border-radius: var(--pz-radius-md, 8px);
    color: var(--pz-secondary-text);
    font-size: 0.9rem;
    font-family: inherit;
    transition: border-color 0.2s;
    box-sizing: border-box;
}

.portal-form input:focus,
.portal-form select:focus,
.portal-form textarea:focus {
    outline: none;
    border-color: var(--pz-primary, #0ea5e9);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--pz-primary, #0ea5e9) 20%, transparent);
}

.portal-form textarea {
    min-height: 120px;
    resize: vertical;
}

.portal-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 24px;
    background: var(--pz-primary, #0ea5e9);
    color: var(--pz-text-on-primary, #fff);
    border: none;
    border-radius: var(--pz-radius-md, 8px);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s;
    text-decoration: none;
}

.portal-btn:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 85%, black);
}

.portal-btn-outline {
    background: transparent;
    border: 1px solid color-mix(in srgb, var(--pz-primary, #0ea5e9) 40%, transparent);
    color: var(--pz-primary, #0ea5e9);
}

.portal-btn-outline:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 10%, transparent);
}

.portal-btn-sm {
    padding: 6px 14px;
    font-size: 0.82rem;
}

/* ─── Login Page ─────────────────────────────────────────── */
.login-wrapper {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 40px;
    gap: 80px;
    background: var(--pz-info-soft, #c5dffb);
}

@media (max-width: 900px) {
    .login-wrapper {
        flex-direction: column;
        gap: 32px;
        padding: 40px 20px;
    }
}

/* ─── S218 (retour Arnaud) — Login MODE SOMBRE = bleu noble ────────────────────
   Le fond du login = var(--pz-info-soft) : pâle #dbeafe en clair (« superbe » — Arnaud),
   mais ROYAL #1e3a8a en sombre = « le bleu du fond, j'aime pas trop ». Arnaud : « mettre
   le bleu foncé en fond général et un bleu moins foncé » → on cale le login sombre sur le
   bleu NUIT noble de la plateforme (#0a1628 = --pz-bg-body sombre, déjà le fond des écrans
   connectés) avec un voile #16294d (« bleu moins foncé ») en haut à gauche pour la profondeur.
   Le MODE CLAIR reste strictement inchangé. Validation visuelle Arnaud requise (Q-LOGIN-DARK). */
body.portal-page:not(.light-mode) .login-wrapper {
    background:
        radial-gradient(ellipse at 28% 20%, #16294d 0%, transparent 58%),
        linear-gradient(155deg, #0c1d3a 0%, #0a1628 62%);
}
/* Le titre « petzerhiel.lu » prend --pz-bg-base (inverse du fond) : lisible en clair (#fff),
   mais #0a1628 en sombre = navy sur navy = invisible. On force un blanc-bleuté noble lisible. */
body.portal-page:not(.light-mode) .login-brand-title {
    color: #e8f0fb;
}

.login-box {
    width: 100%;
    max-width: 420px;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-radius: var(--pz-radius-xl, 16px);
    padding: 40px 36px;
    box-shadow: 12px 16px 32px rgba(10, 29, 62, 0.18), 4px 6px 12px rgba(10, 29, 62, 0.08);
}

.login-box h1 {
    text-align: center;
    color: var(--pz-text-on-primary, #fff);
    font-size: 1.5rem;
    margin: 0 0 6px;
}

.login-box .login-subtitle {
    text-align: center;
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.88rem;
    margin-bottom: 28px;
}

.login-brand {
    text-align: center;
    flex: 0 0 auto;
    max-width: 480px;
}

.login-brand-title {
    font-family: 'Outfit', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    text-align: center;
    color: var(--pz-bg-base, #0a1d3e);
    font-size: 5.32rem;
    font-weight: 600;
    letter-spacing: -1px;
    line-height: 1;
    margin: 0 0 16px;
    text-shadow: 3px 4px 6px rgba(10, 29, 62, 0.12), 1px 2px 3px rgba(10, 29, 62, 0.06);
}

.login-brand-logo {
    display: block;
    margin: 0 auto 16px;
    width: 150px;
    height: 150px;
    object-fit: contain;
    filter: drop-shadow(3px 4px 6px rgba(10, 29, 62, 0.12)) drop-shadow(1px 2px 3px rgba(10, 29, 62, 0.06));
}

.login-brand-tagline {
    font-family: 'Outfit', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    text-align: center;
    color: var(--pz-brand-accent, #768c47);
    font-size: 2.3rem;
    font-weight: 500;
    letter-spacing: 4px;
    text-transform: lowercase;
    margin: 0;
    text-shadow: 3px 4px 6px rgba(10, 29, 62, 0.12), 1px 2px 3px rgba(10, 29, 62, 0.06);
}

/* Accent jaune doré du logo (soleil) — points du .lu et séparateurs tagline */
.login-brand-accent {
    color: var(--pz-warning, #e9c46a);
    font-weight: 700;
}

@media (max-width: 900px) {
    .login-brand-title { font-size: 3.45rem; margin-bottom: 11px; }
    .login-brand-logo { width: 105px; height: 105px; margin-bottom: 11px; }
    .login-brand-tagline { font-size: 1.9rem; letter-spacing: 2.5px; }
}

/* ─── Bannière de marque des pages publiques (legal / cgv / release-notes) ──────
   Canon « page légale simple » (docs/design-system/canons.md, layout/doc_brand_header.php),
   CALÉ SUR L'ÉCRAN DE LOGIN. Avant S218 la bannière prenait --pz-info-soft en fond → ROYAL
   #1e3a8a en mode sombre = « moche » (Arnaud) face au login noble. On reproduit ici le même
   traitement : carte bleu doux + titre navy en CLAIR ; navy noble + titre clair en SOMBRE. */
.pz-doc-brand {
    display: flex;
    align-items: center;
    gap: 18px;
    background: var(--pz-info-soft, #c5dffb);
    border: 1px solid color-mix(in srgb, var(--pz-bg-base, #0a1d3e) 8%, transparent);
    border-radius: var(--pz-radius-lg, 14px);
    padding: 16px 24px;
    margin: 0 0 26px;
    box-shadow: 6px 8px 18px rgba(10, 29, 62, .10), 2px 3px 6px rgba(10, 29, 62, .05);
}
.pz-doc-brand-logo { flex: 0 0 auto; line-height: 0; }
.pz-doc-brand-text { flex: 1 1 auto; min-width: 0; }
.pz-doc-brand-title {
    font-family: 'Outfit', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    /* S220 (retour Arnaud) : +20% + légère ombre pour que le titre se détache du fond clair */
    font-size: 2.1rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -.5px;
    color: var(--pz-bg-base, #0a1d3e);
    text-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}
.pz-doc-brand-tagline {
    font-family: 'Outfit', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    font-size: 1.1rem;
    font-weight: 500;
    letter-spacing: 2.5px;
    text-transform: lowercase;
    color: var(--pz-brand-accent, #768c47);
    margin-top: 5px;
}
.pz-doc-brand-accent { color: var(--pz-warning, #e9c46a); font-weight: 700; }

/* MODE SOMBRE — bleu nuit noble (identique à .login-wrapper sombre) au lieu du royal --pz-info-soft */
body.portal-page:not(.light-mode) .pz-doc-brand {
    background:
        radial-gradient(ellipse at 22% 0%, #16294d 0%, transparent 62%),
        linear-gradient(155deg, #0c1d3a 0%, #0a1628 70%);
    border-color: color-mix(in srgb, #e8f0fb 12%, transparent);
    box-shadow: 6px 8px 18px rgba(0, 0, 0, .28), 2px 3px 6px rgba(0, 0, 0, .18);
}
body.portal-page:not(.light-mode) .pz-doc-brand-title { color: #e8f0fb; }

.login-box .login-error {
    background: rgba(239, 68, 68, 0.15);
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: var(--pz-urgent-soft, #fca5a5);
    padding: 10px 14px;
    border-radius: var(--pz-radius-md, 8px);
    font-size: 0.85rem;
    margin-bottom: 18px;
    text-align: center;
}

.login-box .form-group {
    margin-bottom: 18px;
}

.login-box label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.85rem;
    color: rgba(255, 255, 255, 0.7);
    font-weight: 600;
}

.login-box input {
    width: 100%;
    padding: 12px 14px;
    background: rgba(0, 0, 0, 0.35);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 15%, transparent);
    border-radius: var(--pz-radius-md, 8px);
    color: var(--pz-text-on-primary, #fff);
    font-size: 0.95rem;
    box-sizing: border-box;
}

.login-box input:focus {
    outline: none;
    border-color: var(--pz-primary, #0ea5e9);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--pz-primary, #0ea5e9) 20%, transparent);
}

.login-box .login-submit {
    width: 100%;
    padding: 12px;
    background: var(--pz-primary, #0ea5e9);
    color: var(--pz-text-on-primary, #fff);
    border: none;
    border-radius: var(--pz-radius-md, 8px);
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    margin-top: 6px;
    transition: background 0.2s;
}

.login-box .login-submit:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 85%, black);
}

.login-box .login-footer {
    text-align: center;
    margin-top: 20px;
    font-size: 0.82rem;
    color: rgba(255, 255, 255, 0.55);
}

.login-box .login-footer a {
    color: var(--pz-primary, #0ea5e9);
    text-decoration: none;
}

/* ─── Balance display ────────────────────────────────────── */
.balance-display {
    text-align: center;
    padding: 20px;
}

.balance-label {
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.85rem;
    margin-bottom: 6px;
}

.balance-amount {
    font-size: 2.2rem;
    font-weight: 700;
    color: var(--pz-text-on-primary, #fff);
}

.balance-amount.positive {
    color: var(--pz-success, #4ade80);
}

.balance-amount.negative {
    color: var(--pz-urgent, #f87171);
}

/* ─── Section: recent operations ─────────────────────────── */
.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}

.section-header h3 {
    margin: 0;
    font-size: 1.1rem;
    color: var(--pz-text-on-primary, #fff);
}

.section-header a {
    color: var(--pz-primary, #0ea5e9);
    text-decoration: none;
    font-size: 0.85rem;
}

/* ─── Assembly cards ─────────────────────────────────────── */
.assembly-card {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
}

.assembly-info h4 {
    margin: 0 0 6px;
    color: var(--pz-text-on-primary, #fff);
    font-size: 1rem;
}

.assembly-info p {
    margin: 0 0 4px;
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.85rem;
}

.assembly-docs {
    margin-top: 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* ─── Empty state ────────────────────────────────────────── */
.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: rgba(255, 255, 255, 0.55);
}

.empty-state .empty-icon {
    font-size: 3rem;
    margin-bottom: 12px;
    display: block;
}

.empty-state p {
    font-size: 0.92rem;
    margin: 0;
}

/* ─── Back link ──────────────────────────────────────────── */
.back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--pz-primary, #0ea5e9);
    text-decoration: none;
    font-size: 0.88rem;
    margin-bottom: 20px;
}

.back-link:hover {
    text-decoration: underline;
}

/* ─── Filters ────────────────────────────────────────────── */
.portal-filters {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 20px;
}

.portal-filters select {
    padding: 8px 12px;
    background: rgba(0, 0, 0, 0.35);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 15%, transparent);
    border-radius: var(--pz-radius-card, 6px);
    color: var(--pz-text-on-primary, #fff);
    font-size: 0.85rem;
}

/* ─── Light mode — comprehensive overrides ──────────────── */
/* Body — Sprint 65 R3 hotfix : background neutralisé, var(--pz-bg-body) gagne.
   background-image (gradient) à none en clair pour ne pas avoir le radial sombre
   sur fond blanc. */
.light-mode.portal-page {
    background-image: none;
    color: var(--pz-text-primary);
}
/* Sidebar — Sprint 65 R3 hotfix : background neutralisé, var(--pz-secondary) gagne. */
.light-mode .portal-sidebar {
    backdrop-filter: blur(6px);
    border-right-color: var(--pz-border, #e2e8f0);
}
/* S70 V_A.2 — overrides .light-mode .sidebar-* SUPPRIMÉS (devenus redondants).
   Les sélecteurs principaux consomment --pz-secondary-text via color-mix() qui bascule
   automatiquement avec le mode + thème user. Plus besoin de hardcoder les couleurs
   par mode. Cf ADR v3 §13 anti-pattern LIGHT_MODE_HARDCODED. */
/* Content area */
.light-mode .portal-page-title { color: var(--pz-text-primary); text-shadow: none; }
/* S177 retour Arnaud — .portal-card consommait --pz-bg-base (token NON dans les pickers)
   → grands fonds blancs inertes (Actions à mener, Panorama Adresse/Comptes bancaires…).
   Aligné sur --pz-bg-raised (picker « Fond des cartes »), cohérent avec data_table /
   KPI / pz-acc-zone qui suivent déjà ce token. */
.light-mode .portal-card {
    background: var(--pz-bg-raised, #ffffff);
    border-color: var(--pz-border, #e2e8f0);
    color: var(--pz-text-primary);
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.light-mode .portal-card h3 { color: var(--pz-text-primary); }
/* Dashboard */
.light-mode .dash-stat .stat-value { color: var(--pz-primary, #0284c7); }
.light-mode .dash-stat .stat-label { color: var(--pz-text-muted); }
.light-mode .manager-avatar { background: color-mix(in srgb, var(--pz-primary, #0284c7) 10%, transparent); }
.light-mode .manager-info h4 { color: var(--pz-text-primary); }
.light-mode .manager-info p { color: var(--pz-text-muted); }
.light-mode .manager-info a { color: var(--pz-primary, #0284c7); }
/* Tables */
/* S70 V_A.5 — overrides .light-mode .portal-table* SUPPRIMÉS (redondants).
   La cascade --pz-secondary-text + color-mix() gère les 2 modes auto. */
/* Forms */
/* S70 V_A.5 — overrides .light-mode .portal-form* SUPPRIMÉS (redondants).
   La cascade --pz-secondary + --pz-secondary-text gère les 2 modes auto. */
.light-mode .portal-btn { background: var(--pz-primary, #0284c7); }
.light-mode .portal-btn-outline { border-color: color-mix(in srgb, var(--pz-primary, #0284c7) 40%, transparent); color: var(--pz-primary, #0284c7); }
/* Filters */
.light-mode .portal-filters select { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); color: var(--pz-text-primary); }
/* Documents */
.light-mode .doc-cat-card { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); color: var(--pz-text-primary); }
.light-mode .doc-cat-card:hover { background: color-mix(in srgb, var(--pz-primary, #0284c7) 5%, transparent); border-color: var(--pz-primary, #0284c7); }
.light-mode .doc-cat-card .cat-icon { color: var(--pz-primary, #0284c7); }
.light-mode .doc-cat-card .cat-label { color: var(--pz-text-primary); }
.light-mode .doc-cat-card .cat-updated { color: var(--pz-text-muted); }
.light-mode .doc-download-btn { background: color-mix(in srgb, var(--pz-primary, #0284c7) 10%, transparent); color: var(--pz-primary, #0284c7); border-color: color-mix(in srgb, var(--pz-primary, #0284c7) 20%, transparent); }
.light-mode .doc-list-info .doc-icon { color: var(--pz-primary, #0284c7); }
.light-mode .doc-list-info .doc-title { color: var(--pz-text-primary); }
.light-mode .doc-list-info .doc-date { color: var(--pz-text-muted); }
.light-mode .doc-list-item { border-bottom-color: var(--pz-border-soft, #f1f5f9); }
/* Property cards */
.light-mode .property-header .prop-ref-badge { background: color-mix(in srgb, var(--pz-primary, #0284c7) 10%, transparent); color: var(--pz-primary, #0284c7); }
.light-mode .lot-card { background: color-mix(in srgb, var(--pz-text-primary) 2%, transparent); border-color: var(--pz-border, #e2e8f0); }
.light-mode .lot-card .lot-number { color: var(--pz-primary, #0284c7); }
.light-mode .lot-card .lot-detail { color: var(--pz-text-muted); }
/* Requests */
.light-mode .thread-message.msg-client { background: color-mix(in srgb, var(--pz-primary, #0284c7) 5%, transparent); border-left-color: var(--pz-primary, #0284c7); }
.light-mode .thread-message .msg-sender { color: var(--pz-text-primary); }
.light-mode .thread-message .msg-date { color: var(--pz-text-muted); }
.light-mode .thread-message .msg-body { color: var(--pz-border, #334155); }
.light-mode .thread-attachment { color: var(--pz-primary, #0284c7); background: color-mix(in srgb, var(--pz-text-primary) 3%, transparent); }
/* Back link, section headers */
.light-mode .back-link { color: var(--pz-primary, #0284c7); }
.light-mode .section-header h3 { color: var(--pz-text-primary); }
.light-mode .section-header a { color: var(--pz-primary, #0284c7); }
/* Empty state */
.light-mode .empty-state { color: var(--pz-text-muted); }
/* Badges */
.light-mode .badge-upcoming { background: color-mix(in srgb, var(--pz-primary, #0284c7) 10%, transparent); color: var(--pz-primary, #0284c7); border-color: color-mix(in srgb, var(--pz-primary, #0284c7) 20%, transparent); }
/* Balance */
.light-mode .balance-label { color: var(--pz-text-muted); }
.light-mode .balance-amount { color: var(--pz-text-primary); }
/* Login */
.light-mode .login-box { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
.light-mode .login-box h1 { color: var(--pz-text-primary); }
.light-mode .login-box .login-subtitle { color: var(--pz-text-muted); }
/* Brand colors fixés sur fond #c5dffb (navy + olive marque) en clair comme en sombre */
.light-mode .login-brand-title { color: var(--pz-bg-base, #0a1d3e); }
.light-mode .login-brand-tagline { color: var(--pz-brand-accent, #768c47); }
.light-mode .login-box label { color: var(--pz-text-secondary); }
.light-mode .login-box input { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); color: var(--pz-text-primary); }
.light-mode .login-box input:focus { border-color: var(--pz-primary, #0284c7); }
.light-mode .login-box .login-submit { background: var(--pz-primary, #0284c7); }
.light-mode .login-box .login-footer { color: var(--pz-text-muted); }
.light-mode .login-box .login-footer a { color: var(--pz-primary, #0284c7); }
/* Assembly */
.light-mode .assembly-info h4 { color: var(--pz-text-primary); }
.light-mode .assembly-info p { color: var(--pz-text-muted); }
/* Syndic tiles & stats */
.light-mode .syndic-stats-bar .syndic-stat { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); }
.light-mode .syndic-stat-value { color: var(--pz-primary, #0284c7); }
.light-mode .syndic-stat-label { color: var(--pz-text-muted); }
.light-mode .syndic-residence-tile { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); }
.light-mode .syndic-residence-tile:hover { border-color: var(--pz-primary, #0284c7); }
.light-mode .residence-photo { background: linear-gradient(135deg, var(--pz-border-soft, #f1f5f9) 0%, var(--pz-border, #e2e8f0) 100%); }
.light-mode .residence-name { color: var(--pz-text-primary); }
.light-mode .residence-address { color: var(--pz-text-muted); }
.light-mode .residence-maps-link { color: var(--pz-text-secondary); background: var(--pz-border-soft, #f1f5f9); }
.light-mode .residence-maps-link:hover { color: var(--pz-text-on-primary, #fff); background: var(--pz-primary, #0284c7); }
.light-mode .resi-stat-main { background: var(--pz-bg-raised, #f8fafc); border-color: var(--pz-border, #e2e8f0); color: inherit; }
.light-mode .resi-stat-main:hover { background: var(--pz-border-soft, #f1f5f9); }
.light-mode .resi-stat-main-value { color: var(--pz-text-primary); }
.light-mode .resi-stat-main-label { color: var(--pz-text-muted); }
.light-mode .residence-card-sub-stats { border-top-color: var(--pz-border, #e2e8f0); }
.light-mode .resi-sub-stat { color: var(--pz-text-muted); }
.light-mode .resi-sub-stat-value { color: var(--pz-text-primary); }
.light-mode .resi-sub-stat-label { color: var(--pz-text-muted); }
.light-mode .syndic-viewer-notice { background: var(--pz-warning-soft, #fffbeb); border-color: var(--pz-warning-soft, #fde68a); color: var(--pz-warning-active, #92400e); }
/* Data complex groups */
.light-mode .data-complex-group .portal-card { background: var(--pz-bg-base, #fff); border-color: var(--pz-border, #e2e8f0); }
/* Form small inputs (syndic inline forms) */
.light-mode .form-input-sm { background: var(--pz-bg-base, #fff) !important; border-color: var(--pz-border-strong, #d1d5db) !important; color: var(--pz-text-primary) !important; }
.light-mode .form-label-sm { color: var(--pz-text-secondary) !important; }

/* ─── Responsive ─────────────────────────────────────────── */
@media (max-width: 900px) {
    .portal-topbar { padding: 0 12px; gap: 8px; }
    .topbar-nav { display: none; }
    .topbar-right { gap: 16px; }
    .topbar-link, .topbar-link-user, .topbar-link-logout { font-size: .78rem; }
    .settings-panel { width: 100%; right: -100%; }

    .portal-sidebar {
        transform: translateX(-100%);
        transition: transform 0.3s ease;
    }

    .portal-sidebar.open {
        transform: translateX(0);
    }

    .portal-content {
        margin-left: 0;
        padding: 20px 16px 60px;
        /* S196ter audit mobile Léa P0-1 — le max-width desktop (calc(100vw - 280px), :890)
           n'était JAMAIS reseté en mobile → contenu confiné à 95px sur iPhone 375px
           (régression S122, portail mathématiquement illisible au téléphone). */
        max-width: 100vw;
    }

    .accueil-grid {
        grid-template-columns: 1fr;
    }

    .dashboard-grid {
        grid-template-columns: 1fr;
    }

    .doc-categories {
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    }

    .portal-table {
        font-size: 0.8rem;
    }

    .portal-table thead th,
    .portal-table tbody td {
        padding: 10px 8px;
    }
}

@media (max-width: 480px) {
    .login-box {
        padding: 28px 20px;
    }

    .doc-categories {
        grid-template-columns: 1fr 1fr;
    }

    .lots-grid {
        grid-template-columns: 1fr;
    }
}

/* ═══════════════════════════════════════
   SYNDIC DASHBOARD
   ═══════════════════════════════════════ */

/* ── Syndic stats bar (compact, single line) ── */
.syndic-stats-bar {
    display: flex;
    gap: 4px;
    margin-bottom: 20px;
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-card-lg, 10px);
    padding: 10px 6px;
}

.syndic-stat {
    flex: 1;
    text-align: center;
    padding: 4px 8px;
    border-right: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    text-decoration: none;
    color: inherit;
    display: block;
}

.syndic-stat:last-child { border-right: none; }
.syndic-stat--link {
    cursor: pointer;
    border-radius: var(--pz-radius-card, 6px);
    transition: background 0.15s;
}
.syndic-stat--link:hover {
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
}

.syndic-stat-value {
    display: block;
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--pz-brand-accent, #00d4ff);
    line-height: 1.2;
}

.syndic-stat-value.negative { color: var(--pz-warning, #f59e0b); }

.syndic-stat-label {
    display: block;
    font-size: 0.7rem;
    color: rgba(255, 255, 255, 0.55);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 2px;
}

.syndic-viewer-notice {
    background: rgba(59, 130, 246, 0.15);
    border: 1px solid rgba(59, 130, 246, 0.3);
    color: var(--pz-info-soft-text, #93c5fd);
    padding: 10px 16px;
    border-radius: var(--pz-radius-md, 8px);
    font-size: 0.85rem;
    margin-bottom: 16px;
}

/* ── Dashboard top (S97 V_A bis 15 — A=B=280px : 2 lignes tuiles complètes fold + alignement) ── */
.syndic-dashboard-top {
    display: grid;
    /* S150 retour Arnaud #2 — 3 tuiles par ligne (plus larges) : chiffres · tendances · carte sur la 1re
       ligne ; Infos Luxembourg (4e tuile, même largeur) passe en 2e ligne. Avant : 4 col = trop serré. */
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: 280px;     /* 1re ligne fixe ; les lignes implicites (Infos) s'ajustent au contenu */
    grid-auto-rows: auto;
    gap: 10px;
    margin-bottom: 10px;
}
/* S150 — la card Lux (4e enfant, 2e ligne) garde la largeur d'une tuile (1/3) comme les autres. */
.syndic-dashboard-top > .pz-lux-info-card { border-radius: 0; }
/* Sprint 124 V_A.6 — densité 4→8 metrics grid 2 cols × 4 rows (canon dashboard cross-ctx S125+ V_A).
   Classe `.pz-dashboard-stats-grid` portable propagation autres ctx (admin/client/prestataire). */
.syndic-stats-col,
.pz-dashboard-stats-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: 1fr;
    gap: 4px;
}
.syndic-stats-col .syndic-stat {
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: 0; /* S124 V_A.6 canon carrés strict (Arnaud directive) */
    padding: 8px 10px;
    text-align: left;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-right: none;
    min-height: 0;
}
.syndic-stats-col .syndic-stat-value {
    font-size: 1.1rem;
    order: 2;
    white-space: nowrap;
}
.syndic-stats-col .syndic-stat-label {
    margin-top: 0;
    order: 1;
    font-size: 0.62rem;
}
/* Sprint 124 V_A.6 — tile compact 8 metrics 2 cols (textes visibles + carrés strict canon). */
.syndic-stats-col > .pz-kpi,
.pz-dashboard-stats-grid > .pz-kpi {
    min-height: 0;
    padding: 6px 8px;
    align-items: center;
    justify-content: center;
    text-align: center;
    border-radius: 0; /* S124 V_A.6 canon carrés strict (Arnaud directive) */
    /* S178 retour Arnaud (round 5) — fond = `var(--pz-bg-raised)` opaque, IDENTIQUE aux
       grandes cards de résidence (.pz-residence-card ligne 63 de residence_card.php).
       Round 4 (3% transparent) ne matchait pas visuellement : Arnaud parlait des CARDS
       résidence (containers Bellavista/Londres) pas des sub-tiles .resi-stat-main.
       Override scopé dashboard top only ; reste du repo garde le canon global .pz-kpi 28%. */
    background: var(--pz-bg-raised);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-color: color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
}
/* S151 retour Arnaud — chiffre sur sa propre ligne EN HAUT, nom de la métrique EN DESSOUS
   (au lieu du rendu inline baseline du composant). Scopé au dashboard stats-grid uniquement. */
.syndic-stats-col > .pz-kpi .pz-kpi-head,
.pz-dashboard-stats-grid > .pz-kpi .pz-kpi-head {
    flex-direction: column;
    align-items: center;
    gap: 1px;
}
.syndic-stats-col > .pz-kpi .pz-kpi-value,
.pz-dashboard-stats-grid > .pz-kpi .pz-kpi-value {
    font-size: 1.26rem; /* S151 retour Arnaud — +20 % (1.05 → 1.26) */
    line-height: 1.1;
}
.syndic-stats-col > .pz-kpi .pz-kpi-label,
.pz-dashboard-stats-grid > .pz-kpi .pz-kpi-label {
    font-size: 0.81rem; /* S151 retour Arnaud — +30 % (0.62 → 0.81) */
    line-height: 1.15;
    white-space: normal; /* Sprint 124 V_A.6 — autorise wrap text labels longs (AG ≤ 2 mois, etc.) */
}
/* Sprint 124 V_A.6 — canon carrés strict propagé dashboard syndic top (override portal-card vers angle droit).
   Propagation autres ctx canon strict S125+ V_A : remplacer `.syndic-dashboard-top` par `.pz-dashboard-top`. */
.syndic-dashboard-top .portal-card,
.syndic-dashboard-top .pz-trends-cell { border-radius: 0; }
.syndic-dashboard-map {
    position: relative;
    padding: 0;
    overflow: hidden;
    height: 100%;
}
.syndic-dashboard-map > #syndicMap { height: 100%; background: var(--pz-text-primary); }
.syndic-dashboard-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--pz-text-muted);
    text-align: center;
    padding: 24px;
    height: 100%;
    border: 1px dashed color-mix(in srgb, var(--pz-text-primary) 12%, transparent);
}
.syndic-dashboard-placeholder .ph-icon { font-size: 2.4rem; opacity: .4; margin-bottom: 10px; }
.syndic-dashboard-placeholder .ph-title { font-weight: 600; color: var(--pz-text-muted); margin-bottom: 4px; }
.syndic-dashboard-placeholder .ph-sub { font-size: .78rem; }
@media (max-width: 1200px) {
    /* Sprint 91 Bug 4 — swap KPI/Placeholder/Map : à 1200px, KPI + Placeholder ligne 1, Map ligne 2 full. */
    .syndic-dashboard-top {
        grid-template-columns: 1fr 1fr;
        grid-auto-rows: auto;
    }
    .syndic-stats-col { height: 280px; }
    .syndic-dashboard-placeholder { height: 280px; padding: 14px; }
    .syndic-dashboard-trends { height: 280px; }
    .syndic-dashboard-map { grid-column: 1 / -1; height: 260px; }
}
@media (max-width: 900px) {
    .syndic-dashboard-top { grid-template-columns: 1fr; }
    .syndic-dashboard-map { grid-column: auto; height: 280px; }
    .syndic-dashboard-placeholder { height: 100px; }
}

/* ── Residence tiles (S97 V_A bis 15 — hauteur fixe 280px : A=B + 2 lignes fold) ── */
.syndic-residences-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 290px;       /* S124 V_A.6.2 retour Arnaud — réduire espace vide entre bloc2 et footer strip (V_A.6.1 340 → V_A.6.2 290 = contenu naturel exact header 40 + bloc1 140 + bloc2 80 + footer 32) */
    align-items: stretch;
    gap: 8px;
    margin-top: 0;
    margin-bottom: 12px;
    padding-bottom: 0;
}

/* Sprint 97 V_A bis 6 — Mini-trends compactés pour tenir 240px parent grid cell */
.syndic-dashboard-trends {
    display: flex; flex-direction: column; gap: 6px;
    padding: 10px 12px;
    /* S190 (retour live Arnaud) — fond aligné sur les cartes résidence (Atrium) + les tuiles KPI du
       dashboard : var(--pz-bg-raised) (token color-picker), au lieu du 4% text-primary qui tranchait. */
    background: var(--pz-bg-raised);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: 0; /* S124 V_A.6.1 retour Arnaud — canon carrés strict TOUS coins (override token --pz-radius-card-lg 10px) */
    overflow: hidden;
    height: 100%;
    box-sizing: border-box;
    /* S167 BUG-02 (ombre résiduelle) — backdrop-filter RETIRÉ sur cette carte : sa combinaison avec
       le compositing Firefox laissait un ghost/ombre grise au paint (récurrent). La carte a déjà un
       fond opaque, le blur n'apporte rien ici. isolation:isolate force une couche propre. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    isolation: isolate;
}
/* S178 retour Arnaud (2e passe) — la règle `.portal-card h3` (portal.css ligne 947,
   spécificité 0,1,1) écrasait `.pz-trends-title` (0,1,0) avec --pz-text-on-primary →
   titre invisible cas picker brand proche fond shell. Sélecteur `.portal-card .pz-trends-title`
   (0,2,0) bat la cascade sans !important.
   « le titre de tendances doit utiliser le même color picker que les titres » = canon
   --pz-text-primary (le picker user « Texte principal », mig 171). */
.pz-trends-title,
.portal-card .pz-trends-title {
    margin: 0 0 2px;
    /* S191 (retour live Arnaud) — titre « TENDANCES 6 SEMAINES » +30% (.72 → .94rem) pour l'harmonie. */
    font-size: .94rem; font-weight: 700;
    color: var(--pz-text-primary);
    text-transform: uppercase; letter-spacing: .05em;
}
.pz-trends-grid {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: 6px;
    flex: 1;
    min-height: 0;
}
.pz-trends-cell {
    display: flex; flex-direction: column; justify-content: center;
    padding: 6px 8px;
    /* S178 retour Arnaud round 5 — fond IDENTIQUE aux 8 tuiles KPI metrics du dashboard
       (canon --pz-bg-raised opaque, cf .syndic-stats-col > .pz-kpi). Les tuiles « Tendances
       6 semaines » et les KPI metrics doivent avoir la même couleur de fond. */
    background: var(--pz-bg-raised);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: 0;
    text-decoration: none;
    color: inherit;
    transition: transform .12s ease, border-color .12s ease;
    min-width: 0;
}
.pz-trends-cell.is-link { cursor: pointer; }
.pz-trends-cell.is-link:hover {
    /* S167 BUG-02 — transform retiré (ghost Firefox backdrop-filter+transform). Bordure suffit. */
    border-color: color-mix(in srgb, var(--pz-info, #60a5fa) 30%, transparent);
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
}
.pz-trends-cell-label {
    font-size: .58rem; font-weight: 600;
    /* S178 — picker-réactif (canon resi-stat-main-label) vs --pz-secondary-text fixe. */
    color: color-mix(in srgb, var(--pz-text-primary) 55%, transparent);
    text-transform: uppercase; letter-spacing: .04em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pz-trends-cell-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 6px; margin-top: 2px;
}
.pz-trends-cell-value {
    font-size: 1rem; font-weight: 700; line-height: 1;
    /* S178 — chiffre principal = canon « Texte principal » (picker user). */
    color: var(--pz-text-primary);
    white-space: nowrap;
}
.pz-trends-cell-spark { display: flex; align-items: center; }

.syndic-residence-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-card-lg, 10px);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s;
}

.syndic-residence-tile:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 40%, transparent);
    box-shadow: 0 6px 24px color-mix(in srgb, var(--pz-primary, #0ea5e9) 15%, transparent);
}

/* Stretched link covers the whole tile so the photo + main info are clickable.
   z-index:1 met le lien au-dessus des frères en position:static, mais les enfants
   interactifs en position:relative;z-index:2 restent cliquables grâce au même
   stacking context. Pas de position:relative sur les parents .residence-photo /
   .residence-info — sinon ils piègeraient les enfants et absorberaient les clics. */
.residence-tile-link {
    position: absolute;
    inset: 0;
    z-index: 1;
    text-indent: -9999px;
    overflow: hidden;
    background: transparent;
}

.residence-photo {
    height: 110px;
    overflow: hidden;
    /* S167 BUG-12 — fond dérivé du color picker Sidney (--pz-secondary) au lieu du navy figé
       (--pz-bg-shell). La zone reste neutre quand la photo est absente (placeholder), mais suit
       désormais le thème de marque du cabinet. */
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--pz-secondary, #1a2744) 92%, black) 0%,
        color-mix(in srgb, var(--pz-secondary, #1a2744) 78%, white) 100%);
    display: flex;
    align-items: center;
    justify-content: center;
}

.residence-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.residence-photo-placeholder {
    font-size: 2.5rem;
    opacity: 0.2;
}

.residence-info {
    padding: 12px 14px;
}

.residence-name {
    font-size: 1rem;
    font-weight: 700;
    margin: 0 0 2px;
    color: var(--pz-text-on-primary, #fff);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.residence-address-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 12px;
}

.residence-address {
    flex: 1;
    min-width: 0;
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.55);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin: 0;
}

.residence-maps-link {
    position: relative;
    z-index: 2;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--pz-radius-card, 6px);
    color: rgba(255, 255, 255, 0.55);
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    transition: color 0.15s, background 0.15s;
    text-decoration: none;
}
.residence-maps-link:hover {
    color: var(--pz-text-on-primary, #fff);
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 40%, transparent);
}
.residence-maps-link svg {
    width: 14px;
    height: 14px;
    display: block;
}

.residence-card-main-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
    margin-bottom: 10px;
}
/* Main vignettes — layout horizontal compact : icône à gauche, bloc valeur+libellé
   centré verticalement à droite (flex column). Cliquables individuellement
   (z-index:2 au-dessus de la stretched-link).
   Sprint 08 hotfix : groupe icône+texte centré horizontalement dans la carte. */
.resi-stat-main {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    text-align: center;
    padding: 7px 9px;
    background: color-mix(in srgb, var(--pz-text-primary) 3%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-md, 8px);
    text-decoration: none;
    color: inherit;
    transition: background 0.15s, border-color 0.15s, transform 0.15s;
    cursor: pointer;
}
.resi-stat-main:hover {
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 35%, transparent);
    transform: translateY(-1px);
}
.resi-stat-main-icon {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
}
.resi-stat-main-icon svg {
    width: 16px;
    height: 16px;
    display: block;
}
/* Colored icon variants for each metric — color-mix respecte cascade tokens (Sidney palette) */
.resi-stat-main--buildings .resi-stat-main-icon {
    color: var(--pz-info, #38bdf8);
    background: color-mix(in srgb, var(--pz-info, #38bdf8) 14%, transparent);
}
.resi-stat-main--apartments .resi-stat-main-icon {
    color: var(--pz-brand-accent, #a78bfa);
    background: color-mix(in srgb, var(--pz-brand-accent, #a78bfa) 14%, transparent);
}
.resi-stat-main--occupants .resi-stat-main-icon {
    color: var(--pz-warning, #fbbf24);
    background: color-mix(in srgb, var(--pz-warning, #fbbf24) 14%, transparent);
}
.resi-stat-main-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
    line-height: 1;
}
.resi-stat-main-value {
    display: block;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--pz-text-primary, #e2e8f0);
    line-height: 1.1;
}
.resi-stat-main-label {
    display: block;
    font-size: 0.58rem;
    color: rgba(255, 255, 255, 0.55);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.residence-card-sub-stats {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    align-items: center;
    padding-top: 8px;
    border-top: 1px dashed color-mix(in srgb, var(--pz-text-primary) 7%, transparent);
}
.resi-sub-stat {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.72rem;
    color: rgba(255, 255, 255, 0.55);
    white-space: nowrap;
}
.resi-sub-stat svg {
    width: 12px;
    height: 12px;
    display: block;
    opacity: 0.75;
    flex: 0 0 auto;
}
.resi-sub-stat-value {
    font-weight: 600;
    color: rgba(255, 255, 255, 0.7);
}
.resi-sub-stat-label {
    color: rgba(255, 255, 255, 0.55);
}

/* ── Category tiles (residence view) ── */
.syndic-category-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-top: 4px;
}

.syndic-category-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-card-lg, 10px);
    padding: 24px 16px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s;
}

.syndic-category-tile:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 40%, transparent);
    box-shadow: 0 6px 24px color-mix(in srgb, var(--pz-primary, #0ea5e9) 15%, transparent);
}

.category-tile-icon {
    font-size: 2.2rem;
    margin-bottom: 8px;
    opacity: 0.7;
}

.category-tile-label {
    font-size: 1rem;
    font-weight: 700;
    color: var(--pz-text-on-primary, #fff);
    margin-bottom: 4px;
}

.category-tile-count {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--pz-brand-accent, #00d4ff);
    line-height: 1.2;
}

.category-tile-desc {
    font-size: 0.72rem;
    color: rgba(255, 255, 255, 0.45);
    margin-top: 4px;
}

/* ── Virtual intercom ── */
/* S150 retour Arnaud — tuiles métriques intercom : coins carrés (canon). */
.intercom-tiles > .pz-kpi { border-radius: 0; }
.intercom-wrapper {
    /* S150 retour Arnaud — pleine largeur sous les tuiles (avant : 800px centré → grande zone vide à gauche). */
    max-width: none;
    margin: 16px 0 0;
}

.intercom-back {
    display: inline-block;
    color: var(--pz-brand-accent, #00d4ff);
    text-decoration: none;
    font-size: 0.9rem;
    margin-bottom: 16px;
}

.intercom-back:hover { text-decoration: underline; }

.intercom-header {
    text-align: center;
    padding: 24px 20px 16px;
    background: linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0.02) 100%);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-radius: 0; /* S150 retour Arnaud — coins carrés (canon) */
    border-bottom: none;
}

.intercom-header h2 {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--pz-text-on-primary, #fff);
    margin: 0 0 4px;
}

.intercom-header .intercom-building-name {
    font-size: 0.9rem;
    color: rgba(255, 255, 255, 0.55);
}

.intercom-floor-label {
    padding: 6px 16px;
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 10%, transparent);
    border-left: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-right: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.55);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
}

/* Column headers */
.intercom-colheaders {
    display: flex;
    align-items: center;
    padding: 6px 16px;
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-bottom: none;
    background: color-mix(in srgb, var(--pz-text-primary) 3%, transparent);
    font-size: 0.7rem;
    color: rgba(255, 255, 255, 0.45);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
}

.intercom-colh-name { flex: 2; }
.intercom-colh-unit { flex: 1; }
.intercom-colh-role { flex: 1.2; }
.intercom-colh-actions { flex: 0 0 110px; text-align: center; }

.intercom-entry {
    display: flex;
    align-items: center;
    padding: 10px 16px;
    border-left: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-right: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    background: color-mix(in srgb, var(--pz-text-primary) 2%, transparent);
    gap: 12px;
}

/* Compact single-line layout */
.intercom-entry-compact {
    padding: 6px 16px;
    gap: 0;
}

.intercom-entry-compact .intercom-entry-name { flex: 2; }
.intercom-entry-compact .intercom-entry-unit { flex: 1; }
.intercom-entry-compact .intercom-entry-role { flex: 1.2; }
.intercom-entry-compact .intercom-actions    { flex: 0 0 110px; justify-content: center; }

.intercom-entry:hover {
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
}

.intercom-entry-info {
    flex: 1;
    min-width: 0;
}

.intercom-entry-name {
    font-weight: 600;
    color: var(--pz-text-on-primary, #fff);
    font-size: 0.88rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.intercom-entry-unit {
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.55);
}

.intercom-entry-role {
    font-size: 0.7rem;
    color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 80%, transparent);
    text-transform: uppercase;
}

.intercom-btn-disabled {
    opacity: 0.15;
    cursor: default;
    pointer-events: none;
}

.intercom-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

.intercom-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 12%, transparent);
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    color: rgba(255, 255, 255, 0.7);
    text-decoration: none;
    font-size: 1rem;
    transition: background 0.2s, border-color 0.2s, color 0.2s;
    cursor: pointer;
}

.intercom-btn:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 20%, transparent);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 50%, transparent);
    color: var(--pz-brand-accent, #00d4ff);
}

.intercom-btn-email:hover { background: rgba(59, 130, 246, 0.2); border-color: var(--pz-info, #2563eb); color: var(--pz-info-hover, #60a5fa); }
.intercom-btn-sms:hover   { background: rgba(34, 197, 94, 0.2);  border-color: var(--pz-success, #10b981); color: var(--pz-success, #4ade80); }
.intercom-btn-call:hover  { background: rgba(234, 179, 8, 0.2);  border-color: var(--pz-warning, #eab308); color: var(--pz-warning, #facc15); }

.intercom-footer {
    display: flex;
    gap: 10px;
    padding: 14px 16px;
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-radius: 0 0 12px 12px;
    border-top: none;
    background: color-mix(in srgb, var(--pz-text-primary) 3%, transparent);
}

.intercom-bulk-btn {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 14px;
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-primary, #0ea5e9) 25%, transparent);
    border-radius: var(--pz-radius-md, 8px);
    color: var(--pz-brand-accent, #00d4ff);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 600;
    transition: background 0.2s;
}

.intercom-bulk-btn:hover {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 25%, transparent);
}

.intercom-empty {
    text-align: center;
    padding: 24px 16px;
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border-top: none;
    color: rgba(255, 255, 255, 0.45);
    font-size: 0.9rem;
}

/* Intercom compact table */
.intercom-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.85rem;
}
.intercom-table thead th {
    text-align: left;
    padding: 8px 10px;
    color: var(--pz-text-muted);
    font-weight: 600;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 12%, transparent);
    white-space: nowrap;
}
.intercom-th-name { min-width: 140px; }
.intercom-th-role { min-width: 90px; }
.intercom-th-unit { min-width: 60px; }
.intercom-th-actions { min-width: 100px; text-align: center; }
.intercom-row td {
    padding: 3px 10px; /* S150 retour Arnaud — espacement entre noms réduit */
    border-bottom: 1px solid color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    vertical-align: middle;
}
.intercom-row:hover { background: color-mix(in srgb, var(--pz-text-primary) 3%, transparent); }
.intercom-td-name { font-weight: 600; color: var(--pz-text-primary, #e2e8f0); white-space: nowrap; }
.intercom-td-role { color: var(--pz-text-muted); font-size: 0.8rem; }
.intercom-td-unit { color: var(--pz-border-soft); font-size: 0.82rem; font-family: monospace; }
.intercom-td-actions { text-align: center; white-space: nowrap; }
.intercom-resident-badge {
    display: inline-block;
    background: rgba(34,197,94,0.15);
    color: var(--pz-success, #4ade80);
    font-size: 0.65rem;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: var(--pz-radius-sm, 4px);
    margin-left: 4px;
    vertical-align: middle;
}

.light-mode .intercom-table thead th { color: var(--pz-text-muted); border-bottom-color: var(--pz-border, #e2e8f0); }
.light-mode .intercom-row td { border-bottom-color: var(--pz-border-soft, #f1f5f9); }
.light-mode .intercom-row:hover { background: color-mix(in srgb, var(--pz-text-primary) 2%, transparent); }
.light-mode .intercom-td-name { color: var(--pz-text-primary); }
.light-mode .intercom-td-role { color: var(--pz-text-muted); }
.light-mode .intercom-td-unit { color: var(--pz-text-secondary); }
.light-mode .intercom-resident-badge { background: rgba(34,197,94,0.1); color: var(--pz-success-hover, #16a34a); }

/* Syndic residence — buildings grid */
.syndic-buildings-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
    margin-top: 8px;
}

.syndic-building-tile {
    display: block;
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 8%, transparent);
    border-radius: var(--pz-radius-card-lg, 10px);
    padding: 20px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s;
}

.syndic-building-tile:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--pz-primary, #0ea5e9) 40%, transparent);
    box-shadow: 0 6px 24px color-mix(in srgb, var(--pz-primary, #0ea5e9) 15%, transparent);
}

.building-tile-icon {
    font-size: 2rem;
    margin-bottom: 8px;
    opacity: 0.6;
}

.building-tile-name {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--pz-text-on-primary, #fff);
    margin-bottom: 4px;
}

.building-tile-stats {
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.55);
}

/* Phone popup */
.phone-popup-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.6);
    z-index: 1000;
    align-items: center;
    justify-content: center;
}

.phone-popup-overlay.active { display: flex; }

.phone-popup {
    background: var(--pz-bg-base, #1a2744);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 15%, transparent);
    border-radius: var(--pz-radius-lg, 12px);
    padding: 28px 32px;
    text-align: center;
    min-width: 280px;
}

.phone-popup-number {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--pz-brand-accent, #00d4ff);
    margin: 12px 0;
    letter-spacing: 0.05em;
}

.phone-popup-name {
    font-size: 0.9rem;
    color: rgba(255,255,255,0.6);
    margin-bottom: 4px;
}

.phone-popup-close {
    display: inline-block;
    margin-top: 16px;
    padding: 8px 24px;
    background: color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 15%, transparent);
    border-radius: var(--pz-radius-card, 6px);
    color: var(--pz-text-on-primary, #fff);
    cursor: pointer;
    font-size: 0.85rem;
}

.phone-popup-close:hover { background: color-mix(in srgb, var(--pz-text-primary) 18%, transparent); }

@media (max-width: 1400px) {
    .syndic-residences-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 768px) {
    .syndic-residences-grid {
        grid-template-columns: 1fr;
    }

    .syndic-stats-bar {
        flex-wrap: wrap;
    }

    .syndic-stat {
        flex: 0 0 calc(33% - 4px);
        border-right: none;
    }

    .residence-photo {
        height: 100px;
    }

    .intercom-footer {
        flex-direction: column;
    }

    .syndic-category-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .intercom-table {
        font-size: 0.78rem;
    }
    .intercom-table thead th,
    .intercom-row td {
        padding: 5px 6px;
    }
    .intercom-th-unit, .intercom-td-unit {
        min-width: 40px;
    }
}

/* ============================================================
   Sprint 24 Q7 — UI Help Tooltips (lib/ui_help.php, migration 045)
   ============================================================ */
.pz-help-i {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    margin-left: 4px;
    border-radius: 50%;
    background: var(--pz-neutral, #6b7280);
    color: var(--pz-text-on-primary, #fff);
    font-size: 11px;
    font-weight: 700;
    font-family: serif;
    font-style: italic;
    cursor: help;
    user-select: none;
    vertical-align: middle;
    position: relative;
    transition: background 0.15s;
}
.pz-help-i:hover,
.pz-help-i:focus {
    background: var(--pz-info, #2563eb);
    outline: none;
}

.pz-help-bubble {
    position: absolute;
    z-index: 1000;
    max-width: 360px;
    min-width: 240px;
    padding: 12px 14px;
    background: var(--pz-bg-shell-modal, #1f2937);
    color: var(--pz-bg-raised, #f9fafb);
    border-radius: var(--pz-radius-card, 6px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.25);
    font-size: 0.85rem;
    line-height: 1.45;
    pointer-events: none;
}
.pz-help-bubble[data-pz-help-open] {
    display: block;
    pointer-events: auto;
}
.pz-help-bubble__title {
    display: block;
    margin-bottom: 6px;
    font-size: 0.9rem;
    color: var(--pz-warning, #fbbf24);
}
.pz-help-bubble__body p {
    margin: 0 0 6px 0;
}
.pz-help-bubble__body p:last-child {
    margin-bottom: 0;
}
.pz-help-bubble__body code {
    background: var(--pz-bg-raised, #374151);
    padding: 1px 4px;
    border-radius: var(--pz-radius-sm, 4px);
    font-size: 0.8em;
}
.pz-help-bubble__body ul {
    margin: 4px 0;
    padding-left: 18px;
}

/* ─── Tickets : grille photos (G5 Sprint 27, 5×5) ─── */
.ticket-photos-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
}
@media (max-width: 768px) {
    .ticket-photos-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}
@media (max-width: 480px) {
    .ticket-photos-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}
.ticket-photo-cell {
    display: block;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: var(--pz-radius-card, 6px);
    border: 1px solid var(--pz-border);
    background: var(--pz-text-primary);
}
.ticket-photo-cell img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.2s ease;
}
.ticket-photo-cell:hover img {
    transform: scale(1.05);
}

/* ════════════════════════════════════════════════════════════════════
 * Sprint 33 V1 — Topbar 9 éléments + Mayday (BRD UI v1 §3.5)
 * Préfixe .pz-topbar-* pour distinguer des classes legacy .portal-topbar.
 * Hérite des tokens CSS (tokens.css S31 Bloc 1).
 * ════════════════════════════════════════════════════════════════════ */

.pz-topbar {
    display: flex; align-items: center; gap: 8px;
    padding: 4px 12px; min-height: 44px; /* S124 V_A.6.8 retour Arnaud — réduction hauteur 52→44px (compact pro) + gap 12→8 + padding 16→12 */
    /* Sprint 65 R3 : shell utilise --pz-secondary (fond shell user-customisable). */
    background: var(--pz-secondary);
    color: var(--pz-secondary-text);
    border-bottom: 1px solid var(--pz-border);
    /* S120 V_A.5 retour Arnaud #1 : topbar z-index 100 → 1000 (Layer 2 canon Léa A38).
       Le picker dropdown enfant en z-index 1000 reste prisonnier du stacking context
       du topbar. Pour qu'il chapeaute la sidebar (z-index 100), le topbar lui-même
       doit être en Layer 2 (≥ sidebar). */
    position: sticky; top: 0; z-index: 1000;
}
/* Logo : largeur calée sur sidebar (280px) - padding gauche (16px) - gap (12px)
   = 252px → le chip "Syndic" qui suit s'aligne pile sur le bord droit
   de la sidebar (x = 280px). Désactivé sur mobile (sidebar masquée). */
/* S70 V_A.2 — Logo Petzerhiel = canonique mode-aware (bleu en clair, blanc en sombre).
   Pas de user-theme override (logo Petzerhiel = identité plateforme fixe).
   S70 V_A.3 hotfix : double sécurité via sélecteurs body directs (la cascade var()
   peut être prise en défaut par certains contextes browser/cache). */
.pz-topbar-logo {
    color: var(--pz-brand-logo, #0ea5e9); text-decoration: none;
    font-weight: 600; font-size: 1.05rem; letter-spacing: -0.01em;
    white-space: nowrap;
    /* S167 BUG-15 — zone logo = 280px (= largeur sidebar) pour que le chip « Syndic »
       qui suit s'aligne pile sur le bord droit de la sidebar. */
    min-width: 280px;
}
/* S178 — Logo topbar suit la couleur « Texte principal » du picker user (canon
   --pz-text-primary, comme titres/cellules de table). Avant : --pz-text-on-primary
   (texte SUR fond primary) qui pouvait être quasi-invisible si le picker brand
   était proche du fond shell (retour Arnaud screenshot index « logo doit etre de
   la couleur du texte principal »). Mode sombre = !important pour gagner la cascade
   legacy ou cache opcache résiduel. */
body.portal-page:not(.light-mode) .pz-topbar-logo,
body.admin-body:not(.light-mode) .pz-topbar-logo,
body.dark-mode .pz-topbar-logo {
    color: var(--pz-text-primary, #ffffff) !important;
}
/* Mode clair — idem pour cohérence canon (le picker texte principal pilote le 2 modes). */
body.light-mode .pz-topbar-logo {
    color: var(--pz-text-primary, #0f172a) !important;
}
@media (max-width: 768px) {
    /* Sprint 91 Bug 6 — logo recouvrait le chip "Syndic" mobile.
       Réduction font-size + flex-shrink pour que le chip reste lisible à droite. */
    .pz-topbar-logo {
        min-width: 0;
        font-size: .85rem;
        flex: 0 1 auto;
        max-width: 110px;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .pz-topbar-scope { flex: 0 1 auto; min-width: 0; overflow: hidden; }
    .pz-scope-chip { flex-shrink: 0; }
}
.pz-topbar-logo:hover { opacity: .85; }

/* S70 V_A.2 — Tous les sélecteurs shell consomment --pz-secondary-text (couplé au fond
   shell --pz-secondary du thème syndic). Variants medium/soft/faint via color-mix()
   pour cohérence luminance dans les 2 modes (clair/sombre × thème user). */
.pz-topbar-scope { display: inline-flex; align-items: center; gap: 6px; font-size: .9rem; }
.pz-scope-chip {
    color: color-mix(in srgb, var(--pz-secondary-text) 70%, transparent); text-decoration: none;
    padding: 4px 10px; border-radius: 0; /* S124 V_A.6.3 retour Arnaud — canon carrés strict topbar (vs --pz-radius-lg 12px pill legacy) */
    background: color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    transition: background .15s, color .15s;
}
.pz-scope-chip:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 14%, transparent);
    color: var(--pz-secondary-text);
}
.pz-scope-chip-static { cursor: default; }
.pz-scope-sep { color: color-mix(in srgb, var(--pz-secondary-text) 50%, transparent); }
.pz-scope-current { color: var(--pz-secondary-text); font-weight: 500; }

.pz-topbar-banner { flex: 0 1 auto; padding: 4px 10px; background: var(--pz-warning-soft, rgba(234,179,8,.15)); color: var(--pz-warning, #f59e0b); border-radius: 0; font-size: .85rem; } /* S124 V_A.6.3 carrés strict */
.pz-topbar-banner[hidden] { display: none; }

.pz-topbar-spacer { flex: 1 1 auto; }

.pz-topbar-search {
    display: inline-flex; align-items: center; gap: 4px;
    background: color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    border-radius: 0; padding: 2px 8px; /* S124 V_A.6.3 carrés strict */
    border: 1px solid transparent; transition: border-color .15s;
}
.pz-topbar-search:focus-within {
    border-color: color-mix(in srgb, var(--pz-secondary-text) 35%, transparent);
}
.pz-topbar-search-btn {
    background: none; border: 0; cursor: pointer; padding: 4px;
    color: color-mix(in srgb, var(--pz-secondary-text) 70%, transparent);
    display: inline-flex; align-items: center;
}
.pz-topbar-search-input {
    background: transparent; border: 0; padding: 4px 6px;
    color: var(--pz-secondary-text); font-size: .85rem; width: 180px;
}
.pz-topbar-search-input::placeholder {
    color: color-mix(in srgb, var(--pz-secondary-text) 45%, transparent);
}
.pz-topbar-search-input:focus { outline: none; }

.pz-topbar-action {
    display: inline-flex; align-items: center; gap: 6px;
    /* S122 V_A.1 retour Arnaud #22 — coins carrés canon (vs --pz-radius-card 6px legacy). */
    padding: 6px 10px; border-radius: 0;
    color: color-mix(in srgb, var(--pz-secondary-text) 75%, transparent);
    background: none; border: 0;
    text-decoration: none; cursor: pointer; font-size: .85rem;
    transition: background .15s, color .15s; position: relative;
}
.pz-topbar-action:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 12%, transparent);
    color: var(--pz-secondary-text);
}
/* S167 BUG-14 — le bouton « Nouveau » doit RESSEMBLER à un bouton (Sidney : « on ne voit pas
   que c'est un bouton »). On lui donne le fond/visuel du chip « Syndic » (.pz-scope-chip) :
   fond subtil permanent + bordure légère, pas seulement au hover. */
.pz-topbar-new > summary.pz-topbar-action {
    background: color-mix(in srgb, var(--pz-secondary-text) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--pz-secondary-text) 14%, transparent);
    font-weight: 600;
}
.pz-topbar-new > summary.pz-topbar-action:hover {
    background: color-mix(in srgb, var(--pz-secondary-text) 16%, transparent);
}
.pz-action-label { white-space: nowrap; }
/* S122 V_A.1 retour Arnaud #11 — chip visible résidence active sur picker topbar
   (cohérent visuellement vs ancien `.sidebar-scope-active` Bellavista retiré).
   S122 V_A.1 retour Arnaud #22 — bords carrés (border-radius:0 cohérent canon).
   S122 V_A.1 retour Arnaud #22 — font-size +20% sur picker résidence picker
   (Arnaud directive « agrandi de 20% le texte dans le bouton Toutes periodes »
   = label visible « Toutes mes résidences » ou « Résidence X »). */
.pz-complex-picker-trigger.is-residence-active {
    background: color-mix(in srgb, var(--pz-accent, #a1b81c) 18%, transparent);
    color: var(--pz-secondary-text);
    border: 1px solid color-mix(in srgb, var(--pz-accent, #a1b81c) 45%, transparent);
    border-radius: 0;
    font-weight: 600;
}
.pz-complex-picker-trigger.is-residence-active .pz-action-label {
    font-size: 1.02rem;
}
.pz-complex-picker-trigger.is-residence-active:hover {
    background: color-mix(in srgb, var(--pz-accent, #a1b81c) 28%, transparent);
}

/* Sprint 54 — bouton Mayday HTML pur (remplace SVG image avec cloche redondante).
 * Pill rouge gradient + texte "Mayday" + reflets internes pour effet premium.
 * Padding resserré sur le texte (Arnaud "petite marge"). */
.pz-topbar-mayday-btn {
    display: inline-flex; align-items: center; justify-content: center;
    /* S153 retour Arnaud — Mayday en VERT (primary Sidney), plus de rouge (réservé alertes). */
    background: var(--pz-primary, #0284c7);
    color: var(--pz-primary-text, #fff); border: 1px solid var(--pz-primary-active, #075985);
    padding: 4px 12px; border-radius: 0; /* S122 V_A.1 retour Arnaud #23 — coins carrés Mayday */
    font-weight: 700; font-size: .85rem; letter-spacing: .02em;
    text-decoration: none; cursor: pointer; white-space: nowrap;
    box-shadow: 0 1px 2px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.18);
    transition: background .15s, transform .15s, box-shadow .15s;
}
.pz-topbar-mayday-btn:hover {
    background: var(--pz-primary-hover, #0369a1);
    transform: translateY(-1px);
    box-shadow: 0 2px 6px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.2);
}
.pz-topbar-mayday-btn:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0,0,0,0.3), inset 0 2px 4px rgba(0,0,0,0.2);
}

.pz-topbar-bell { position: relative; }
/* Sprint 38 — badge cloche encore réduit (Arnaud feedback : trop gros) */
.pz-bell-badge {
    position: absolute; top: 0; right: 0;
    min-width: 14px; height: 14px; padding: 0 3px;
    background: var(--pz-danger, #dc2626); color: white;
    border-radius: 0; font-size: .55rem; font-weight: 700; /* S124 V_A.6.3 carrés strict */
    display: inline-flex; align-items: center; justify-content: center;
    line-height: 1;
}

.pz-avatar-initials {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: 50%;
    background: var(--pz-accent, #2563eb); color: white;
    font-size: .8rem; font-weight: 600;
}

/* Sprint 116 V_B fix bug visuel screenshot Sidney démo prep S115 V_C — Léa A38 hierarchy
   z-index cross-component référentiel : Layer 2 overlay topbar/picker ≥1000 vs Layer 1
   navbar sidebar/topbar/bottombar ≤999. Force stacking context élevé sur <details> ouvert
   pour garantir dropdown panel au-dessus de sidebar (z-index: 100) + topbar (z-index: 200)
   + bottombar (z-index: 110) cross-stacking-context. <details> fermé n'a pas besoin de z-index
   (rien à stacker), seulement [open] crée stacking context Layer 2 overlay canon. */
.pz-topbar-dropdown { position: relative; }
.pz-topbar-dropdown[open] { z-index: 1000; }
.pz-topbar-dropdown[open] > summary {
    background: color-mix(in srgb, var(--pz-secondary-text) 14%, transparent);
    color: var(--pz-secondary-text);
}
.pz-topbar-dropdown summary { list-style: none; }
.pz-topbar-dropdown summary::-webkit-details-marker { display: none; }
.pz-topbar-dropdown summary::marker { display: none; }

.pz-dropdown {
    position: absolute; top: calc(100% + 4px); min-width: 200px;
    /* S121 V_A.2 étape 9 retour Arnaud DEV CH : "la residence picker est bleu".
       Hardcoded rgba(15, 23, 42, 0.96) = slate #0f172a non-customisable user.
       Migré vers var(--pz-bg-raised) (customisable mig 116 user_theme S121 V_A.2)
       + var(--pz-border) idem. La cascade S121 V_A.2 garantit qu'override user
       (Sidney vert kaki) s'applique au fond + bordure du dropdown picker résidence. */
    background: var(--pz-bg-raised);
    border: 1px solid var(--pz-border);
    /* S124 V_A.6.3 retour Arnaud — canon carrés strict topbar harmonisation (override 6px legacy). */
    border-radius: 0; padding: 6px;
    box-shadow: 0 8px 24px rgba(0,0,0,.45);
    /* Sprint 116 V_B — Layer 2 overlay canon Léa A38 (≥1000) anti-overlap sidebar/topbar */
    z-index: 1000;
}
.light-mode .pz-dropdown {
    background: var(--pz-bg-base, #ffffff);
    border-color: var(--pz-border, #e2e8f0);
    color: var(--pz-text-primary);
    box-shadow: 0 8px 24px rgba(0,0,0,.12);
}
.pz-dropdown-right { right: 0; }
.pz-dropdown-header { padding: 6px 10px; font-size: .75rem; color: var(--pz-text-muted); text-transform: uppercase; letter-spacing: .05em; }
.pz-dropdown-item {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 10px; border-radius: var(--pz-radius-sm, 4px);
    color: var(--pz-text); text-decoration: none;
    background: none; border: 0; width: 100%; text-align: left;
    cursor: pointer; font-size: .85rem;
}
.pz-dropdown-item:hover { background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 8%, transparent)); }
.pz-dropdown-item.is-active { background: var(--pz-accent-soft, rgba(59,130,246,.15)); color: var(--pz-accent, #60a5fa); }
.pz-dropdown-item-danger { color: var(--pz-danger, #dc2626); }
.pz-dropdown-item-danger:hover { background: var(--pz-danger-soft, rgba(248,113,113,.12)); }

/* Sprint 55 hotfix UI debug — sections dropdown user (ESPACES + PARAMÈTRES) */
.pz-dropdown-section-label {
    padding: 8px 10px 4px;
    font-size: .68rem; font-weight: 700;
    color: var(--pz-text-muted);
    text-transform: uppercase; letter-spacing: .06em;
    border-top: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 8%, transparent));
    margin-top: 4px;
}
.pz-dropdown-section-label:first-of-type {
    border-top: 0; margin-top: 0;
}
.pz-dropdown-theme-row {
    display: flex; gap: 4px; padding: 4px 8px;
}
.pz-dropdown-theme-btn {
    flex: 1; padding: 6px 4px; font-size: .72rem;
    background: transparent; color: var(--pz-text-secondary);
    border: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 12%, transparent));
    border-radius: var(--pz-radius-sm, 4px); cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; gap: 3px;
}
.pz-dropdown-theme-btn:hover {
    background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 8%, transparent));
}
.pz-dropdown-theme-btn.is-active {
    background: var(--pz-accent-soft, rgba(59,130,246,.15));
    color: var(--pz-accent, #60a5fa);
    border-color: var(--pz-accent, #60a5fa);
}

/* Modal Mayday — utilise <dialog> natif. Sprint 38 : centrage explicite
   (inset+margin:auto) pour rester centré même quand le navigateur passe
   par le fallback setAttribute('open') au lieu de showModal(). */
.pz-modal {
    position: fixed; inset: 0; margin: auto;
    border: 0; padding: 0; border-radius: var(--pz-radius-lg, 12px);
    background: var(--pz-surface); color: var(--pz-text);
    max-width: 540px; width: 90vw; max-height: 90vh; height: fit-content;
    box-shadow: 0 24px 60px rgba(0,0,0,.4);
}
/* S180 Phase 1 T5 — pointe token --pz-bg-overlay (canon DS unifié Léa A87). */
.pz-modal::backdrop { background: var(--pz-bg-overlay); }
/* Bouton Annuler (Sprint 38 — fix bouton blanc sur fond sombre) */
.pz-modal-footer .btn-sm:not(.btn-primary):not(.btn-danger) {
    background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 6%, transparent));
    color: var(--pz-text);
    border: 1px solid var(--pz-border);
}
.pz-modal-footer .btn-sm:not(.btn-primary):not(.btn-danger):hover {
    background: var(--pz-surface);
    border-color: var(--pz-text-muted);
}
.pz-modal-content { display: flex; flex-direction: column; }
.pz-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px; border-bottom: 1px solid var(--pz-border);
}
.pz-modal-title { margin: 0; font-size: 1.05rem; display: inline-flex; align-items: center; gap: 8px; color: var(--pz-danger, #dc2626); }
.pz-modal-close { background: none; border: 0; color: var(--pz-text-muted); cursor: pointer; font-size: 1.5rem; line-height: 1; padding: 0 4px; }
.pz-modal-close:hover { color: var(--pz-text); }
.pz-modal-body { padding: 16px 20px; display: flex; flex-direction: column; gap: 12px; }
.pz-modal-hint { margin: 0; font-size: .85rem; color: var(--pz-text-muted); }
.pz-modal-label { display: flex; flex-direction: column; gap: 4px; font-size: .85rem; font-weight: 500; }
.pz-modal-input, .pz-modal-textarea {
    background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 5%, transparent));
    border: 1px solid var(--pz-border);
    color: var(--pz-text); border-radius: var(--pz-radius-card, 6px);
    padding: 8px 10px; font-size: .9rem; font-family: inherit;
}
.pz-modal-input:focus, .pz-modal-textarea:focus {
    outline: 2px solid var(--pz-accent, #60a5fa); outline-offset: 1px; border-color: transparent;
}
.pz-modal-meta { font-size: .75rem; color: var(--pz-text-muted); padding: 6px 10px; background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 4%, transparent)); border-radius: var(--pz-radius-card, 6px); }
.pz-modal-meta code { color: var(--pz-text); font-family: ui-monospace, monospace; }
.pz-modal-footer { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 20px; border-top: 1px solid var(--pz-border); }

/* ════════════════════════════════════════════════════════════════════
 * Sprint 33 V2 / Sprint 54 — Sidebar simplifiée (BRD UI v1 §3.6 revisitée)
 * Zone unique : modules métier avec split label/badge.
 * (Sprint 54 hotfix : retrait zone ① "À traiter" — redondant avec badges
 *  per-section + cloche topbar / et zone ③ "Master data" — Paramètres
 *  accessible via dropdown avatar topbar.)
 * ════════════════════════════════════════════════════════════════════ */

.pz-nav-row {
    display: flex; align-items: stretch;
    /* S122 V_A.1 retour Arnaud #22 — gap réduit 2→0 (« concentre le menu »).
       border-radius 0 canon « pas de coins arrondis ». */
    margin: 0 8px 0 0; border-radius: 0;
    transition: background .15s;
}
.pz-nav-row:hover { background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 5%, transparent)); }
/* S178 retour Arnaud répété — surligne sidebar item actif TOUJOURS pas visible. Cause :
   - Bg = `--pz-accent-soft` fallback rgba bleu hardcodé (pas connecté picker user).
   - Texte = `--pz-text-on-primary` !important (texte SUR fond primary brand,
     quasi-invisible cas vert olive Sidney sur fond bleu hardcodé).
   Fix canon :
   - Bg = color-mix --pz-primary 18% transparent (picker-réactif, distingué du hover 5%).
   - Border-left = 4px solid --pz-primary (signal visuel canon S70).
   - Texte = --pz-text-primary !important (canon « Texte principal » picker user mig 171,
     même règle que .sidebar-nav > a.active fix S178 round 5).
   - font-weight 700 (vs 500 avant) — éclat de l'actif. */
.pz-nav-row.is-active {
    background: color-mix(in srgb, var(--pz-primary, #0ea5e9) 18%, transparent);
    border-left: 4px solid var(--pz-primary, #0ea5e9);
}
.pz-nav-row.is-active .pz-nav-label {
    color: var(--pz-text-primary) !important;
    font-weight: 700;
}
/* Spécificité bumped (.pz-nav-row .pz-nav-label = 0,2,0) pour battre
 * .sidebar-nav a (0,1,1) qui imposait padding: 12px 24px legacy. */
.pz-nav-row a.pz-nav-label,
.sidebar-nav a.pz-nav-label {
    flex: 1 1 auto; display: flex; align-items: center; gap: 8px;
    /* S122 V_A.1 retour Arnaud #22+#23 — padding 6/10/6/30 → 4/7/4/30 (-30% horiz
       espace canon « réduis les espaces avec les ronds de 30% »). */
    padding: 4px 7px 4px 30px; border-radius: 0;
    /* S70 V_A.6 — sidebar nav label = --pz-secondary-text (couplé fond shell). */
    color: var(--pz-secondary-text); text-decoration: none; font-size: .88rem;
    min-width: 0;
}
.pz-nav-label .nav-icon {
    flex: 0 0 16px;
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05em;
    line-height: 1;
}
/* Sprint 54 — badge sidebar resserré (Arnaud diagnostic via inspector :
 * .sidebar-nav a { padding: 12px 24px } écrasait notre padding via specificity
 * (0,1,1) > (0,1,0) du badge). Fix : scope sur .pz-nav-row pour gagner
 * specificity (0,2,1) > (0,1,1) + safety !important sur padding. */
.pz-nav-row a.pz-nav-badge,
.sidebar-nav a.pz-nav-badge {
    flex: 0 0 auto; align-self: center;
    margin-right: 8px;
    background: var(--pz-danger, #dc2626); color: white;
    border-radius: var(--pz-radius-lg, 12px); font-size: .78rem; font-weight: 700;
    text-decoration: none;
    min-width: 18px; height: 22px;
    padding: 0 2px !important;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background .15s;
    gap: 0;
}
.pz-nav-badge:hover { background: var(--pz-urgent-active, #b91c1c); }

.pz-nav-leaf .pz-nav-label { padding-left: 24px; font-size: .82rem; }

/* Responsive — masquer éléments non essentiels en mobile */
@media (max-width: 768px) {
    .pz-only-desktop { display: none !important; }
    .pz-topbar { gap: 8px; padding: 6px 12px; }
    .pz-topbar-scope { font-size: .8rem; }
    .pz-topbar-action { padding: 6px 8px; }
    .pz-modal { width: 95vw; }

    /* S197 audit mobile Léa P0#1 — picker résidence OPÉRABLE au téléphone (le scope se
       choisit en topbar, canon S195bis). Le <details> n'est plus pz-only-desktop ; le
       panel passe en fixed pleine largeur (les !important battent les min/max-width
       inline 320/380px du markup — même levier que le mode cards data_table). */
    .pz-topbar-complex-picker .pz-picker-current {
        max-width: 96px; overflow: hidden; text-overflow: ellipsis;
    }
    .pz-topbar-complex-picker .pz-picker-panel {
        position: fixed !important;
        top: 56px !important;
        left: 8px !important; right: 8px !important;
        min-width: 0 !important; max-width: none !important; width: auto !important;
    }
}

/* Sprint 36 — accueil multi-rôle : sélecteur d'espace en grand
   Sprint 55 hotfix UI debug : margin top 32 → 16 (réduit espace title↔subtitle de 50%) */
.accueil-subtitle-multi {
    font-size: 1.1rem; text-align: center; color: var(--pz-text-muted);
    margin: 16px 0 20px;
}
.accueil-grid-multi {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px; max-width: 980px; margin: 0 auto 40px;
}
.accueil-grid-multi .accueil-card {
    padding: 28px 22px; min-height: 200px;
    transition: transform .15s ease-out, box-shadow .15s ease-out;
}
.accueil-grid-multi .accueil-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 24px rgba(0,0,0,.18);
}
/* Sprint 38 — mono-rôle : tuile unique centrée (Sidney = 1 carte Syndic) */
.accueil-grid-single {
    grid-template-columns: minmax(280px, 360px);
    justify-content: center;
    max-width: 360px;
}

/* Sprint 38 — dropdown rich items (menu "+ Nouveau" topbar) */
.pz-dropdown-item-rich {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 8px 10px; min-width: 240px;
}
.pz-dropdown-item-rich .pz-dropdown-ico {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: var(--pz-radius-card, 6px);
    background: var(--pz-accent-soft, rgba(59,130,246,.15));
    color: var(--pz-accent, #60a5fa);
}
.pz-dropdown-item-rich .pz-dropdown-text {
    display: flex; flex-direction: column; gap: 1px; line-height: 1.2;
}
.pz-dropdown-item-rich .pz-dropdown-text strong {
    font-size: .85rem; color: var(--pz-text); font-weight: 600;
}
.pz-dropdown-item-rich .pz-dropdown-text small {
    font-size: .72rem; color: var(--pz-text-muted);
}

/* ════════════════════════════════════════════════════════════════════
 * Sprint 33 V3 — Bottombar mobile + Footer desktop (BRD UI v1 §3.6)
 * ════════════════════════════════════════════════════════════════════ */

.pz-only-mobile { display: none; }
@media (max-width: 768px) {
    .pz-only-mobile { display: flex; }
}

/* Sprint 62 hotfix v3 → S197 — Bottombar desktop ET mobile.
   S197 décision Arnaud (reco Léa audit mobile S196ter) : la bottombar n'est PLUS masquée
   ≤768px — elle porte le seul trigger Mayday + Messagerie + Annuaire. Au téléphone elle
   gagne le burger Modules (.pz-bb-burger, remplace le FAB bleu) et « + Nouveau »
   (.pz-bb-new, remplace le FAB orange). */
.pz-bottombar {
    display: flex;
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 100;
    justify-content: space-around; align-items: stretch;
    /* Sprint 65 R3 : bottombar consomme --pz-secondary (shell user-customisable). */
    background: var(--pz-secondary, rgba(0, 0, 0, 0.85));
    color: var(--pz-secondary-text);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-top: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-secondary-text) 8%, transparent));
    /* Sprint 97 V_A bis 4 — bottombar 52px (alignée topbar) demandée Arnaud. */
    padding: 0 12px env(safe-area-inset-bottom, 0);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.25);
    pointer-events: auto;
    height: 52px;
}
/* S209 (retour Arnaud, demande répétée) — le burger « Modules » n'ouvre que la sidebar off-canvas
   (≤900px). Sur desktop la sidebar est toujours visible → le burger n'a aucun intérêt sur PC, on le
   masque. (L'intention « masqué desktop » du commentaire de bottombar.php n'avait jamais de règle CSS.) */
@media (min-width: 901px) { .pz-bb-burger { display: none !important; } }
/* S197 décision Arnaud (reco Léa audit mobile S196ter) — la bottombar VIT au téléphone :
   elle porte le SEUL trigger Mayday + Messagerie + Annuaire. Les 2 FABs flottants 64px
   (sidebar-toggle bleu + Nouveau orange) sont SUPPRIMÉS : le burger Modules et le menu
   « + Nouveau » entrent DANS la bottombar. Items compactés, labels ellipsés. */
@media (max-width: 768px) {
    .pz-bottombar { padding: 0 4px env(safe-area-inset-bottom, 0); }
    .pz-bottombar .pz-bb-item { min-width: 0; padding: 4px 2px; }
    .pz-bottombar .pz-bb-label {
        max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
        font-size: .56rem;
    }
}
@media (max-width: 480px) {
    /* très petits écrans — le lien externe « Mon Website » (le moins critique mobile) cède la place */
    .pz-bb-website { display: none; }
}

/* S197 — burger Modules dans la bottombar (remplace le FAB bleu) : visible tant que la
   sidebar est off-canvas (≤900px, cf. .portal-sidebar transform), masqué desktop. */
.pz-bb-burger { display: none; }
@media (max-width: 900px) {
    .pz-bb-burger { display: inline-flex; }
}

/* S197 — « + Nouveau » dans la bottombar (remplace le FAB orange) : <details> natif,
   panel ouvrant vers le HAUT. Mobile only (desktop = dropdown « + Nouveau » topbar). */
.pz-bb-new { display: none; position: relative; }
@media (max-width: 768px) {
    .pz-bb-new { display: flex; flex: 1 1 0; }
}
.pz-bb-new > summary { list-style: none; width: 100%; }
.pz-bb-new > summary::-webkit-details-marker { display: none; }
.pz-bb-new > summary::marker { content: none; }
.pz-bb-new[open] > summary .pz-bb-label { color: var(--pz-primary, #0ea5e9); }
.pz-bb-newmenu-panel {
    position: absolute; bottom: calc(100% + 10px); right: 0;
    min-width: 240px; max-width: calc(100vw - 16px);
    background: var(--pz-bg-raised);
    border: 1px solid var(--pz-border);
    border-radius: var(--pz-radius-lg, 12px);
    box-shadow: 0 -8px 24px rgba(0,0,0,.5);
    padding: 6px;
    display: flex; flex-direction: column; gap: 2px;
    z-index: 201;
}
.pz-bb-newmenu-item {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; border-radius: var(--pz-radius-card, 6px);
    color: var(--pz-text-primary, #f1f5f9); text-decoration: none; font-size: .85rem;
}
.pz-bb-newmenu-item:hover { background: var(--pz-accent-soft, rgba(59,130,246,.15)); }
/* Override mode clair — Sprint 65 R3 hotfix : background neutralisé, var(--pz-secondary) gagne.
   border + shadow conservés (cohérence visuelle, pas customisable user). */
body.light-mode .pz-bottombar {
    border-top-color: var(--pz-border, #e2e8f0);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.06);
}
.pz-bb-item {
    flex: 1 1 0; display: inline-flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 1px;
    padding: 4px 4px; background: none; border: 0;
    /* S70 V_A.2 — bottombar item consomme --pz-secondary-text (couplé fond shell). */
    color: color-mix(in srgb, var(--pz-secondary-text) 70%, transparent);
    text-decoration: none;
    /* Sprint 97 V_A bis 4 — height aligné bottombar 52px (au lieu de 52 min-height qui débordait). */
    cursor: pointer; font-size: .6rem; height: 52px; position: relative;
}
.pz-bb-item:hover, .pz-bb-item.is-active {
    color: var(--pz-primary, #0ea5e9);
}
/* S177 — logo SDBM externe (bitmap, pas SVG inline) : aligné sur la couleur des autres
   icônes bottombar (--pz-secondary-text). filter:invert(1) bascule blanc/noir selon mode
   pour qu'il reste lisible sur le shell (sombre ou clair). */
.pz-bb-sdbm-logo { filter: brightness(0) invert(1); }
body.light-mode .pz-bb-sdbm-logo { filter: brightness(0); }
.pz-bb-item-primary {
    color: var(--pz-accent, #60a5fa);
}
/* S124 V_A.6.9 retour Arnaud final — Mayday SVG inline custom (cercle rempli + "!" même viewBox).
   « le cercle blanc et le fond rouge sont mal alignés » → solution = SVG inline avec circle fill +
   path stroke partageant viewBox 0 0 24 24 = alignment parfait garanti par construction.
   Plus de wrapper background needed, le SVG porte tout. */
.pz-bb-mayday {
    background: none;
    border: 0;
    color: color-mix(in srgb, var(--pz-secondary-text) 70%, transparent);
    box-shadow: none;
}
.pz-bb-mayday-svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    transition: filter .15s, transform .15s;
}
.pz-bb-mayday:hover .pz-bb-mayday-svg {
    filter: brightness(0.92);
    transform: scale(1.05);
}
.pz-bb-mayday:active .pz-bb-mayday-svg {
    transform: scale(0.98);
}
/* S184 retour Arnaud — le label « Mayday » doit être identique aux autres labels bottombar
   (même graisse ET même couleur, pas gris). On NE touche PAS à l'icône Mayday ni à sa couleur. */
.pz-bb-mayday .pz-bb-label {
    margin-top: 2px;
    color: color-mix(in srgb, var(--pz-secondary-text) 70%, transparent);
}
.pz-bb-label { font-weight: 500; line-height: 1; }
/* S184 — logos société (annuaire) : version sombre sur fond sombre, version claire sur fond clair. */
.pz-dir-logo-light { display: none; }
body.light-mode .pz-dir-logo-light { display: block; }
body.light-mode .pz-dir-logo-dark  { display: none; }
.pz-bb-badge {
    /* S228 (retour Arnaud « le badge messagerie est complètement déconnecté de l'icône, il
       devrait être en overlay ») — l'item bottombar est une colonne flex (icône 22px CENTRÉE +
       label dessous). `right:25%` calculait depuis le bord droit de l'item LARGE → la pastille
       flottait loin de l'icône. On la cale sur le coin haut-DROIT de l'icône centrée : son bord
       droit est à calc(50% + 11px), on place la pastille à cheval dessus. */
    position: absolute; top: 3px; left: calc(50% + 3px); right: auto;
    min-width: 16px; height: 16px; padding: 0 4px;
    background: var(--pz-danger, #dc2626); color: white;
    border: 1.5px solid var(--pz-shell-bg, #0f172a);
    border-radius: 999px; font-size: .6rem; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center; line-height: 1;
    box-shadow: 0 1px 3px rgba(0,0,0,.4);
}

/* Sidebar mobile-overlay (toggle via pzBbModulesToggle) */
@media (max-width: 768px) {
    .portal-sidebar { transform: translateX(-100%); transition: transform .25s ease; }
    .portal-sidebar.is-open-mobile { transform: translateX(0); }
}

/* Footer desktop minimal */
.pz-footer {
    border-top: 1px solid var(--pz-border);
    background: var(--pz-surface);
    color: var(--pz-text-muted);
    font-size: .75rem;
    /* S211 C1 (retour Arnaud) — même hauteur que la topbar (.pz-topbar min-height:44px,
       padding 4px) : pied de page calé sur la barre du haut. Contenu centré verticalement. */
    padding: 4px 16px;
    min-height: 44px;
    display: flex;
    align-items: center;
    /* S210 (Q-FOOTER-STICKY) — pousse le footer en bas du body flex-column, sans compression. */
    margin-top: auto;
    flex-shrink: 0;
}
.pz-footer-inner {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    width: 100%;
}
/* S209 — footer 3 zones (retour Arnaud) : version+statut à GAUCHE, marque+logo+légal au CENTRE.
   Les zones gauche/droite ont le même flex → le centre est réellement centré. */
.pz-footer-left   { flex: 1 1 0; display: flex; align-items: center; gap: 8px; justify-content: flex-start; min-width: 0; }
.pz-footer-center { flex: 0 1 auto; display: flex; align-items: center; gap: 8px; justify-content: center; }
.pz-footer-right  { flex: 1 1 0; display: flex; align-items: center; gap: 8px; justify-content: flex-end; min-width: 0; }
.pz-footer-brand { color: var(--pz-text); font-weight: 500; }
.pz-footer-muted { color: var(--pz-text-muted); }
.pz-footer-sep { opacity: .4; }
.pz-footer-spacer { flex: 1 1 auto; }
.pz-footer-link {
    color: var(--pz-text-muted); text-decoration: none;
}
.pz-footer-link:hover { color: var(--pz-accent, #60a5fa); }
.pz-status-dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    margin-right: 4px;
}
.pz-status-dot-ok { background: var(--pz-success, #10b981); }
.pz-status-dot-warn { background: var(--pz-warning, #f59e0b); }
.pz-status-dot-err { background: var(--pz-danger, #dc2626); }

/* ════════════════════════════════════════════════════════════════════
 * Sprint 33 V4 — Accueil 4 zones hybrides (BRD UI v1 §3.7)
 * Pile (rouge) / Recommandations (bleu) / Warnings (jaune) / KPI
 * ════════════════════════════════════════════════════════════════════ */

.pz-acc-zone {
    margin: 16px auto; max-width: 960px;
    /* S70 V_A.3 — fond card = thème syndic (Q2=c branding total) ;
       texte primaire = --pz-text-primary (couplé fond shell). */
    background: var(--pz-bg-raised);
    color: var(--pz-text-primary);
    border: 1px solid color-mix(in srgb, var(--pz-text-primary) 12%, transparent);
    border-radius: var(--pz-radius-card-lg, 10px);
    padding: 14px 18px;
}
.pz-acc-zone-header {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 10px;
}
.pz-acc-zone-header h2 {
    margin: 0; font-size: 1rem; font-weight: 600;
    display: inline-flex; align-items: center; gap: 8px;
    color: var(--pz-text-primary);
}
.pz-acc-zone-link {
    color: color-mix(in srgb, var(--pz-text-primary) 65%, transparent);
    text-decoration: none; font-size: .8rem;
}
.pz-acc-zone-link:hover { color: var(--pz-text-primary); }

/* S70 V_A.3 — border-left + h2 colorés = SÉMANTIQUE canonique fixe Petzerhiel
   (rouge urgent / bleu info / jaune warning / vert succès). Ne bascule pas
   avec thème user (cf contrat Q3=b). */
.pz-acc-zone-pile { border-left: 4px solid var(--pz-urgent, #dc2626); }
.pz-acc-zone-pile h2 { color: var(--pz-urgent, #dc2626); }
.pz-acc-zone-reco { border-left: 4px solid var(--pz-info, #2563eb); }
.pz-acc-zone-reco h2 { color: var(--pz-info, #2563eb); }
.pz-acc-zone-warn { border-left: 4px solid var(--pz-warning, #f59e0b); }
.pz-acc-zone-warn h2 { color: var(--pz-warning, #f59e0b); }
.pz-acc-zone-kpi  { border-left: 4px solid var(--pz-success, #10b981); }
.pz-acc-zone-kpi h2  { color: var(--pz-success, #10b981); }

.pz-acc-grid-2 {
    display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
    margin: 0 auto; max-width: 960px;
}
.pz-acc-grid-2 .pz-acc-zone { margin: 0; }
@media (max-width: 768px) {
    .pz-acc-grid-2 { grid-template-columns: 1fr; }
}

.pz-acc-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.pz-acc-item {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 10px; border-radius: var(--pz-radius-card, 6px);
    /* S70 V_A.3 — overlay subtle sur fond card thème syndic. */
    background: color-mix(in srgb, var(--pz-text-primary) 5%, transparent);
}
.pz-acc-item:hover {
    background: color-mix(in srgb, var(--pz-text-primary) 10%, transparent);
}
.pz-acc-sev {
    flex: 0 0 auto; padding: 2px 6px; border-radius: var(--pz-radius-sm, 4px);
    font-size: .65rem; font-weight: 700; text-transform: uppercase;
    background: var(--pz-urgent, #dc2626); color: white;
}
.pz-acc-item-critical .pz-acc-sev { background: var(--pz-urgent, #dc2626); }
.pz-acc-item-high     .pz-acc-sev { background: var(--pz-warning-hover, #f97316); }
.pz-acc-item-medium   .pz-acc-sev { background: var(--pz-warning, #f59e0b); }
.pz-acc-item-info     .pz-acc-sev { background: var(--pz-info, #2563eb); }
.pz-acc-item-body {
    flex: 1 1 auto; display: flex; flex-direction: column;
    color: var(--pz-text-primary); text-decoration: none;
}
.pz-acc-item-body strong { font-size: .9rem; font-weight: 500; line-height: 1.3; }
.pz-acc-item-body small {
    color: color-mix(in srgb, var(--pz-text-primary) 60%, transparent);
    font-size: .75rem; margin-top: 2px;
}

.pz-acc-empty {
    padding: 14px; border-radius: var(--pz-radius-card, 6px); font-size: .85rem;
    color: color-mix(in srgb, var(--pz-secondary-text) 65%, transparent);
    background: color-mix(in srgb, var(--pz-secondary-text) 5%, transparent);
    text-align: center;
}
.pz-acc-empty-ok {
    background: var(--pz-success-soft, rgba(34,197,94,.1));
    color: var(--pz-success, #10b981);
    display: flex; align-items: center; justify-content: center; gap: 8px;
}

.pz-acc-kpis {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
}
@media (max-width: 600px) { .pz-acc-kpis { grid-template-columns: repeat(2, 1fr); } }

/* S198 mobile P1 (audit Léa S196) — grille 4 colonnes générique qui CÈDE sur mobile.
   Remplace les inline grid-template-columns:repeat(4,1fr) imbattables par media query
   (accounting_residence:174/518/1609 — pattern .pz-acc-kpis généralisé). */
.pz-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
@media (max-width: 720px) { .pz-grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .pz-grid-4 { grid-template-columns: 1fr; } }
.pz-acc-kpi {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: 14px 8px; border-radius: var(--pz-radius-md, 8px);
    background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 5%, transparent));
    color: var(--pz-text); text-decoration: none;
    transition: transform .15s, background .15s;
}
.pz-acc-kpi:hover { transform: translateY(-2px); background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 10%, transparent)); }
.pz-acc-kpi-value { font-size: 1.6rem; font-weight: 700; line-height: 1.1; }
.pz-acc-kpi-label { font-size: .75rem; color: var(--pz-text-muted); margin-top: 4px; text-align: center; }
.pz-acc-kpi.is-warn .pz-acc-kpi-value { color: var(--pz-warning, #f59e0b); }
.pz-acc-kpi.is-active .pz-acc-kpi-value { color: var(--pz-accent, #60a5fa); }

/* ─────────────────────────────────────────────────────────────────────
 * Sprint 58 V_E (Bloc 10 BRD UI v1 §4.10) — Skeleton loaders unifiés.
 * Usage : <tr class="pz-skeleton-row"><td colspan="N"></td></tr>
 *         <div class="pz-skeleton-card"></div>
 *         <div class="pz-skeleton-line is-medium"></div>
 * Supprime le saut visuel pendant le chargement async (tables AJAX, listes).
 * ───────────────────────────────────────────────────────────────────── */
@keyframes pz-skeleton-shimmer {
    0%   { background-position: -200px 0; }
    100% { background-position: calc(200px + 100%) 0; }
}
.pz-skeleton-row td,
.pz-skeleton-card,
.pz-skeleton-line {
    background: linear-gradient(90deg, rgba(148,163,184,0.08) 0%, rgba(148,163,184,0.18) 50%, rgba(148,163,184,0.08) 100%);
    background-size: 200px 100%;
    background-repeat: no-repeat;
    animation: pz-skeleton-shimmer 1.4s ease-in-out infinite;
    border-radius: var(--pz-radius-sm, 4px);
}
.pz-skeleton-row td { height: 36px; padding: 0; border: 0 !important; }
.pz-skeleton-card { height: 96px; margin-bottom: 8px; }
.pz-skeleton-line { height: 12px; margin: 6px 0; }
.pz-skeleton-line.is-short  { width: 40%; }
.pz-skeleton-line.is-medium { width: 65%; }
.pz-skeleton-line.is-long   { width: 90%; }

/* ════════════════════════════════════════════════════════════════════════
 * Sprint 64 NIGHTWATCH addendum V_8.E — Classes utilitaires standard
 * pour réduire progressivement les `style=""` inline (audit recensé 1586
 * attrs dont ~430 avec couleurs hardcoded sur top 5 sections).
 *
 * Usage : remplacer `style="background:#dc2626;color:#fff"` par
 *         `class="pz-bg-danger"` (texte blanc sur rouge auto via token).
 *
 * Bascule mode clair/sombre auto via tokens.css. Migration progressive
 * S65+ : sed batch ciblé par pattern (cf docs/sprints/sprint-64-addendum-
 * ui-cleanup.md §V_8.E pour les 10 patterns prioritaires).
 * ══════════════════════════════════════════════════════════════════════ */

/* Backgrounds sémantiques — fond coloré + texte blanc lisible */
.pz-bg-danger  { background: var(--pz-danger, #dc2626); color: var(--pz-text-on-primary, #fff); }
.pz-bg-warning { background: var(--pz-warning, #f59e0b); color: var(--pz-text-on-primary, #fff); }
.pz-bg-success { background: var(--pz-success, #10b981); color: var(--pz-text-on-primary, #fff); }
.pz-bg-info    { background: var(--pz-info, #2563eb); color: var(--pz-text-on-primary, #fff); }
.pz-bg-primary { background: var(--pz-primary, #0ea5e9); color: var(--pz-text-on-primary, #fff); }
.pz-bg-neutral { background: var(--pz-text-muted); color: var(--pz-text-on-primary, #fff); }

/* Texte sémantique — bascule auto mode clair */
.pz-text-danger    { color: var(--pz-danger, #dc2626); }
.pz-text-warning   { color: var(--pz-warning, #f59e0b); }
.pz-text-success   { color: var(--pz-success, #10b981); }
.pz-text-info      { color: var(--pz-info, #2563eb); }
.pz-text-primary-c { color: var(--pz-primary, #0ea5e9); }
.pz-text-muted-c   { color: var(--pz-text-muted); }

/* Pills/badges utilitaires — pattern fréquent style=display:inline-block;padding:3px 10px;border-radius:var(--pz-radius-lg, 12px) */
.pz-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: var(--pz-radius-lg, 12px);
    font-size: .7rem;
    font-weight: 700;
    line-height: 1.4;
}
.pz-pill-sm { padding: 2px 7px; font-size: .65rem; }

/* Boutons d'action mini (pattern style=padding:3px 7px;font-size:.75rem) */
.pz-btn-action {
    padding: 3px 7px;
    font-size: .75rem;
    border-radius: var(--pz-radius-sm, 4px);
    border: none;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* Cellules table — alignement vertical standard */
.pz-cell-mono { font-family: monospace; font-size: .85em; }
.pz-cell-num  { text-align: right; font-variant-numeric: tabular-nums; }
.pz-cell-center { text-align: center; }

/* S91 DS Vague E (interview Léa Q24) — alias court pour usage inline.
   Tabular nums = colonnes Montant/Compteur où Sidney compare verticalement.
   Pattern Stripe/Revolut/N26 : alignement parfait des chiffres. */
.pz-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.pz-num, th.pz-num { text-align: right; font-variant-numeric: tabular-nums; }

/* ════════════════════════════════════════════════════════════════════════
 * Sprint 64 NIGHTWATCH addendum V_9.K — Sélecteur langue topbar
 * Drapeau actif visible direct + dropdown 6 options ISO (fr/en/de/lb/pt/it).
 * Réutilise pz-topbar-dropdown existant (S33 V1) + pz-topbar-dropdown-panel.
 * ══════════════════════════════════════════════════════════════════════ */

.pz-topbar-lang summary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
}
.pz-topbar-lang-flag {
    font-size: 1.1rem;
    line-height: 1;
}
.pz-topbar-lang-code {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--pz-text-shell-medium, rgba(255,255,255,.7));
}
.pz-topbar-lang-panel {
    min-width: 110px;
    padding: 4px;
}
.pz-topbar-lang-form { display: block; }
.pz-topbar-lang-opt {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 10px;
    background: transparent;
    border: none;
    color: var(--pz-text-primary);
    text-align: left;
    cursor: pointer;
    border-radius: var(--pz-radius-sm, 4px);
    font-size: .85rem;
    transition: background .15s;
}
.pz-topbar-lang-opt:hover { background: var(--pz-surface-elevated, color-mix(in srgb, var(--pz-text-primary) 6%, transparent)); }
.pz-topbar-lang-opt.is-active {
    background: var(--pz-primary-soft, rgba(2,132,199,.12));
    color: var(--pz-primary, #0284c7);
    font-weight: 600;
}
.pz-topbar-lang-opt .pz-topbar-lang-code { color: inherit; font-size: .75rem; }

/* Mode clair — texte lisible */
body.light-mode .pz-topbar-lang-code { color: rgba(15,23,42,.7); }
body.light-mode .pz-topbar-lang-opt { color: var(--pz-secondary-text); }
body.light-mode .pz-topbar-lang-opt:hover { background: color-mix(in srgb, var(--pz-text-primary) 4%, transparent); }
body.light-mode .pz-topbar-lang-opt.is-active { background: var(--pz-info-soft, #e0f2fe); color: var(--pz-primary, #0284c7); }

/* ════════════════════════════════════════════════════════════════════════
 * Sprint 66 R4 — Boutons Lego DB-driven (système design + ui_component_theme)
 *
 * 6 variantes : .btn-primary | .btn-secondary | .btn-danger | .btn-warning |
 *               .btn-success | .btn-outline
 *
 * Chaque classe consomme les vars `--pz-btn-{variant}-{key}` injectées par
 * lib/ui_themes.php::ui_themes_render_css() depuis ui_component_theme
 * (migration 067). Cascade fallback : template DB → tokens.css sémantique
 * → hex historique.
 *
 * Compatibilité : ces classes globales coexistent avec les classes inline
 * que certaines sections définissent localement (cf admin_ui_help.php,
 * admin_ui_themes.php). Cascade résolue par ordre des <style> (les sections
 * locales gagnent si plus tardives, les vars DB-driven priment via cascade
 * de variables CSS).
 * ════════════════════════════════════════════════════════════════════════ */

.btn,
.btn-primary, .btn-secondary, .btn-danger, .btn-warning, .btn-success, .btn-outline {
    display: inline-block;
    padding: 6px 14px;
    font-size: .9rem;
    font-weight: 500;
    line-height: 1.4;
    border-radius: var(--pz-radius-sm, 4px);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
    box-sizing: border-box;
    font-family: inherit;
}

/* Primary */
.btn-primary {
    background: var(--pz-btn-primary-bg, #0ea5e9);
    color: var(--pz-btn-primary-color, #ffffff);
    border-color: var(--pz-btn-primary-border, #0ea5e9);
}
.btn-primary:hover:not(:disabled) {
    background: var(--pz-btn-primary-hover-bg, #0284c7);
    color: var(--pz-btn-primary-hover-color, #ffffff);
    border-color: var(--pz-btn-primary-hover-border, #0284c7);
}
.btn-primary:active { background: var(--pz-btn-primary-active-bg, #0369a1); }
.btn-primary:disabled {
    background: var(--pz-btn-primary-disabled-bg);
    color: var(--pz-btn-primary-disabled-color);
    cursor: not-allowed;
}

/* Secondary */
.btn-secondary {
    background: var(--pz-btn-secondary-bg, transparent);
    color: var(--pz-btn-secondary-color);
    border-color: var(--pz-btn-secondary-border);
}
.btn-secondary:hover:not(:disabled) {
    background: var(--pz-btn-secondary-hover-bg, var(--pz-overlay-soft, color-mix(in srgb, var(--pz-text-primary) 4%, transparent)));
    color: var(--pz-btn-secondary-hover-color);
    border-color: var(--pz-btn-secondary-hover-border);
}
.btn-secondary:active { background: var(--pz-btn-secondary-active-bg, var(--pz-overlay-strong, color-mix(in srgb, var(--pz-text-primary) 8%, transparent))); }

/* Danger */
.btn-danger {
    background: var(--pz-btn-danger-bg, #dc2626);
    color: var(--pz-btn-danger-color, #ffffff);
    border-color: var(--pz-btn-danger-border, #dc2626);
}
.btn-danger:hover:not(:disabled) {
    background: var(--pz-btn-danger-hover-bg, #b91c1c);
    color: var(--pz-btn-danger-hover-color, #ffffff);
    border-color: var(--pz-btn-danger-hover-border, #b91c1c);
}
.btn-danger:active { background: var(--pz-btn-danger-active-bg, #991b1b); }

/* Warning */
.btn-warning {
    background: var(--pz-btn-warning-bg, #f59e0b);
    color: var(--pz-btn-warning-color);
    border-color: var(--pz-btn-warning-border, #f59e0b);
}
.btn-warning:hover:not(:disabled) {
    background: var(--pz-btn-warning-hover-bg, #d97706);
    color: var(--pz-btn-warning-hover-color);
    border-color: var(--pz-btn-warning-hover-border, #d97706);
}
.btn-warning:active { background: var(--pz-btn-warning-active-bg, #b45309); }

/* Success */
.btn-success {
    background: var(--pz-btn-success-bg, #10b981);
    color: var(--pz-btn-success-color, #ffffff);
    border-color: var(--pz-btn-success-border, #10b981);
}
.btn-success:hover:not(:disabled) {
    background: var(--pz-btn-success-hover-bg, #059669);
    color: var(--pz-btn-success-hover-color, #ffffff);
    border-color: var(--pz-btn-success-hover-border, #059669);
}
.btn-success:active { background: var(--pz-btn-success-active-bg, #047857); }

/* Outline */
.btn-outline {
    background: var(--pz-btn-outline-bg, transparent);
    color: var(--pz-btn-outline-color, #0ea5e9);
    border-color: var(--pz-btn-outline-border, #0ea5e9);
}
.btn-outline:hover:not(:disabled) {
    background: var(--pz-btn-outline-hover-bg, rgba(14, 165, 233, .1));
    color: var(--pz-btn-outline-hover-color, #0284c7);
    border-color: var(--pz-btn-outline-hover-border, #0284c7);
}
.btn-outline:active { background: var(--pz-btn-outline-active-bg, rgba(14, 165, 233, .2)); }

/* Tailles auxiliaires (réutilisable cross-variants) */
.btn-sm { padding: 4px 10px; font-size: .82rem; }
.btn-xs { padding: 2px 8px; font-size: .72rem; border-radius: var(--pz-radius-sm, 4px); }
.btn-lg { padding: 9px 18px; font-size: 1rem; }

/* ════════════════════════════════════════════════════════════════════════
 * Sprint 66 R7.4 — Halo "preview" pour le bouton « Voir sur portail »
 * dans admin_ui_themes.php. JS index.php lit ?pz_preview=<key> et applique
 * .pz-preview-halo sur les éléments matchant le sélecteur du composant
 * pendant 10s. Permet aux admins d'identifier visuellement l'élément
 * concerné par le template qu'ils éditent.
 * ════════════════════════════════════════════════════════════════════════ */
@keyframes pz-preview-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(14, 165, 233, .85), 0 0 0 0 rgba(14, 165, 233, .55); }
    50%  { box-shadow: 0 0 0 8px rgba(14, 165, 233, .25), 0 0 0 16px rgba(14, 165, 233, .08); }
    100% { box-shadow: 0 0 0 0 rgba(14, 165, 233, .85), 0 0 0 0 rgba(14, 165, 233, .55); }
}
.pz-preview-halo {
    animation: pz-preview-pulse 1.4s ease-in-out infinite;
    position: relative;
    z-index: 10;
    border-radius: var(--pz-radius-md, 8px);
    transition: outline-color .3s;
    outline: 2px solid rgba(14, 165, 233, .6);
    outline-offset: 4px;
}

/* ─── Sprint 82 audit S80 D5 — MFA TOTP UI (settings tab Sécurité) ─── */
.pz-totp-alert { padding: 12px; border-radius: var(--pz-radius-card, 6px); border: 1px solid; }
.pz-totp-alert--warn {
    background: var(--pz-warning-soft, #7c2d12);
    color: var(--pz-warning-soft, #fed7aa);
    border-color: var(--pz-warning, #f59e0b);
}
.pz-totp-alert--success {
    background: var(--pz-success-soft, #064e3b);
    color: var(--pz-success-soft, #bbf7d0);
    border-color: var(--pz-success, #10b981);
}
.pz-totp-disable-form { margin-top: 16px; }
.pz-totp-btn-danger {
    background: var(--pz-danger, #dc2626);
    color: var(--pz-text-on-primary, #fff);
    padding: 8px 14px;
    border: none;
    border-radius: var(--pz-radius-sm, 4px);
    cursor: pointer;
}
.pz-totp-enroll-card {
    background: var(--pz-bg-raised);
    border: 1px solid var(--pz-border);
    border-radius: var(--pz-radius-md, 8px);
    padding: 16px;
    max-width: 600px;
}
.pz-totp-enroll-title { margin-top: 0; }
.pz-totp-enroll-steps { line-height: 1.8; }
.pz-totp-secret-code {
    background: var(--pz-bg-base);
    padding: 4px 8px;
    border-radius: var(--pz-radius-sm, 4px);
    font-family: ui-monospace, monospace;
    letter-spacing: .1em;
    font-size: .95em;
}
.pz-totp-link { color: var(--pz-info, #60a5fa); }
.pz-totp-confirm-form { margin-top: 16px; }
.pz-totp-code-label { display: block; margin-bottom: 8px; font-weight: 600; }
.pz-totp-code-input {
    font-size: 1.4em;
    letter-spacing: .3em;
    padding: 8px 12px;
    width: 200px;
    text-align: center;
    border: 1px solid var(--pz-border);
    background: var(--pz-bg-input);
    color: var(--pz-text-primary);
    border-radius: var(--pz-radius-card, 6px);
}
.pz-totp-confirm-actions { margin-top: 14px; display: flex; gap: 10px; }
.pz-totp-btn-cancel {
    padding: 8px 14px;
    background: var(--pz-bg-elevated);
    color: var(--pz-text-primary, #fff);
    border: none;
    border-radius: var(--pz-radius-sm, 4px);
    cursor: pointer;
}
.pz-totp-enable-btn { padding: 10px 16px; }
.pz-totp-help-note { margin-top: 12px; font-size: .9em; }

/* Sprint 86 hotfix⁴ — QR code box dans enrollment TOTP */
.pz-totp-qr-box {
    margin: 16px 0;
    padding: 16px;
    background: var(--pz-bg-base, #fff);
    border-radius: var(--pz-radius-md, 8px);
    text-align: center;
}
.pz-totp-qr-title {
    margin: 0 0 12px;
    color: var(--pz-text-primary);
    font-size: 1rem;
}
.pz-totp-qr-frame {
    display: inline-block;
    padding: 12px;
    background: var(--pz-bg-base, #fff);
    border: 1px solid var(--pz-border, #e2e8f0);
    border-radius: var(--pz-radius-sm, 4px);
}
.pz-totp-qr-frame svg { display: block; max-width: 220px; height: auto; }
.pz-totp-qr-hint {
    margin: 12px 0 0;
    font-size: .85em;
    color: var(--pz-text-muted);
}
.pz-totp-manual-entry {
    margin: 12px 0;
    padding: 8px 12px;
    background: var(--pz-bg-base);
    border-radius: var(--pz-radius-card, 6px);
}
.pz-totp-manual-entry summary {
    cursor: pointer;
    font-weight: 600;
    padding: 4px 0;
}
.pz-totp-mobile-link-hint {
    margin: 8px 0;
    font-size: .9em;
    color: var(--pz-text-muted);
}

/* ─── Sprint 87 α.2 — readability inputs disabled / readonly ─────────────────
   Bug observé S86 : champs Mon compte / Organisation rendus en placeholder
   italique gris (email + phone disabled). Fix : forcer la value visible
   en couleur normale + curseur not-allowed pour signaler non-éditable. */
input[disabled],
input[readonly],
select[disabled],
textarea[disabled],
textarea[readonly] {
    color: var(--pz-text, #e2e8f0) !important;
    -webkit-text-fill-color: var(--pz-text, #e2e8f0);
    opacity: 0.85;
    cursor: not-allowed;
    font-style: normal;
    background: var(--pz-input-disabled-bg, color-mix(in srgb, var(--pz-text-primary) 7%, transparent));
}
body.light-mode input[disabled],
body.light-mode input[readonly],
body.light-mode select[disabled],
body.light-mode textarea[disabled],
body.light-mode textarea[readonly] {
    color: var(--pz-text) !important;
    -webkit-text-fill-color: var(--pz-text);
    background: var(--pz-input-disabled-bg, color-mix(in srgb, var(--pz-text-primary) 4%, transparent));
}

/* ────────────────────────────────────────────────────────────────────────
 * pz-calendar-month — Sprint 111 V_B BUTTERFLY Phase 1 cycle 2 F12+F19.
 * Helper canon lib/calendar_view.php générateur vue calendrier mensuel.
 * Tokens cohérents canon strict 6/6 (border-radius canon 0/6, no hex inline).
 * ──────────────────────────────────────────────────────────────────────── */
.pz-calendar-month {
    background: var(--pz-bg-elev-1);
    border: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 8%, transparent));
    border-radius: var(--pz-radius-card, 6px);
    padding: 16px;
    margin: 12px 0;
}
.pz-calendar-header {
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.pz-calendar-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: var(--pz-text, #e2e8f0);
}
.pz-calendar-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-size: 0.875rem;
}
.pz-calendar-table .pz-calendar-dow {
    padding: 6px 4px;
    text-align: center;
    color: var(--pz-text-muted);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 8%, transparent));
}
.pz-calendar-cell {
    /* S167 BUG-03 — hauteur compacte (80→58px) pour faire tenir 6 semaines à l'écran (démo).
       Fond rattaché au color picker Sidney (--pz-secondary) au lieu du navy figé --pz-bg-elev-0. */
    height: 58px;
    vertical-align: top;
    padding: 4px;
    border: 1px solid var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 6%, transparent));
    background: color-mix(in srgb, var(--pz-secondary, #1a2744) 50%, transparent);
    overflow: hidden;
    position: relative;
}
.pz-calendar-cell.is-empty {
    background: transparent;
    border-color: transparent;
}
.pz-calendar-cell.is-today {
    /* Jour courant = teinte de la couleur de marque (picker), pas le bleu figé. */
    background: color-mix(in srgb, var(--pz-primary, #2563eb) 18%, transparent);
    border-color: var(--pz-primary, #2563eb);
}
.pz-calendar-cell.has-events {
    cursor: pointer;
}
.pz-calendar-day-num {
    font-weight: 600;
    color: var(--pz-text-muted);
    margin-bottom: 4px;
    font-size: 0.875rem;
}
.pz-calendar-cell.is-today .pz-calendar-day-num {
    color: var(--pz-accent, #2563eb);
}
.pz-calendar-event {
    display: block;
    padding: 2px 6px;
    margin-bottom: 2px;
    border-radius: var(--pz-radius-sm, 4px);
    font-size: 0.75rem;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-decoration: none;
}
.pz-calendar-event.is-info     { background: var(--pz-info-bg, rgba(56,189,248,0.16));  color: var(--pz-info-fg, #38bdf8); }
.pz-calendar-event.is-warn     { background: var(--pz-warn-bg, rgba(245,158,11,0.16));  color: var(--pz-warn-fg, #f59e0b); }
.pz-calendar-event.is-pile     { background: var(--pz-pile-bg, rgba(239,68,68,0.16));   color: var(--pz-pile-fg, #ef4444); }
.pz-calendar-event.is-ok       { background: var(--pz-ok-bg, rgba(34,197,94,0.16));     color: var(--pz-ok-fg, #22c55e); }
.pz-calendar-event-badge {
    font-size: 0.875em;
}
.pz-calendar-event-more {
    font-size: 0.7rem;
    color: var(--pz-text-muted);
    font-style: italic;
    margin-top: 2px;
}

/* light mode tokens override */
body.light-mode .pz-calendar-month {
    background: var(--pz-bg-elev-1, #ffffff);
    border-color: var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 8%, transparent));
}
body.light-mode .pz-calendar-cell {
    background: var(--pz-bg-elev-0, #f8fafc);
    border-color: var(--pz-border, color-mix(in srgb, var(--pz-text-primary) 6%, transparent));
}

/* F11 bell digest phase indicator (S111 V_B) */
.pz-topbar-bell.is-phase-digest .pz-bell-badge {
    background: var(--pz-accent, #2563eb);
    color: var(--pz-text-on-primary, #ffffff);
}

/* ─── Accessibilité : prefers-reduced-motion (S139, WCAG 2.3.3) ──────────────
   Neutralise animations/transitions pour les utilisateurs ayant activé
   « réduire les animations » au niveau OS. Aucun effet (donc aucun changement
   visuel démo) pour les utilisateurs sans cette préférence. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ─── Canon DS dialog::backdrop unifié (S180 Phase 1 T5 / Léa A87) ───────────
   Baseline pour tous les <dialog> HTML5 natifs (helpers Lego ET dialogs custom
   sections). Utilise --pz-bg-overlay défini en tokens.css :
   - Mode clair shell sidebar : rgba(15, 23, 42, 0.6) sombre bleuté
   - Mode dark portal page    : rgba(0, 0, 0, 0.7) plus sombre
   - Suit automatiquement le mode user via cascade tokens.

   Specificity 0,0,2 (element + pseudo) — les helpers Lego avec selectors
   classes (.pz-drawer::backdrop = 0,1,1) gagnent par specificity. Cette
   règle bénéficie aux dialogs custom sections qui n'ont pas de selector
   dédié + sert de référence canon DS pour audit cohérence (sentinelle A87
   force toute redéfinition à pointer var(--pz-bg-overlay) au lieu de
   hardcoded rgba). */
dialog::backdrop {
    background: var(--pz-bg-overlay);
    backdrop-filter: blur(2px);
}


/* ─────────────────────────────────────────────────────────────────────────
   S198 mobile P1 (audit Léa S196) — bloc touch/anti-zoom iOS DÉPLACÉ d'admin.css
   (admin.css n'est chargé que pour admin/syndic/vitrine/prestataire → les OWNER
   ctx=client n'en héritaient pas : zoom auto Safari sur focus input, cibles 28px).
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    /* Boutons : cible tactile généreuse */
    .btn-sm,
    .admin-table .btn-sm,
    .admin-table .btn-xs {
        padding: 8px 14px;
        font-size: .85rem;
        min-height: 36px;
        line-height: 1.3;
    }
    .btn-xs { padding: 7px 12px; font-size: .8rem; min-height: 34px; }

    /* Tables legacy : wrapper scroll horizontal silencieux */
    .admin-table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        max-width: 100%;
        font-size: .85em;
    }
    .admin-table thead, .admin-table tbody, .admin-table tr {
        display: table;
        width: 100%;
        table-layout: auto;
    }
    .admin-table th, .admin-table td {
        padding: 8px 10px;
        white-space: nowrap;
        /* S198 P2 audit Léa #9 — neutralise les widths inline legacy (syndic_assemblies:804
           380px présence, admin_patrimoine:625-626 340/420px) : la table scrolle, les colonnes
           reprennent leur taille naturelle. */
        width: auto !important;
        min-width: 0 !important;
    }

    /* Forms : 16px = seuil anti-zoom-auto Safari iOS sur focus (TOUS les contextes,
       OWNER inclus — formulaires drawers, login, demandes) */
    .form-group input,
    .form-group select,
    .form-group textarea,
    .form-input-sm,
    .pz-drawer-field input,
    .pz-drawer-field select,
    .pz-drawer-field textarea {
        min-height: 40px;
        font-size: 16px;
    }
}

/* Pure touch (pas de hover, pointeur grossier = mobile/tablette) : cibles ≥40px
   + S198 P2 audit Léa #7 : bump tactile composant (row-actions + pagination + actions toolbar). */
@media (hover: none) and (pointer: coarse) {
    .btn-sm:hover,
    .admin-btn:hover,
    .admin-btn-ghost:hover { background: inherit; }
    .pz-tab { min-height: 40px; }
    .pz-dt-row-action,
    .pz-dt-action,
    .pz-dt-pagination button,
    .pz-dt-pagination a {
        min-height: 40px;
        min-width: 40px;
    }
}

/* S198 P2 audit Léa #10 — hint de scroll horizontal (calendrier ≥700px dans overflow-x:auto) */
.pz-scroll-hint { display: none; }
@media (max-width: 720px) {
    .pz-scroll-hint {
        display: block;
        text-align: center;
        color: var(--pz-text-muted, #94a3b8);
        font-size: .75rem;
        margin: 2px 0 6px;
    }
}
