/* ==========================================================================
   SB 1.5 — Panel web
   Thème : PrimeNG « Aura Dark »
     · surfaces  → palette zinc
     · primaire  → palette emerald
     · rayons    → 6px (md), 4px (sm), 8px (lg)

   Les jetons sont nommés comme ceux de PrimeNG (--p-*) : changer de préréglage
   revient à remplacer les deux échelles ci-dessous. Les alias hérités plus bas
   permettent aux vues EJS de continuer à utiliser --accent, --red, etc.
   ========================================================================== */

:root {
    color-scheme: dark;

    /* --- Échelle de surface (zinc) ---------------------------------------- */
    --p-surface-0: #ffffff;
    --p-surface-50: #fafafa;
    --p-surface-100: #f4f4f5;
    --p-surface-200: #e4e4e7;
    --p-surface-300: #d4d4d8;
    --p-surface-400: #a1a1aa;
    --p-surface-500: #71717a;
    --p-surface-600: #52525b;
    --p-surface-700: #3f3f46;
    --p-surface-800: #27272a;
    --p-surface-900: #18181b;
    --p-surface-950: #09090b;

    /* --- Échelle primaire (emerald) --------------------------------------- */
    --p-primary-100: #d1fae5;
    --p-primary-200: #a7f3d0;
    --p-primary-300: #6ee7b7;
    --p-primary-400: #34d399;
    --p-primary-500: #10b981;
    --p-primary-600: #059669;
    --p-primary-700: #047857;

    /* --- Jetons sémantiques, mode sombre ---------------------------------- */
    --p-primary-color: var(--p-primary-400);
    --p-primary-hover-color: var(--p-primary-300);
    --p-primary-contrast-color: var(--p-surface-950);
    /* Teinte primaire translucide, pour les anneaux de focus. */
    --p-primary-background: rgba(52, 211, 153, .2);

    --p-ground-background: var(--p-surface-950);
    --p-content-background: var(--p-surface-900);
    --p-content-hover-background: var(--p-surface-800);

    /*
     * Bordures translucides plutôt qu'une teinte fixe : posées sur une surface
     * claire ou sombre elles gardent le même poids visuel, et le trait reste
     * une nuance de la surface au lieu d'un cadre dessiné par-dessus.
     */
    --p-content-border-color: rgba(255, 255, 255, .07);
    --p-content-border-strong: rgba(255, 255, 255, .12);

    /* Voile qui éclaire le haut d'une carte, comme une lumière rasante. */
    --p-surface-sheen: linear-gradient(180deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, 0) 45%);

    --p-text-color: var(--p-surface-0);
    --p-text-muted-color: var(--p-surface-400);
    --p-text-hover-color: var(--p-surface-0);

    --p-form-background: rgba(255, 255, 255, .025);
    --p-form-border-color: rgba(255, 255, 255, .09);
    --p-form-hover-border-color: rgba(255, 255, 255, .18);

    /* --- États ------------------------------------------------------------ */
    --p-success-color: #34d399;
    --p-success-background: rgba(52, 211, 153, .16);
    --p-danger-color: #f87171;
    --p-danger-background: rgba(248, 113, 113, .16);
    --p-warn-color: #fbbf24;
    --p-warn-background: rgba(251, 191, 36, .16);
    --p-info-color: #60a5fa;
    --p-neutral-color: var(--p-surface-400);

    /* --- Métriques -------------------------------------------------------- */
    /*
     * Rayons élargis : les angles serrés d'Aura datent le panel. L'échelle
     * reste proportionnée — un champ de saisie ne doit pas paraître aussi
     * arrondi que la carte qui le contient.
     */
    --p-border-radius-sm: 8px;
    --p-border-radius-md: 11px;
    --p-border-radius-lg: 16px;
    --p-border-radius-xl: 22px;
    --p-focus-ring-width: 2px;
    --p-focus-ring-offset: 2px;
    --p-transition-duration: .18s;
    /* Départ franc, arrivée amortie : un mouvement qui se pose au lieu de
       s'arrêter net. */
    --p-ease: cubic-bezier(.4, 0, .2, 1);

    /* --- Alias hérités, utilisés par les styles en ligne des vues ---------- */
    --bg: var(--p-ground-background);
    --bg-soft: var(--p-surface-900);
    --surface: var(--p-content-background);
    --surface-hover: var(--p-content-hover-background);
    --border: var(--p-content-border-color);
    --text: var(--p-text-color);
    --text-muted: var(--p-text-muted-color);
    --accent: var(--p-primary-color);
    --accent-hover: var(--p-primary-hover-color);
    --green: var(--p-success-color);
    --red: var(--p-danger-color);
    --orange: var(--p-warn-color);
    --grey: var(--p-neutral-color);
    --radius: var(--p-border-radius-lg);
    --radius-sm: var(--p-border-radius-md);

    /* --- Élévation --------------------------------------------------------- */
    /* Deux couches : une ombre large et diffuse pour la distance, une seconde
       courte et dense pour ancrer l'élément. Une ombre unique paraît plate. */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow: 0 12px 32px -10px rgba(0, 0, 0, .6), 0 2px 6px rgba(0, 0, 0, .35);
    --shadow-lg: 0 32px 64px -16px rgba(0, 0, 0, .7), 0 4px 12px rgba(0, 0, 0, .4);
    /* Une ombre teintée sous un bouton primaire le fait flotter au lieu de
       simplement l'assombrir. */
    --shadow-primary: 0 8px 20px -8px rgba(52, 211, 153, .55);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    min-height: 100vh;
    background: var(--p-ground-background);
    color: var(--p-text-color);
    font-family: Inter, "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Chiffres de largeur fixe : dans un tableau d'états, des colonnes qui
       tressautent à chaque rafraîchissement se remarquent tout de suite. */
    font-variant-numeric: tabular-nums;
}

/*
 * Halo discret en haut de page. Posé en `fixed` sur un pseudo-élément plutôt
 * qu'en fond de `body` : il ne défile pas, ne s'étire pas sur les pages
 * longues, et `pointer-events: none` le garde hors de portée du curseur.
 */
body::before {
    content: "";
    position: fixed;
    inset: 0 0 auto;
    height: 480px;
    pointer-events: none;
    z-index: 0;
    background:
        radial-gradient(60% 100% at 50% 0%, rgba(52, 211, 153, .09), transparent 70%),
        radial-gradient(40% 80% at 85% 0%, rgba(96, 165, 250, .06), transparent 70%);
}

/* Le contenu passe au-dessus du halo. */
.topbar, .layout, .auth { position: relative; z-index: 1; }

a { color: var(--p-primary-color); text-decoration: none; transition: color var(--p-transition-duration); }
a:hover { color: var(--p-primary-hover-color); text-decoration: none; }

/* Les grands titres se resserrent, les petits respirent : un interlettrage
   uniforme fait paraître un h1 lâche et un h3 comprimé. */
h1, h2, h3 { margin: 0 0 .5rem; line-height: 1.2; font-weight: 650; }
h1 { font-size: 1.875rem; letter-spacing: -.025em; }
h2 { font-size: 1.25rem; letter-spacing: -.015em; }
h3 { font-size: 1rem; letter-spacing: -.005em; }
p { margin: 0 0 1rem; }

code {
    font-family: "JetBrains Mono", "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
    font-size: .85em;
    background: var(--p-surface-950);
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-sm);
    padding: .1em .4em;
    color: var(--p-surface-300);
}

/* --- Structure ---------------------------------------------------------- */

.layout {
    max-width: 1140px;
    margin: 0 auto;
    padding: 0 1.5rem 5rem;
}

/*
 * Barre collante et translucide : la navigation reste atteignable sur une
 * longue liste de bots. Le flou n'est appliqué que là où il est supporté —
 * ailleurs, le fond opaque de repli prend le relais et rien ne devient
 * illisible.
 */
.topbar {
    position: sticky;
    top: 0;
    background: rgba(9, 9, 11, .92);
    border-bottom: 1px solid var(--p-content-border-color);
    margin-bottom: 2.5rem;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .topbar {
        background: rgba(9, 9, 11, .65);
        -webkit-backdrop-filter: blur(16px) saturate(160%);
        backdrop-filter: blur(16px) saturate(160%);
    }
}

.topbar-inner {
    max-width: 1140px;
    margin: 0 auto;
    padding: .875rem 1.5rem;
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.brand {
    display: flex;
    align-items: center;
    gap: .625rem;
    font-weight: 600;
    font-size: 1rem;
    color: var(--p-text-color);
}
.brand:hover { color: var(--p-text-color); }

.brand-mark {
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border-radius: 10px;
    background: linear-gradient(145deg, var(--p-primary-300), var(--p-primary-600));
    color: var(--p-primary-contrast-color);
    font-size: .75rem;
    font-weight: 800;
    letter-spacing: -.02em;
    box-shadow: var(--shadow-primary);
}

.nav { display: flex; gap: .25rem; margin-left: auto; align-items: center; flex-wrap: wrap; }

.nav-link {
    padding: .5rem .875rem;
    border-radius: 999px;
    color: var(--p-text-muted-color);
    font-weight: 500;
    transition: background var(--p-transition-duration) var(--p-ease),
                color var(--p-transition-duration) var(--p-ease);
}
.nav-link:hover { background: rgba(255, 255, 255, .06); color: var(--p-text-color); }
.nav-link.is-active {
    background: var(--p-primary-background);
    color: var(--p-primary-color);
}

.nav-user {
    display: flex; align-items: center; gap: .625rem;
    padding-left: 1rem; margin-left: .5rem;
    border-left: 1px solid var(--p-content-border-color);
}
.nav-user img { width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--p-content-border-color); }
.nav-user-name { font-size: .875rem; font-weight: 500; }
.nav-user-role { font-size: .75rem; color: var(--p-text-muted-color); }

.page-head {
    display: flex; align-items: flex-start; gap: 1rem;
    flex-wrap: wrap; margin-bottom: 1.5rem;
}
.page-head p { color: var(--p-text-muted-color); margin: 0; }
.page-head-actions { margin-left: auto; display: flex; gap: .5rem; }

/* --- Boutons (PrimeNG Button) -------------------------------------------- */

.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
    padding: .5625rem 1.125rem;
    border: 1px solid var(--p-content-border-strong);
    border-radius: var(--p-border-radius-md);
    background: rgba(255, 255, 255, .03);
    color: var(--p-text-color);
    font: inherit;
    font-weight: 550;
    letter-spacing: -.005em;
    cursor: pointer;
    transition: background var(--p-transition-duration) var(--p-ease),
                border-color var(--p-transition-duration) var(--p-ease),
                color var(--p-transition-duration) var(--p-ease),
                transform var(--p-transition-duration) var(--p-ease),
                box-shadow var(--p-transition-duration) var(--p-ease);
}
.btn:hover {
    background: rgba(255, 255, 255, .07);
    border-color: var(--p-form-hover-border-color);
}
/* L'enfoncement se voit sans déplacer le texte autour. */
.btn:active { transform: translateY(1px); }

.btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 var(--p-focus-ring-offset) var(--p-ground-background),
                0 0 0 calc(var(--p-focus-ring-offset) + var(--p-focus-ring-width)) var(--p-primary-color);
}

.btn-primary {
    background: linear-gradient(180deg, var(--p-primary-300), var(--p-primary-500));
    border-color: transparent;
    color: var(--p-primary-contrast-color);
    font-weight: 650;
    box-shadow: var(--shadow-primary);
}
.btn-primary:hover {
    background: linear-gradient(180deg, var(--p-primary-200), var(--p-primary-400));
    border-color: transparent;
    box-shadow: 0 10px 26px -8px rgba(52, 211, 153, .7);
}

.btn-danger { color: var(--p-danger-color); border-color: var(--p-content-border-color); }
.btn-danger:hover { background: var(--p-danger-background); border-color: var(--p-danger-color); }

/* Un bouton désactivé garde son apparence : seul l'estompage signale l'état,
   sinon un « Démarrer » primaire deviendrait un bouton fantôme au survol. */
.btn[disabled] { opacity: .4; cursor: not-allowed; box-shadow: none; }
.btn[disabled]:hover {
    background: rgba(255, 255, 255, .03);
    border-color: var(--p-content-border-strong);
    transform: none;
}
.btn[disabled]:active { transform: none; }
.btn-primary[disabled]:hover {
    background: linear-gradient(180deg, var(--p-primary-300), var(--p-primary-500));
    border-color: transparent;
    box-shadow: none;
}
.btn-danger[disabled]:hover { background: rgba(255, 255, 255, .03); border-color: var(--p-content-border-strong); }

.btn-sm { padding: .375rem .75rem; font-size: .8125rem; border-radius: var(--p-border-radius-sm); }
.btn-lg { padding: .8125rem 1.75rem; font-size: .9375rem; }

/* --- Cartes (PrimeNG Card) ----------------------------------------------- */

/*
 * La carte n'est pas un aplat : un voile clair en haut simule une lumière
 * rasante et lui donne une épaisseur. Le dégradé est posé sur la couleur de
 * fond, pas à la place, pour que la surface reste opaque.
 */
.card {
    position: relative;
    background: var(--p-surface-sheen), var(--p-content-background);
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-lg);
    padding: 1.5rem;
    box-shadow: var(--shadow-sm);
    transition: border-color var(--p-transition-duration) var(--p-ease),
                box-shadow var(--p-transition-duration) var(--p-ease);
}

.grid { display: grid; gap: 1.125rem; }
.grid-bots { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.grid-stats { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

.stat { text-align: center; padding: 1.375rem .875rem; }
.stat-value {
    font-size: 2rem; font-weight: 700; line-height: 1.1; letter-spacing: -.03em;
    /* Dégradé sur le chiffre : la donnée prime, l'étiquette reste sourde. */
    background: linear-gradient(180deg, var(--p-surface-0), var(--p-surface-400));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}
/* Valeur textuelle plutôt que numérique : une durée détaillée déborderait
   d'une tuile à 1.75rem. */
.stat-value-text {
    font-size: 1rem; font-weight: 600; line-height: 1.4; letter-spacing: 0;
    background: none; color: var(--p-text-color);
}
.stat-label {
    color: var(--p-text-muted-color);
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    font-weight: 500;
}

.bot-card { display: flex; flex-direction: column; gap: 1.125rem; }
/* La carte se soulève au survol : le geste dit « cliquable » mieux qu'un
   simple changement de teinte. */
.bot-card:hover, .guild-card:hover {
    border-color: var(--p-content-border-strong);
    box-shadow: var(--shadow);
}
.bot-head { display: flex; align-items: center; gap: .875rem; }
.bot-avatar {
    width: 44px; height: 44px; border-radius: 14px;
    background: var(--p-surface-950);
    border: 1px solid var(--p-content-border-color);
    flex-shrink: 0;
    object-fit: cover;
}
.bot-name { font-weight: 600; letter-spacing: -.01em; }
.bot-id { font-size: .75rem; color: var(--p-text-muted-color); font-family: "JetBrains Mono", Consolas, monospace; }

.bot-meta { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem 1rem; font-size: .875rem; }
.bot-meta dt {
    color: var(--p-text-muted-color);
    font-size: .6875rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 500;
    margin-bottom: .125rem;
}
.bot-meta dd { margin: 0; font-weight: 500; }

.bot-actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: auto; }
.bot-actions form { display: contents; }

/* --- Pastilles d'état (PrimeNG Tag) -------------------------------------- */

.pill {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .25rem .625rem;
    /* Entièrement arrondie : une pastille d'état se lit comme une étiquette,
       pas comme un petit bouton. */
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 600;
    background: var(--p-surface-800);
    color: var(--p-text-muted-color);
    white-space: nowrap;
}
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Le point d'un bot en ligne bat doucement : l'état se remarque sans qu'on
   ait à relire l'étiquette. Coupé si l'utilisateur réduit les animations. */
.pill-online::before { animation: pulse 2.4s var(--p-ease) infinite; }

@keyframes pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(52, 211, 153, .5); }
    60% { box-shadow: 0 0 0 5px rgba(52, 211, 153, 0); }
}

.pill-online { background: var(--p-success-background); color: var(--p-success-color); }
.pill-crashed { background: var(--p-danger-background); color: var(--p-danger-color); }
.pill-starting, .pill-stopping { background: var(--p-warn-background); color: var(--p-warn-color); }
.pill-expired { background: var(--p-danger-background); color: var(--p-danger-color); opacity: .8; }

/* --- Tableaux (PrimeNG DataTable) ---------------------------------------- */

.table-wrap {
    overflow-x: auto;
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-lg);
    box-shadow: var(--shadow-sm);
}
table { width: 100%; border-collapse: collapse; font-size: .875rem; background: var(--p-content-background); }
th, td { padding: .875rem 1.125rem; text-align: left; vertical-align: middle; }
th {
    font-size: .6875rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--p-text-muted-color);
    font-weight: 600;
    background: rgba(255, 255, 255, .025);
    border-bottom: 1px solid var(--p-content-border-color);
}
td { border-bottom: 1px solid var(--p-content-border-color); }
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background var(--p-transition-duration); }
tbody tr:hover { background: var(--p-content-hover-background); }
td.actions { white-space: nowrap; }
td.actions form { display: inline; }

/* --- Formulaires (PrimeNG InputText) ------------------------------------- */

.field { margin-bottom: 1rem; }
.field label {
    display: block;
    margin-bottom: .375rem;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--p-text-color);
}

input[type="text"], input[type="search"], select, textarea {
    width: 100%;
    padding: .625rem .875rem;
    background: var(--p-form-background);
    border: 1px solid var(--p-form-border-color);
    border-radius: var(--p-border-radius-md);
    color: var(--p-text-color);
    font: inherit;
    transition: border-color var(--p-transition-duration) var(--p-ease),
                background var(--p-transition-duration) var(--p-ease),
                box-shadow var(--p-transition-duration) var(--p-ease);
}
textarea { resize: vertical; min-height: 5rem; }
input::placeholder, textarea::placeholder { color: var(--p-surface-600); }
input:hover, select:hover, textarea:hover { border-color: var(--p-form-hover-border-color); }
select { cursor: pointer; }

input:focus, select:focus, textarea:focus {
    outline: none;
    background: rgba(255, 255, 255, .04);
    border-color: var(--p-primary-color);
    box-shadow: 0 0 0 3px var(--p-primary-background);
}

.form-inline { display: flex; gap: .75rem; flex-wrap: wrap; align-items: flex-end; }
.form-inline .field { flex: 1 1 200px; margin-bottom: 0; }

/* --- Messages (PrimeNG Message) ------------------------------------------ */

.flash {
    padding: .75rem 1rem;
    border-radius: var(--p-border-radius-md);
    border: 1px solid transparent;
    margin-bottom: 1.25rem;
    font-size: .875rem;
    font-weight: 500;
}
.flash-success {
    background: var(--p-success-background);
    border-color: rgba(52, 211, 153, .3);
    color: var(--p-success-color);
}
.flash-error {
    background: var(--p-danger-background);
    border-color: rgba(248, 113, 113, .3);
    color: var(--p-danger-color);
}
.flash code { background: transparent; border: none; color: inherit; font-weight: 600; }

/* --- Configuration d'un bot ---------------------------------------------- */

.crumbs {
    display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
    margin-bottom: .5rem;
    font-size: .8125rem;
    color: var(--p-text-muted-color);
}
.crumbs a { color: var(--p-text-muted-color); text-decoration: none; }
.crumbs a:hover { color: var(--p-primary-color); }

.settings-form { display: flex; flex-direction: column; gap: 1.25rem; }

.settings-section { padding: 0; overflow: hidden; }
.settings-section-head {
    padding: 1.125rem 1.5rem;
    border-bottom: 1px solid var(--p-content-border-color);
    background: rgba(255, 255, 255, .025);
}
.settings-section-head h2 { margin: 0; font-size: 1rem; }
.settings-section-head p {
    margin: .25rem 0 0;
    font-size: .8125rem;
    color: var(--p-text-muted-color);
}

/* Deux colonnes dès qu'il y a la place : une liste de 11 journaux sur une
   seule colonne obligerait à faire défiler pour comparer. */
.settings-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 1rem 1.25rem;
    padding: 1.25rem;
}
.settings-fields .field { margin-bottom: 0; }

.field-label { display: flex; flex-direction: column; gap: .125rem; }
.field-help {
    font-size: .75rem;
    font-weight: 400;
    color: var(--p-text-muted-color);
}
.field-count { margin: .375rem 0 0; font-size: .75rem; color: var(--p-text-muted-color); }

.settings-actions {
    display: flex; gap: .75rem; flex-wrap: wrap;
    padding-bottom: 1rem;
}

/* Interrupteur : la case native reste la source de vérité, seulement masquée,
   pour garder le clavier et les lecteurs d'écran. */
.switch { display: flex; align-items: center; gap: .625rem; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track {
    flex: 0 0 auto;
    width: 40px; height: 22px;
    padding: 3px;
    border-radius: 999px;
    background: var(--p-surface-700);
    transition: background var(--p-transition-duration);
}
.switch-thumb {
    display: block;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--p-surface-300);
    transition: transform var(--p-transition-duration), background var(--p-transition-duration);
}
.switch input:checked + .switch-track { background: var(--p-primary-color); }
.switch input:checked + .switch-track .switch-thumb {
    transform: translateX(18px);
    background: var(--p-surface-950);
}
.switch input:focus-visible + .switch-track {
    box-shadow: 0 0 0 var(--p-focus-ring-width) var(--p-primary-background);
}
.switch-text { font-size: .8125rem; color: var(--p-text-muted-color); }

/* Liste à cocher : un serveur peut avoir cent rôles, la hauteur est bornée. */
.picker {
    max-height: 11rem;
    overflow-y: auto;
    padding: .5rem;
    background: var(--p-form-background);
    border: 1px solid var(--p-form-border-color);
    border-radius: var(--p-border-radius-md);
}
.picker-item {
    display: flex; align-items: center; gap: .5rem;
    padding: .25rem .375rem;
    border-radius: var(--p-border-radius-sm);
    font-size: .8125rem;
    font-weight: 400;
    cursor: pointer;
}
.picker-item:hover { background: var(--p-content-hover-background); }
.picker-item input { width: auto; accent-color: var(--p-primary-color); }
.picker-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.guild-card { text-decoration: none; color: inherit; transition: border-color var(--p-transition-duration); }
.guild-card:hover { border-color: var(--p-primary-color); }
.guild-card .bot-head { margin: 0; }
.guild-initial {
    display: flex; align-items: center; justify-content: center;
    width: 40px; height: 40px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--p-surface-800);
    font-weight: 600;
}
.guild-go { margin-left: auto; font-size: 1.25rem; color: var(--p-text-muted-color); }

/* --- Transcriptions de tickets ------------------------------------------- */

.filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.25rem; }
.filter-chip {
    display: inline-flex; align-items: center; gap: .5rem;
    padding: .375rem .75rem;
    border: 1px solid var(--p-content-border-strong);
    border-radius: 999px;
    color: var(--p-text-muted-color);
    font-size: .8125rem; font-weight: 500;
    transition: background var(--p-transition-duration) var(--p-ease),
                color var(--p-transition-duration) var(--p-ease);
}
.filter-chip:hover { background: rgba(255, 255, 255, .06); color: var(--p-text-color); }
.filter-chip.is-active {
    background: var(--p-primary-background);
    border-color: transparent;
    color: var(--p-primary-color);
}
.filter-chip img { width: 18px; height: 18px; border-radius: 50%; }
.filter-count { opacity: .65; font-variant-numeric: tabular-nums; }

.ticket-link { display: inline-flex; align-items: center; gap: .5rem; font-weight: 500; }
.ticket-kind {
    padding: .125rem .375rem;
    border-radius: var(--p-border-radius-sm);
    font-size: .625rem; font-weight: 700; letter-spacing: .04em;
    background: var(--p-surface-800); color: var(--p-text-muted-color);
}
.ticket-kind-modmail { background: var(--p-primary-background); color: var(--p-primary-color); }

/* --- Explorateur de base -------------------------------------------------- */

.db-search { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; }
.db-search input { flex: 1 1 18rem; }

.db-table { table-layout: fixed; }
.db-table th:nth-child(1) { width: 34%; }
.db-table th:nth-child(2) { width: 12%; }
.db-table th:nth-child(3) { width: 10%; }

.db-key {
    font-family: "JetBrains Mono", Consolas, monospace;
    font-size: .8125rem;
    word-break: break-all;
}
.db-key-title {
    font-family: "JetBrains Mono", Consolas, monospace;
    font-size: 1.125rem;
    word-break: break-all;
    letter-spacing: 0;
}

.db-type {
    display: inline-block;
    padding: .0625rem .375rem;
    border-radius: var(--p-border-radius-sm);
    background: var(--p-surface-800);
    color: var(--p-text-muted-color);
    font-size: .6875rem; font-weight: 600;
}
.db-type-tableau { background: rgba(96, 165, 250, .16); color: var(--p-info-color); }
.db-type-objet { background: rgba(167, 139, 250, .16); color: #a78bfa; }
.db-type-boolean { background: var(--p-success-background); color: var(--p-success-color); }
.db-type-number { background: var(--p-warn-background); color: var(--p-warn-color); }

/* L'aperçu tient sur une ligne : une valeur de 4 Ko ne doit pas étirer la
   rangée sur trente lignes. */
.db-preview {
    font-family: "JetBrains Mono", Consolas, monospace;
    font-size: .75rem;
    color: var(--p-text-muted-color);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    max-width: 0;
}

.db-pager {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
    margin-top: 1rem;
    font-size: .8125rem;
}
.db-pager-buttons { display: flex; align-items: center; gap: .75rem; }
/* Un lien ne peut pas être `disabled` : on le neutralise visuellement et au
   pointeur, sans le retirer du flux. */
.btn.is-disabled { opacity: .4; pointer-events: none; }

.db-value {
    max-height: 28rem;
    overflow: auto;
    margin: 0;
    padding: 1rem;
    background: var(--p-surface-950);
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-md);
    font-size: .8125rem;
    line-height: 1.6;
    white-space: pre;
}
.db-value code { background: none; border: none; padding: 0; color: var(--p-surface-200); }

.db-section-title { font-size: .8125rem; text-transform: uppercase; letter-spacing: .06em; color: var(--p-text-muted-color); }

.db-raw { margin-top: 1.25rem; padding: 1rem 1.5rem; }
.db-raw summary { cursor: pointer; font-size: .8125rem; color: var(--p-text-muted-color); }
.db-raw summary:hover { color: var(--p-text-color); }
.db-raw .db-value { margin-top: .875rem; }

/* --- Valeurs mises en forme ---------------------------------------------- */

/*
 * Chaque type a sa couleur : en parcourant une structure, l'œil distingue un
 * identifiant d'une date sans lire, ce qui est tout l'intérêt par rapport au
 * JSON brut où tout est de la même teinte.
 */
.dv-root { font-size: .875rem; }

.dv-null { color: var(--p-surface-500); font-style: italic; }
.dv-string { color: var(--p-surface-200); }
.dv-number { color: var(--p-warn-color); font-variant-numeric: tabular-nums; }
.dv-date { color: var(--p-info-color); }
.dv-id { color: #a78bfa; font-family: "JetBrains Mono", Consolas, monospace; font-size: .8125rem; }
.dv-url { color: var(--p-primary-color); word-break: break-all; }
.dv-hint { color: var(--p-surface-600); font-size: .6875rem; margin-left: .375rem; }

.dv-bool {
    display: inline-block;
    padding: .0625rem .375rem;
    border-radius: 999px;
    font-size: .6875rem; font-weight: 600;
}
.dv-bool-true { background: var(--p-success-background); color: var(--p-success-color); }
.dv-bool-false { background: var(--p-surface-800); color: var(--p-text-muted-color); }

.dv-text {
    margin: 0;
    padding: .5rem .625rem;
    background: var(--p-surface-950);
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-sm);
    font-size: .8125rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-height: 16rem; overflow: auto;
}
.dv-deep { color: var(--p-text-muted-color); }

/* Objet : les noms de champ en gouttière, les valeurs alignées à droite —
   la structure se lit verticalement sans accolades. */
.dv-object {
    display: grid;
    grid-template-columns: minmax(6rem, auto) 1fr;
    gap: .25rem .875rem;
    margin: 0;
    padding: .5rem 0 .5rem .875rem;
    border-left: 2px solid var(--p-content-border-color);
}
.dv-object > dt {
    color: var(--p-text-muted-color);
    font-size: .8125rem;
    font-weight: 500;
    overflow-wrap: anywhere;
}
.dv-object > dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

.dv-list {
    margin: 0;
    padding: .25rem 0 .25rem 1.75rem;
    border-left: 2px solid var(--p-content-border-color);
}
.dv-list > li { padding: .1875rem 0; }
.dv-list > li::marker { color: var(--p-surface-600); font-size: .75rem; }

.dv-table-wrap { overflow-x: auto; border-radius: var(--p-border-radius-sm); }
.dv-table { width: 100%; border-collapse: collapse; font-size: .8125rem; background: none; }
.dv-table th, .dv-table td {
    padding: .375rem .625rem;
    border-bottom: 1px solid var(--p-content-border-color);
    text-align: left;
    vertical-align: top;
}
.dv-table th {
    background: rgba(255, 255, 255, .025);
    font-size: .6875rem; text-transform: uppercase; letter-spacing: .05em;
}
.dv-table tbody tr:last-child td { border-bottom: none; }
.dv-table tbody tr:hover { background: rgba(255, 255, 255, .03); }
.dv-index { width: 2.5rem; color: var(--p-surface-600); font-variant-numeric: tabular-nums; }

.dv-more { margin: .5rem 0 0; font-size: .75rem; color: var(--p-text-muted-color); }

.db-danger {
    display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap;
    margin-top: 1.25rem;
    border-color: rgba(248, 113, 113, .25);
}
.db-danger h2 { font-size: 1rem; }
.db-danger p { margin: 0; color: var(--p-text-muted-color); font-size: .875rem; max-width: 46rem; }
.db-danger form { margin-left: auto; }

/* --- Rendu façon Discord -------------------------------------------------- */

/*
 * Le bloc reprend les codes de Discord — fond propre, avatars ronds, messages
 * groupés — sans emprunter son thème au reste du panel : une transcription
 * doit se lire comme une capture de la conversation, pas comme une page de
 * plus. D'où des couleurs posées en dur ici, et non des jetons du thème.
 */
.dc {
    background: #313338;
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow);
    color: #dbdee1;
    font-size: .9375rem;
    line-height: 1.375;
}

.dc-head {
    display: flex; align-items: center; gap: .75rem;
    padding: .875rem 1.25rem;
    background: #2b2d31;
    border-bottom: 1px solid rgba(0, 0, 0, .3);
}
.dc-guild-icon { width: 32px; height: 32px; border-radius: 50%; }
.dc-channel { font-weight: 650; color: #f2f3f5; }
.dc-guild { font-size: .75rem; color: #949ba4; }
.dc-participants { margin-left: auto; font-size: .75rem; color: #949ba4; }

/* Une longue conversation reste dans son cadre plutôt que d'étirer la page. */
.dc-messages { max-height: 70vh; overflow-y: auto; padding: 1rem 0; }

.dc-divider {
    display: flex; align-items: center; gap: .75rem;
    margin: 1rem 1.25rem .5rem;
    color: #949ba4; font-size: .75rem; font-weight: 600;
}
.dc-divider::before, .dc-divider::after {
    content: ""; flex: 1; height: 1px; background: rgba(255, 255, 255, .06);
}

.dc-message {
    display: flex; gap: 1rem;
    padding: .125rem 1.25rem;
    margin-top: 1.0625rem;
}
/* Un message groupé n'a ni avatar ni en-tête : il se cale sur la gouttière
   du précédent. */
.dc-message.is-grouped { margin-top: .0625rem; }
.dc-message:hover { background: rgba(2, 2, 2, .06); }

.dc-avatar {
    width: 40px; height: 40px; border-radius: 50%;
    flex: 0 0 40px;
    background: #1e1f22;
    object-fit: cover;
}
.dc-avatar-fallback {
    display: grid; place-items: center;
    font-weight: 600; color: #dbdee1;
}

/* L'heure n'apparaît au survol que sur les messages groupés, comme dans
   l'application. Elle occupe la gouttière de l'avatar. */
.dc-hover-time {
    width: 40px; flex: 0 0 40px;
    font-size: .6875rem; color: #949ba4;
    text-align: right; line-height: 1.375;
    opacity: 0;
    transition: opacity var(--p-transition-duration) var(--p-ease);
}
.dc-message:hover .dc-hover-time { opacity: 1; }

.dc-body { min-width: 0; flex: 1; }
.dc-meta { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.dc-author { font-weight: 500; color: #f2f3f5; }
.dc-bot-tag {
    padding: .0625rem .275rem;
    border-radius: 3px;
    background: #5865f2; color: #fff;
    font-size: .625rem; font-weight: 600;
    text-transform: uppercase;
}
.dc-time { font-size: .6875rem; color: #949ba4; }

.dc-content { white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; }
.dc-edited { font-size: .625rem; color: #949ba4; margin-left: .25rem; }

.dc-mention {
    padding: 0 2px; border-radius: 3px;
    background: rgba(88, 101, 242, .3); color: #c9cdfb;
    font-weight: 500;
}
.dc-link { color: #00a8fc; }
.dc-link:hover { color: #00a8fc; text-decoration: underline; }
.dc-quote {
    display: block;
    padding-left: .75rem;
    border-left: 4px solid #4e5058;
    color: #b5bac1;
}
.dc-timestamp { background: rgba(88, 101, 242, .18); border-radius: 3px; padding: 0 2px; }

/* Le contenu masqué se révèle au survol : sans JavaScript, c'est le geste le
   plus proche du clic de Discord. */
.dc-spoiler {
    background: #1e1f22; border-radius: 3px;
    color: transparent;
    transition: color var(--p-transition-duration) var(--p-ease);
}
.dc-spoiler:hover { background: rgba(30, 31, 34, .6); color: #dbdee1; }

.dc-inline-code {
    background: #1e1f22; border: none;
    border-radius: 3px; padding: .125rem .25rem;
    font-size: .85em; color: #dbdee1;
}
.dc-codeblock {
    background: #1e1f22;
    border: 1px solid #2b2d31;
    border-radius: 4px;
    padding: .625rem;
    margin: .25rem 0;
    overflow-x: auto;
    font-size: .8125rem;
    white-space: pre;
}
.dc-codeblock code { background: none; border: none; padding: 0; color: #dbdee1; }

.dc-emoji { width: 1.375em; height: 1.375em; vertical-align: -.3em; }

.dc-reply {
    display: flex; align-items: center; gap: .375rem;
    margin: 0 1.25rem -.125rem 4.25rem;
    font-size: .8125rem; color: #b5bac1;
}
.dc-reply img { width: 16px; height: 16px; border-radius: 50%; }
.dc-reply-name { font-weight: 500; color: #f2f3f5; }
.dc-reply-text { color: #949ba4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dc-reply-spine {
    width: 32px; height: 10px;
    margin-left: -2.375rem;
    border-left: 2px solid #4e5058;
    border-top: 2px solid #4e5058;
    border-top-left-radius: 6px;
    align-self: flex-end;
}

.dc-image { display: block; margin-top: .25rem; max-width: 400px; }
.dc-image img { max-width: 100%; height: auto; border-radius: 8px; display: block; }

.dc-file {
    display: flex; align-items: center; gap: .625rem;
    margin-top: .25rem; padding: .625rem;
    max-width: 400px;
    background: #2b2d31;
    border: 1px solid rgba(255, 255, 255, .06);
    border-radius: 8px;
}
.dc-file-icon { font-size: 1.25rem; }
.dc-file-size { font-size: .75rem; color: #949ba4; }

.dc-embed {
    max-width: 520px;
    margin-top: .25rem;
    padding: .625rem 1rem .625rem .75rem;
    background: #2b2d31;
    border-left: 4px solid #4f545c;
    border-radius: 4px;
}
.dc-embed-author { display: flex; align-items: center; gap: .5rem; font-size: .875rem; font-weight: 600; margin-bottom: .25rem; }
.dc-embed-author img { width: 24px; height: 24px; border-radius: 50%; }
.dc-embed-title { font-weight: 600; color: #f2f3f5; margin-bottom: .25rem; }
.dc-embed-description { font-size: .875rem; white-space: pre-wrap; overflow-wrap: anywhere; }
.dc-embed-fields { display: flex; flex-wrap: wrap; gap: .5rem 1rem; margin-top: .5rem; }
.dc-embed-field { flex: 1 1 100%; min-width: 0; }
.dc-embed-field.is-inline { flex: 1 1 30%; }
.dc-embed-field-name { font-size: .8125rem; font-weight: 600; color: #f2f3f5; }
.dc-embed-field-value { font-size: .8125rem; overflow-wrap: anywhere; }
.dc-embed-thumb { float: right; max-width: 80px; border-radius: 4px; margin-left: .75rem; }
.dc-embed-image { display: block; max-width: 100%; border-radius: 4px; margin-top: .5rem; }
.dc-embed-footer { display: flex; align-items: center; gap: .5rem; margin-top: .5rem; font-size: .75rem; color: #949ba4; }
.dc-embed-footer img { width: 20px; height: 20px; border-radius: 50%; }

.dc-reactions { display: flex; flex-wrap: wrap; gap: .25rem; margin-top: .25rem; }
.dc-reaction {
    display: inline-flex; align-items: center; gap: .25rem;
    padding: .125rem .375rem;
    background: rgba(255, 255, 255, .04);
    border: 1px solid rgba(255, 255, 255, .06);
    border-radius: 8px;
    font-size: .8125rem;
}
.dc-reaction img { width: 16px; height: 16px; }

.dc-foot {
    padding: .875rem 1.25rem;
    background: #2b2d31;
    border-top: 1px solid rgba(0, 0, 0, .3);
    font-size: .8125rem; color: #949ba4;
}

.empty { text-align: center; padding: 3.5rem 1.5rem; }
.empty-icon { font-size: 2.5rem; margin-bottom: .5rem; opacity: .9; }
.empty h2 { margin-bottom: .375rem; }
.empty p { color: var(--p-text-muted-color); max-width: 26rem; margin: 0 auto 1.5rem; }

.muted { color: var(--p-text-muted-color); }
.mono { font-family: "JetBrains Mono", Consolas, monospace; font-size: .8125rem; }

/* --- Page de connexion --------------------------------------------------- */

.auth { min-height: 100vh; display: grid; place-items: center; padding: 1.5rem; }

.auth-card {
    width: 100%;
    max-width: 24rem;
    text-align: center;
    padding: 2.75rem 2rem;
    background: var(--p-surface-sheen), var(--p-content-background);
    border: 1px solid var(--p-content-border-color);
    border-radius: var(--p-border-radius-xl);
    box-shadow: var(--shadow-lg);
}
.auth-mark {
    width: 60px; height: 60px;
    margin: 0 auto 1.5rem;
    display: grid; place-items: center;
    border-radius: var(--p-border-radius-lg);
    background: linear-gradient(145deg, var(--p-primary-300), var(--p-primary-600));
    color: var(--p-primary-contrast-color);
    font-size: 1.375rem;
    font-weight: 800;
    box-shadow: var(--shadow-primary);
}
.auth-card p { color: var(--p-text-muted-color); }
.auth-card .btn { width: 100%; margin-top: .5rem; }

/* --- Page d'erreur ------------------------------------------------------- */

.error-page { min-height: 70vh; display: grid; place-items: center; text-align: center; }
.error-code { font-size: 3.75rem; font-weight: 800; color: var(--p-primary-color); line-height: 1; letter-spacing: -.03em; }
.error-page p { color: var(--p-text-muted-color); white-space: pre-line; max-width: 28rem; margin: 0 auto 1.5rem; }

/* --- Propriétaire (avatar + pseudo) -------------------------------------- */

/* L'avatar est une pastille alignée sur la ligne du nom, pas une vignette :
   il se lit comme une puce et ne domine jamais la cellule. */
.owner { display: inline-flex; align-items: center; gap: .375rem; color: inherit; }
.owner:hover { color: inherit; }
.owner:hover .owner-name { color: var(--p-primary-color); }

.owner-avatar {
    width: 18px; height: 18px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--p-surface-950);
    object-fit: cover;
}

.owner-name { font-weight: 500; transition: color var(--p-transition-duration); }
.owner-id { color: var(--p-text-muted-color); font-size: .75rem; }

/* --- Lignes de type ------------------------------------------------------ */

.type-row {
    display: flex; align-items: center; gap: .75rem;
    padding: .5rem 0;
    border-bottom: 1px solid var(--p-surface-800);
    font-size: .875rem;
}
.type-row:last-of-type { border-bottom: none; }
.type-row .mono { flex: 1; }
.type-row .type-counts { color: var(--p-text-muted-color); font-size: .8125rem; white-space: nowrap; }

/* --- Pied de page -------------------------------------------------------- */

.footer {
    border-top: 1px solid var(--p-content-border-color);
    margin-top: 3.5rem;
    padding: 1.25rem;
    text-align: center;
    color: var(--p-text-muted-color);
    font-size: .8125rem;
}

/* --- Mobile -------------------------------------------------------------- */

@media (max-width: 640px) {
    .topbar-inner { padding: .75rem 1rem; }
    .layout { padding: 0 1rem 3rem; }
    .nav { width: 100%; margin-left: 0; }
    .nav-user { margin-left: auto; border-left: none; padding-left: 0; }
    .page-head-actions { margin-left: 0; width: 100%; }
    .page-head-actions .btn { flex: 1; }
    .bot-meta { grid-template-columns: 1fr; }
    .card { padding: 1.25rem; }
    .settings-fields { padding: 1.125rem; }
    h1 { font-size: 1.5rem; }
    .stat-value { font-size: 1.75rem; }

    /* La barre collante mange trop de hauteur sur un petit écran une fois la
       navigation passée à la ligne. */
    .topbar { position: static; }
}

/* --- Préférences d'affichage --------------------------------------------- */

/*
 * Mouvement réduit : les transitions ne sont pas supprimées mais ramenées à
 * une durée imperceptible. Les retirer ferait sauter les états au lieu de les
 * apaiser, et certains composants s'appuient sur la fin d'une transition.
 */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}
