/* Design system minimal de ChallengeMe : quelques tokens, pas de framework.
   Objectif assumé : zéro dépendance CSS tant que la charte graphique n'est pas arrêtée.

   Feuille partagée par l'application mobile (MAUI BlazorWebView) et l'application web
   (Blazor Server). Elle est servie sous _content/ChallengeMe.Client/app.css dans les deux cas.

   Écriture mobile-first : tout ce qui suit vaut pour un téléphone, et la section « Grand écran »
   en fin de fichier réadapte la mise en page au-delà de 768 px. Un seul jeu de composants .razor
   pour les deux plateformes — la différence est ici, pas dans le balisage. */

:root {
    --navy-900: #0b1220;
    --navy-800: #0f172a;
    --navy-700: #1b2537;
    --navy-600: #27324a;
    --line: #2f3b54;

    --text: #eef2f8;
    --text-muted: #9aa8bf;

    --accent: #3b82f6;
    --accent-strong: #2563eb;
    --success: #22c55e;
    --warning: #f59e0b;
    --danger: #ef4444;

    --radius: 12px;
    --gap: 12px;

    --header-height: 56px;
    --nav-height: 64px;
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    background: var(--navy-900);
    color: var(--text);
    font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
    font-size: 16px;
    -webkit-tap-highlight-color: transparent;
}

h1, h2, h3 {
    margin: 0;
    font-weight: 600;
    line-height: 1.25;
}

h1 { font-size: 1.35rem; }
h2 { font-size: 1.05rem; }

a {
    color: var(--accent);
    text-decoration: none;
}

/* Zone sûre sous l'encoche / la barre d'état iOS et Android. */
.status-bar-safe-area {
    height: env(safe-area-inset-top);
    background: var(--navy-800);
}

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

.app-shell {
    display: flex;
    flex-direction: column;
    min-height: 100%;
    align-items: center;
}

.app-header {
    display: flex;
    align-items: center;
    gap: var(--gap);
    height: var(--header-height);
    padding: 0 16px;
    background: var(--navy-800);
    border-bottom: 1px solid var(--line);
    position: sticky;
    top: 0;
    z-index: 10;
}

.app-brand {
    font-weight: 700;
    letter-spacing: -0.01em;
}

.app-content {
    flex: 1;
    padding: 16px 16px calc(var(--nav-height) + 24px);
}

.app-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--nav-height);
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    background: var(--navy-800);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
}

.nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: var(--text-muted);
    font-size: 0.7rem;
}

.nav-item.active {
    color: var(--accent);
}

.nav-icon {
    font-size: 1.15rem;
}

/* ---- Écrans d'authentification ---- */

.auth-shell {
    min-height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.auth-card {
    width: 100%;
    max-width: 420px;
}

.auth-logo {
    display: block;
    width: 80px;
    height: 80px;
    margin: 0 auto 16px;
}

.auth-brand {
    font-size: 1.75rem;
    text-align: center;
}

.auth-tagline {
    margin: 8px 0 28px;
    text-align: center;
    color: var(--text-muted);
}

.auth-title {
    margin-bottom: 16px;
}

.auth-switch {
    margin-top: 20px;
    text-align: center;
    color: var(--text-muted);
}

.auth-intro {
    margin: 0 0 18px;
    color: var(--text-muted);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* ---- En-têtes de page ---- */

.page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap);
    margin-bottom: 12px;
}

.page-head-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.page-intro {
    margin: 0 0 16px;
    color: var(--text-muted);
    line-height: 1.5;
}

.page-back {
    display: inline-block;
    margin-bottom: 16px;
    color: var(--text-muted);
}

.section {
    margin: 24px 0;
}

.section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap);
}

.section-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.section-hint {
    margin: 0 0 10px;
    color: var(--text-muted);
    font-size: 0.85rem;
    line-height: 1.45;
}

/* ---- Formulaires ---- */

.field {
    display: block;
    margin-bottom: 16px;
}

.field-row {
    display: flex;
    gap: var(--gap);
}

.field-row .field {
    flex: 1;
}

.field-label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.field-optional {
    opacity: 0.7;
}

.field-input {
    width: 100%;
    padding: 12px 14px;
    background: var(--navy-700);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--text);
    font-size: 1rem;
    font-family: inherit;
}

.field-input:focus {
    outline: none;
    border-color: var(--accent);
}

.field-hint {
    display: block;
    margin-top: 6px;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.field-check {
    display: flex;
    align-items: center;
    gap: 10px;
}

.code-input {
    font-family: ui-monospace, "SFMono-Regular", "Consolas", monospace;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.inline-form {
    display: flex;
    gap: var(--gap);
}

.inline-form .field-input {
    flex: 1;
}

.validation-message {
    display: block;
    margin-top: 6px;
    font-size: 0.8rem;
    color: var(--danger);
}

/* ---- Boutons ---- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 12px 18px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-size: 0.95rem;
    font-family: inherit;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.btn:disabled {
    opacity: 0.55;
}

.btn-primary {
    background: var(--accent);
    color: #fff;
}

.btn-primary:active:not(:disabled) {
    background: var(--accent-strong);
}

.btn-ghost {
    background: transparent;
    border-color: var(--line);
    color: var(--text);
}

.btn-danger {
    background: transparent;
    border-color: var(--danger);
    color: var(--danger);
}

/* Action destructrice secondaire : la couleur suffit à la distinguer, sans lui donner le poids
   visuel d'un bouton bordé au milieu d'une rangée d'actions ordinaires. */
.btn-danger-ghost {
    color: var(--danger);
}

.btn-block {
    width: 100%;
    margin-top: 8px;
}

.btn-sm {
    padding: 8px 12px;
    font-size: 0.85rem;
}

/* ---- Codes publics ---- */

.code-chip,
.code-chip-inline {
    padding: 5px 10px;
    background: var(--navy-700);
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--text);
    font-family: ui-monospace, "SFMono-Regular", "Consolas", monospace;
    font-size: 0.8rem;
    letter-spacing: 0.08em;
    cursor: pointer;
}

.code-chip {
    margin-left: auto;
}

.code-block {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 16px;
    background: var(--navy-700);
    border: 1px dashed var(--line);
    border-radius: var(--radius);
    color: var(--text);
    font-family: ui-monospace, "SFMono-Regular", "Consolas", monospace;
    font-size: 1.3rem;
    letter-spacing: 0.16em;
    cursor: pointer;
}

.code-action {
    font-family: "Segoe UI", system-ui, sans-serif;
    font-size: 0.8rem;
    letter-spacing: normal;
    color: var(--accent);
}

/* ---- Cloche de notifications ---- */

.bell {
    position: relative;
    font-size: 1.2rem;
    line-height: 1;
}

.bell-badge {
    position: absolute;
    top: -6px;
    right: -8px;
    min-width: 17px;
    padding: 1px 4px;
    background: var(--danger);
    border-radius: 999px;
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    text-align: center;
}

/* Tout est lu, mais une décision reste à prendre : orange plutôt que rouge, parce que ce n'est
   pas la même information — « du nouveau » d'un côté, « on t'attend » de l'autre. */
.bell-badge-action {
    background: var(--warning);
    color: var(--navy-900);
}

/* ---- Filtres du feed ---- */

.filter-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 12px;
    overflow-x: auto;
}

.filter-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.filter-tab:disabled {
    opacity: 0.55;
}

.filter-tab-active {
    background: var(--navy-700);
    border-color: var(--accent);
    color: var(--text);
}

/* Pictogramme de type, aligné sur le titre de la carte : dans un fil hétérogène (invitations,
   sessions, réponses), il donne la nature de la ligne avant même de la lire. */
.notif-icon {
    margin-right: 6px;
}

/* ---- Cartes ---- */

.card-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--gap);
}

.card {
    padding: 14px;
    background: var(--navy-800);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    cursor: pointer;
}

.card-static {
    cursor: default;
}

.card-unread {
    border-left: 3px solid var(--accent);
}

.card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.card-title {
    font-weight: 600;
}

.card-date {
    flex-shrink: 0;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.card-body {
    margin: 8px 0 0;
    color: var(--text-muted);
    font-size: 0.9rem;
    line-height: 1.45;
}

.card-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
    font-size: 0.82rem;
    color: var(--text-muted);
}

.card-flag {
    margin-top: 10px;
    padding: 8px 10px;
    background: var(--navy-700);
    border-radius: 8px;
    font-size: 0.82rem;
    color: var(--warning);
}

.card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}

/* Une carte sans action n'occupe pas de place vide : le feed en contient beaucoup (sessions
   publiées, réponses reçues) et la rangée d'actions y serait un blanc de 40 px répété. */
.card-actions:empty {
    display: none;
}

/* ---- Badges ---- */

.badge {
    padding: 3px 8px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    white-space: nowrap;
}

.badge-activity {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--navy-600);
    color: var(--text);
}

.badge-icon { font-size: 0.85rem; }
.badge-owner { background: rgba(59, 130, 246, 0.18); color: var(--accent); }
.badge-pending { background: rgba(245, 158, 11, 0.18); color: var(--warning); }
.badge-mine { background: rgba(34, 197, 94, 0.18); color: var(--success); }
.badge-count { background: var(--danger); color: #fff; }

/* Issue d'une notification actionnable : la décision prise, une fois qu'elle l'est. Reprend le
   code couleur des statuts d'événement — vert pour ce qui aboutit, rouge pour ce qui est refusé. */
.badge-outcome-accepted { background: rgba(34, 197, 94, 0.18); color: var(--success); }
.badge-outcome-declined { background: rgba(239, 68, 68, 0.18); color: var(--danger); }
.badge-outcome-obsolete { background: var(--navy-600); color: var(--text-muted); }

.badge-status-draft { background: var(--navy-600); color: var(--text-muted); }
.badge-status-open { background: rgba(59, 130, 246, 0.18); color: var(--accent); }
.badge-status-confirmed { background: rgba(34, 197, 94, 0.18); color: var(--success); }
.badge-status-cancelled { background: rgba(239, 68, 68, 0.18); color: var(--danger); }
.badge-status-done { background: var(--navy-600); color: var(--text-muted); }

/* ---- Listes de membres ---- */

.member-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.member {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 0;
    border-bottom: 1px solid var(--line);
}

.member:last-child {
    border-bottom: none;
}

.member-position {
    width: 24px;
    flex-shrink: 0;
    color: var(--text-muted);
    font-size: 0.8rem;
    text-align: right;
}

.member-name {
    flex: 1;
}

/* ---- Détails ---- */

.details {
    margin: 0;
    padding: 0;
}

.details > div {
    display: flex;
    justify-content: space-between;
    gap: var(--gap);
    padding: 11px 0;
    border-bottom: 1px solid var(--line);
}

.details dt {
    color: var(--text-muted);
    font-size: 0.85rem;
}

.details dd {
    margin: 0;
    text-align: right;
}

/* ---- Bannières ---- */

.banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 12px 0;
    padding: 12px 14px;
    border-radius: var(--radius);
    font-size: 0.88rem;
    line-height: 1.4;
}

.banner-error { background: rgba(239, 68, 68, 0.14); color: #fca5a5; }
.banner-success { background: rgba(34, 197, 94, 0.14); color: #86efac; }
.banner-info { background: rgba(59, 130, 246, 0.14); color: #93c5fd; }

.banner-close {
    background: none;
    border: none;
    color: inherit;
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
}

/* ---- États vides et chargement ---- */

.empty {
    padding: 40px 20px;
    text-align: center;
}

.empty-hint {
    color: var(--text-muted);
    line-height: 1.5;
}

.empty-actions {
    display: flex;
    justify-content: center;
    gap: var(--gap);
    margin-top: 20px;
}

.empty-inline {
    color: var(--text-muted);
    font-size: 0.88rem;
}

.loading {
    padding: 40px 20px;
    text-align: center;
}

.loading-spinner {
    width: 28px;
    height: 28px;
    margin: 0 auto 12px;
    border: 3px solid var(--line);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spin 0.9s linear infinite;
}

.loading-text {
    color: var(--text-muted);
    font-size: 0.88rem;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* ---- Bandeau d'erreur Blazor ---- */

#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    padding: 14px 20px;
    background: var(--warning);
    color: #1f2937;
    box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.3);
}

#blazor-error-ui .dismiss {
    position: absolute;
    top: 8px;
    right: 12px;
    cursor: pointer;
}

/* ---- Accessibilité au clavier ----

   Le mobile n'a pas de clavier physique et ne posait donc pas la question ; sur le web, une
   navigation entièrement au clavier sans anneau de focus visible est inutilisable. `:focus-visible`
   plutôt que `:focus` : l'anneau n'apparaît pas au clic à la souris ou au doigt. */

:where(a, button, .card, .code-block, .code-chip, .code-chip-inline):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ---- Conteneurs de mise en page ----

   Trois classes posées par les pages, sans effet sur mobile : ce sont des `div` ordinaires, donc
   des blocs, et les marges des sections qu'elles contiennent se comportent exactement comme si
   elles n'existaient pas. Elles ne prennent un sens qu'aux points d'arrêt de bureau.

   .page-narrow  — page de formulaire ou de réglages : borne la largeur de saisie.
   .page-grid    — page de consultation : passe en deux colonnes.
   .page-grid-main / .page-grid-side — les deux colonnes de .page-grid.

   Elles sont volontairement posées dans un ordre du DOM qui reproduit l'empilement mobile
   d'origine. C'est le placement explicite en grille, et non l'ordre du DOM, qui répartit les blocs
   en colonnes — le mobile n'a donc rien à réapprendre. */

/* ---- Grand écran (>= 768 px) ----

   Le mobile n'atteint jamais ce point d'arrêt ; ces règles ne concernent en pratique que
   l'application web et la fenêtre Windows de l'application MAUI.

   Une application de téléphone affichée en grand n'est pas une application de bureau : on ne se
   contente pas d'élargir la colonne. La barre du pouce devient une barre latérale, la typographie
   remonte d'un cran, les zones de saisie cessent de s'étirer, et les pages de consultation passent
   sur deux colonnes (voir 1024 px). */

@media (min-width: 768px) {
    :root {
        --nav-width: 240px;
        --content-max: 1180px;
        --header-height: 64px;
    }

    /* Un texte lu à un bras de distance sur un écran de 24 pouces n'a pas la même taille utile
       qu'à trente centimètres sur un téléphone. */
    html, body { font-size: 16px; }
    h1 { font-size: 1.75rem; }
    h2 { font-size: 1.15rem; }

    .app-brand { font-size: 1.05rem; }
    .app-header { padding: 0 28px; gap: 16px; }

    /* La barre latérale se place sous l'en-tête, qui reste pleine largeur : la marque et le code
       public restent au même endroit que sur mobile, un seul repère à apprendre. */
    .app-nav {
        top: var(--header-height);
        right: auto;
        bottom: 0;
        width: var(--nav-width);
        height: auto;
        grid-template-columns: 1fr;
        grid-auto-rows: min-content;
        gap: 4px;
        padding: 16px 12px;
        border-top: none;
        border-right: 1px solid var(--line);
    }

    .nav-item {
        flex-direction: row;
        justify-content: flex-start;
        gap: 12px;
        padding: 11px 12px;
        border-radius: var(--radius);
        font-size: 0.95rem;
    }

    .nav-item:hover {
        background: var(--navy-700);
        color: var(--text);
    }

    .nav-item.active {
        background: rgba(59, 130, 246, 0.14);
        color: var(--accent);
    }

    .nav-icon { font-size: 1.1rem; }

    /* Plus de barre basse à dégager : la réserve de padding disparaît. */
    .app-content {
        max-width: var(--content-max);
        margin-left: var(--nav-width);
        padding: 28px 32px 56px;
    }

    .page-head { margin-bottom: 20px; }
    .page-intro { max-width: 68ch; }
    .section-hint { max-width: 68ch; }

    /* Formulaires et réglages. Un champ de saisie de 1 100 px de large est illisible et donne
       l'impression que la page est vide : on borne, et la colonne reste calée à gauche plutôt que
       centrée, pour rester alignée sur le titre de la page. */
    .page-narrow { max-width: 720px; }

    /* Idem pour les éléments qui, seuls dans le flux d'une page large, s'étireraient sans raison. */
    .page-narrow .btn-block,
    .page-grid .btn-block { max-width: 100%; }

    .code-block { max-width: 460px; }

    /* Le survol n'existe pas au doigt : ces retours ne sont ajoutés que là où un pointeur existe. */
    .card {
        transition: border-color 0.12s ease, background 0.12s ease;
    }

    .card:not(.card-static):hover {
        border-color: var(--accent);
    }

    .btn {
        transition: background 0.12s ease, border-color 0.12s ease;
    }

    .btn-primary:hover:not(:disabled) { background: var(--accent-strong); }
    .btn-ghost:hover:not(:disabled) { background: var(--navy-700); }
    .btn-danger:hover:not(:disabled) { background: rgba(239, 68, 68, 0.12); }

    .code-chip:hover,
    .code-chip-inline:hover,
    .code-block:hover {
        border-color: var(--accent);
    }
}

/* ---- Bureau (>= 1024 px) ----

   Le point d'arrêt où une seule colonne cesse d'être défendable : deux tiers de l'écran restent
   vides et l'utilisateur fait défiler pour atteindre des blocs qui tiendraient côte à côte. */

@media (min-width: 1024px) {
    /* Les listes de cartes (groupes, sessions, demandes) passent en grille. `auto-fill` plutôt
       qu'un nombre de colonnes figé : la même règle donne deux colonnes dans la zone principale
       d'une page en deux colonnes, et trois en pleine largeur. */
    .card-list {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
        align-items: start;
    }

    /* Exception : un fil de notifications se lit de haut en bas, par ordre d'arrivée. En grille,
       l'œil perd la chronologie — on garde une colonne, simplement bornée. */
    .card-feed {
        grid-template-columns: 1fr;
        max-width: 780px;
    }

    /* Deux colonnes : le contenu vivant à gauche, ce qui s'y rapporte à droite.
       Le placement est explicite (grid-column), donc indépendant de l'ordre du DOM — c'est ce qui
       permet de conserver l'empilement mobile sans le réécrire. */
    .page-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 340px;
        /* row-gap : quand la colonne de droite est coupée en deux blocs, ils occupent deux rangées
           distinctes et se toucheraient sans cet écart — les marges internes des panneaux sont
           remises à zéro sur le dernier de chaque bloc. */
        gap: 20px 28px;
        align-items: start;
    }

    .page-grid > * { min-width: 0; }

    .page-grid-main { grid-column: 1; grid-row: 1; }
    .page-grid-side { grid-column: 2; }

    /* Quand la colonne de droite est coupée en deux blocs (l'un avant la colonne principale dans
       le DOM, l'autre après), la colonne principale doit couvrir les deux rangées — sinon la
       hauteur de la première borne la liste et pousse le second bloc trop bas. */
    .page-grid-main-tall { grid-column: 1; grid-row: 1 / span 2; }

    /* La colonne de droite devient un panneau : sans ce fond, deux colonnes de texte nu se lisent
       comme deux pages juxtaposées, sans hiérarchie. */
    .page-grid-side .section {
        margin: 0 0 20px;
        padding: 18px;
        background: var(--navy-800);
        border: 1px solid var(--line);
        border-radius: var(--radius);
    }

    .page-grid-side .section:last-child { margin-bottom: 0; }
    .page-grid-side .code-block { max-width: 100%; }

    /* Le premier bloc de chaque colonne doit démarrer à la même hauteur : sans cela, la marge
       haute de la section décale la colonne principale sous le premier panneau. */
    .page-grid-main > :first-child,
    .page-grid-main-tall > :first-child { margin-top: 0; }

    /* Les listes de personnes tiennent en colonnes dès qu'il y a de la place. `column-width`
       plutôt qu'un nombre : une liste étroite (panneau de droite) reste sur une colonne, une liste
       large en prend deux ou trois, sans règle supplémentaire. */
    .member-list {
        column-width: 240px;
        column-gap: 28px;
    }

    .member { break-inside: avoid; }

    /* Les métadonnées d'une session se lisent mieux en deux colonnes qu'en liste d'une ligne
       chacune sur toute la largeur. */
    .details {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
        column-gap: 28px;
    }

    .empty { padding: 64px 24px; }
}
