/*
 * OkaySire — page d'auth · direction "Passeport" (livraison design, remplace login.css).
 * Le panneau gauche prend la couleur de l'APP (--brand-accent/-2, posés par le bloc
 * <style> nonce'd par-client) ; le formulaire reste sur un blanc froid neutre.
 * Défaut OkaySire = vert sapin. Fonts self-hosted (/fonts). CSP-clean : les seules
 * valeurs dynamiques sont --brand-accent/-2, --brand-bg-image et le background-image
 * de chaque tuile — tous émis par BrandingStyle dans le seul bloc <style> nonce'd.
 *
 * Mur d'affiches — direction « l'atmosphère » : .poster-tile porte une image de
 * contenu par-app (background-image posé côté serveur). La couleur de l'app n'est
 * PAS un filtre posé sur l'œuvre : c'est l'air dans lequel le mur s'éloigne. Une
 * seule variable par colonne (--haze) pilote ensemble flou, brume et virage de
 * teinte, et un mask-image dissout le mur là où le titre vit — la lisibilité vient
 * de la composition, pas d'un voile. Fallback : aplat --brand-accent-2.
 */

/* ------------------------------------------------------------------ fonts */
@font-face {
    font-family: 'Bricolage Grotesque';
    font-style: normal; font-weight: 400 800; font-display: swap;
    src: url('/fonts/bricolage-grotesque-latin.woff2') format('woff2');
}
@font-face {
    font-family: 'Instrument Serif';
    font-style: normal; font-weight: 400; font-display: swap;
    src: url('/fonts/instrument-serif-latin.woff2') format('woff2');
}

/* ------------------------------------------------------------------ tokens */
:root {
    --font-sans: 'Bricolage Grotesque', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --font-serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;

    /* blanc FROID (biais vert-gris) — jamais warm cream */
    --ground: #eef1ee;
    --card-bg: #f6f8f5;
    --ink: #141a16;
    --ink-soft: #39433d;
    --muted: #5d6862;
    --muted-2: #838d87;
    --line: rgba(20, 26, 22, .13);
    --line-strong: rgba(20, 26, 22, .22);

    /* couleur de l'APP — overridée par le bloc :root nonce'd. Défaut OkaySire = vert sapin. */
    --brand-accent: #14563f;
    --brand-accent-2: #0e3d2c;
    --on-brand: #eaf1ea; /* texte clair sur le panneau coloré */

    /* Marque « profonde » — même teinte, valeur basse. --brand-accent-2 n'est que
       l'accent assombri de 18 % côté serveur : sur un accent clair (corail #f0574e
       → #c5473f) il reste VIF, et un aplat vif sous le titre est criard tout en
       frôlant le seuil de contraste. Dérivée ici en CSS (aucun calcul serveur en
       plus), elle garantit le contraste du texte quel que soit l'accent du client. */
    --brand-deep: color-mix(in srgb, var(--brand-accent-2) 58%, #14100f);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}
a { color: inherit; }

/* ------------------------------------------------------------------ layout */
.auth { display: flex; min-height: 100vh; }

/* ------------------------------------------- panneau app (gauche), coloré */
.brand-panel {
    position: relative;
    flex: 1.1;
    overflow: hidden;
    color: var(--on-brand);
    background: var(--brand-accent); /* fallback plein si color-mix non supporté */
    background: radial-gradient(135% 120% at 18% -10%,
        color-mix(in srgb, var(--brand-accent) 82%, #fff) 0%,
        var(--brand-accent) 42%,
        var(--brand-accent-2) 100%);
}
@media (max-width: 900px) { .brand-panel { display: none; } }

/* Image de fond par-client optionnelle (si une seule image plutôt que la galerie).
   Ancrage vertical en HAUT, pas au centre : ces fonds sont des AFFICHES portrait
   (980×1440 ici), donc `cover` cale sur la largeur et déborde en hauteur — 246 px sur
   un panneau de 721×813. Centré, ce débord était rogné symétriquement (~167 px de
   l'original à chaque bout) : une affiche porte son sujet en HAUT et son propre titre
   imprimé en BAS, on perdait donc la tête du sujet, et ce qui restait du titre de
   l'affiche entrait en collision avec .brand-title. Or .brand-content (logo + titre
   + description) est justement posée en bas du panneau. Ancrer en haut préserve le
   sujet ET rejette toute la zone sacrifiée là où le texte de l'UI et le dégradé de
   .brand-overlay la recouvrent déjà.
   L'horizontale reste centrée par défaut : sur une image paysage `cover` cale sur la
   hauteur, le débord devient latéral et c'est bien un recadrage symétrique
   gauche/droite qu'on veut — l'ancrage vertical n'a alors plus aucun effet.
   Ce cadrage est désormais RÉGLABLE par client : --brand-bg-position est émis par le
   serveur (BrandingStyle) à partir de deux ENTIERS bornés 0–100, jamais d'une chaîne
   CSS — sinon la valeur fermerait la déclaration et en injecterait d'autres.
   Le fallback est `center top`, PAS le défaut navigateur : si la variable manquait
   (HTML mis en cache, page ne passant pas par BrandingStyle), on retombe sur le
   comportement v0.6.14 décrit ci-dessus et non sur `0% 0%`. */
.brand-panel--image { background-image: var(--brand-bg-image); background-size: cover; background-position: var(--brand-bg-position, center top); }
.brand-panel--image .poster-wall { display: none; }

/* Le mur se dissout vers le bas-gauche → le titre repose sur la couleur pure du
   panneau. Aucun voile global n'est donc nécessaire pour la lisibilité (d'où
   l'absence d'opacity ici : le masque fait tout le travail). Le débord n'existe
   qu'à GAUCHE, là où le masque efface — la colonne proche, côté formulaire, reste
   entière. .brand-panel a overflow:hidden : ce qui dépasse est rogné proprement. */
.poster-wall {
    position: absolute; inset: -10% 0 -4% -8%;
    display: flex; gap: 22px; pointer-events: none;
    -webkit-mask-image: radial-gradient(128% 100% at 6% 104%,
        transparent 0%, rgba(0, 0, 0, .16) 26%, rgba(0, 0, 0, .62) 52%, #000 76%);
            mask-image: radial-gradient(128% 100% at 6% 104%,
        transparent 0%, rgba(0, 0, 0, .16) 26%, rgba(0, 0, 0, .62) 52%, #000 76%);
}

/* Profondeur : de la colonne LOINTAINE (à gauche, côté texte) à la colonne PROCHE
   (à droite, côté formulaire). Largeur, vitesse, flou et brume varient ensemble —
   un seul curseur par colonne, --haze, hérité par les tuiles. Les délais négatifs
   désynchronisent la dérive dès la première frame (sinon les 4 colonnes partent au
   même endroit et le mur se lit comme une grille). */
.poster-col {
    flex: 1; display: flex; flex-direction: column; gap: 22px;
    animation: poster-drift linear infinite;
}
.poster-col--0 { --haze: .58; flex: .74;  margin-top:  6%; animation-duration: 96s; animation-delay: -37s; filter: blur(3px)   saturate(.60); }
.poster-col--1 { --haze: .34; flex: .88;  margin-top: -5%; animation-duration: 74s; animation-delay: -11s; filter: blur(1.5px) saturate(.80); }
.poster-col--2 { --haze: .16; flex: 1.06; margin-top:  3%; animation-duration: 58s; animation-delay: -46s; filter: blur(.5px)  saturate(.93); }
.poster-col--3 { --haze: .05; flex: 1.24; margin-top: -8%; animation-duration: 46s; animation-delay: -19s; }

/* Tuile = image de contenu par-app (background-image posé côté serveur : folder ou
   URLs CDN → bloc <style> nonce'd) + deux couches pilotées par --haze. AUCUN
   multiply : il ferait chuter la luminance et salirait l'affiche.
   flex-shrink: 0 est structurel — sans lui, 6 tuiles en aspect-ratio 2/3 dans une
   colonne plus courte que leur somme sont écrasées et les affiches sont coupées. */
.poster-tile {
    position: relative;
    flex-shrink: 0;
    aspect-ratio: 2 / 3;      /* ratio affiche (films/séries/jeux) */
    border-radius: 13px;
    overflow: hidden;
    background-color: var(--brand-accent-2);  /* fallback si pas d'image */
    background-size: cover;
    background-position: center;
    isolation: isolate;       /* les blends ci-dessous ne voient que CETTE tuile */
    box-shadow:
        inset 0 0 0 1px color-mix(in srgb, var(--on-brand) 18%, transparent),
        0 28px 54px -26px rgba(0, 0, 0, .9);
}
/* Virage de TEINTE vers la marque : `color` ne touche ni la luminance ni le
   contraste de l'affiche — impossible de la rendre boueuse (≠ multiply). */
.poster-tile::before {
    content: ""; position: absolute; inset: 0; z-index: 1;
    background: linear-gradient(170deg, var(--brand-accent) 0%, var(--brand-accent-2) 100%);
    mix-blend-mode: color;
    opacity: var(--haze, .2);
}
/* Perte de contraste = éloignement. La tuile lointaine se dilue dans la marque
   profonde, pas dans un gris : c'est exactement l'air du panneau. */
.poster-tile::after {
    content: ""; position: absolute; inset: 0; z-index: 2;
    background: var(--brand-deep);
    opacity: calc(var(--haze, .2) * .82);
}

/* Bibliothèque pauvre : à des profondeurs différentes la même affiche ne se lit
   déjà plus comme une répétition ; ces recadrages finissent le travail. Le serveur
   ne pose .poster-wall--sparse que s'il a MOINS d'affiches distinctes que de
   tuiles — sur une bibliothèque riche aucune affiche n'est rognée (donc aucun
   titre imprimé sur l'affiche n'est coupé). */
.poster-wall--sparse .poster-tile:nth-of-type(2n+1) { background-size: 122% auto; background-position: 28% 22%; }
.poster-wall--sparse .poster-tile:nth-of-type(3n)   { background-size: 110% auto; background-position: 70% 64%; }

@keyframes poster-drift { from { transform: translateY(0); } to { transform: translateY(-33%); } }
/* Le flou a un coût GPU. Sous prefers-reduced-motion on coupe la dérive ET le
   flou : la profondeur reste lisible via la brume, la largeur et la taille. */
@media (prefers-reduced-motion: reduce) {
    .poster-col { animation: none; }
    .poster-col--0 { filter: saturate(.60); }
    .poster-col--1 { filter: saturate(.80); }
    .poster-col--2 { filter: saturate(.93); }
}

/* L'overlay est redevenu discret — le masque du mur fait l'essentiel. Il ne reste
   que le socle de marque profonde sous le titre (contraste garanti) et la couture
   avec le formulaire blanc, à droite (box-shadow inset). */
.brand-overlay {
    position: absolute; inset: 0;
    background: var(--brand-accent-2); /* fallback */
    background:
        radial-gradient(112% 88% at 2% 108%,
            var(--brand-deep) 0%,
            var(--brand-deep) 26%,
            color-mix(in srgb, var(--brand-deep) 74%, transparent) 48%,
            transparent 78%),
        linear-gradient(180deg,
            color-mix(in srgb, var(--brand-accent) 16%, transparent) 0%,
            transparent 32%,
            color-mix(in srgb, var(--brand-deep) 38%, transparent) 80%,
            color-mix(in srgb, var(--brand-deep) 78%, transparent) 100%);
    box-shadow: inset -90px 0 80px -60px color-mix(in srgb, var(--brand-deep) 70%, transparent);
}
.brand-overlay::after {
    content: ""; position: absolute; inset: 0; opacity: .06; mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.brand-content { position: absolute; inset-inline: 0; bottom: 0; padding: 54px 58px; }
.brand-logo { display: inline-flex; align-items: center; gap: 12px; font-weight: 700; font-size: 22px; letter-spacing: -.01em; }
.brand-mark {
    width: 32px; height: 32px; border-radius: 9px; flex: none;
    display: grid; place-items: center; font-weight: 700; font-size: 17px;
    color: var(--brand-accent); background: var(--on-brand);
}
/* Le .badge générique (plus bas) est dessiné POUR UN FOND CLAIR : texte et liseré en
   --brand-accent. Sur le panneau le fond est sombre — et parfois c'est une affiche —
   donc l'accent n'a plus de contraste : sur le vert sapin, l'accent OkaySire par
   DÉFAUT, la pastille disparaît purement et simplement.
   Ici on la repose sur la marque profonde — le même « air » que le reste du panneau,
   pas un aplat rapporté — et on passe texte et liseré en --on-brand. Le socle est
   quasi opaque : c'est ce qui garantit le contraste même quand la pastille tombe sur
   une affiche claire. Sélecteur en .brand-logo .badge (0,2,0) : celui du formulaire,
   dans .auth-logo sur fond clair, garde l'accent et ne bouge pas. */
.brand-logo .badge {
    border-color: color-mix(in srgb, var(--on-brand) 34%, transparent);
    background: color-mix(in srgb, var(--brand-deep) 88%, transparent);
    color: var(--on-brand);
}
.brand-title {
    margin: 24px 0 14px; font-family: var(--font-serif); font-weight: 400;
    font-size: 47px; line-height: 1.04; letter-spacing: .004em; max-width: 15ch; text-wrap: balance;
}
.brand-desc { margin: 0; max-width: 44ch; font-size: 15.5px; line-height: 1.6; color: color-mix(in srgb, var(--on-brand) 80%, transparent); }

/* ----------------------------------------------------------- auth (droite) */
.auth-panel {
    flex: 1; min-width: 448px;
    display: flex; align-items: center; justify-content: center;
    padding: 40px 32px; position: relative;
}
.auth-panel::before {
    content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .028; mix-blend-mode: multiply;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (max-width: 900px) { .auth-panel { min-width: 0; width: 100%; } }

.auth-card { width: 100%; max-width: 398px; position: relative; }
.auth-card > * { animation: rise .6s cubic-bezier(.2, .7, .2, 1) both; }
.auth-card > *:nth-child(1) { animation-delay: .02s; }
.auth-card > *:nth-child(2) { animation-delay: .08s; }
.auth-card > *:nth-child(3) { animation-delay: .14s; }
.auth-card > *:nth-child(4) { animation-delay: .2s; }
.auth-card > *:nth-child(5) { animation-delay: .26s; }
@keyframes rise { from { opacity: 0; transform: translateY(11px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .auth-card > * { animation: none; } }

.auth-logo { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; font-size: 17px; letter-spacing: -.01em; margin-bottom: 42px; }
.auth-logo .brand-mark { width: 27px; height: 27px; font-size: 14px; color: var(--card-bg); background: var(--brand-accent); }

.badge {
    display: inline-flex; align-items: center; height: 21px; padding: 0 8px;
    border: 1px solid var(--brand-accent); border-radius: 6px; color: var(--brand-accent);
    font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; line-height: 1;
}

.auth-heading { font-family: var(--font-serif); font-weight: 400; font-size: 41px; line-height: 1.05; margin: 0 0 9px; letter-spacing: .004em; text-wrap: balance; }
.auth-sub { margin: 0 0 30px; color: var(--muted); font-size: 15px; line-height: 1.5; }

/* ----------------------------------------------------------- social + or */
.social { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.social-btn {
    display: flex; align-items: center; justify-content: center; gap: 10px; height: 47px;
    border-radius: 11px; border: 1px solid var(--line-strong); background: var(--card-bg); color: var(--ink);
    font-family: var(--font-sans); font-size: 14.5px; font-weight: 600; cursor: pointer;
    transition: border-color .15s, background .15s;
}
.social-btn:hover { border-color: color-mix(in srgb, var(--ink) 30%, transparent); background: #fff; }

.btn-secondary {
    display: flex; align-items: center; justify-content: center; width: 100%; height: 47px;
    margin: 6px 0 14px; border-radius: 11px; border: 1px solid var(--line-strong); background: transparent;
    color: var(--brand-accent); font-family: var(--font-sans); font-size: 14px; font-weight: 600; cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.btn-secondary:hover {
    border-color: color-mix(in srgb, var(--brand-accent) 55%, transparent);
    background: color-mix(in srgb, var(--brand-accent) 8%, transparent);
}

.divider { display: flex; align-items: center; gap: 14px; margin: 4px 0 20px; color: var(--muted-2); font-size: 12px; text-transform: uppercase; letter-spacing: .1em; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ------------------------------------------------------------------ form */
.field { margin-bottom: 17px; }
.field label { display: block; margin-bottom: 8px; font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
.field-row { display: flex; align-items: center; justify-content: space-between; }
.forgot-link { font-size: 12.5px; color: var(--muted); text-decoration: none; border-bottom: 1px solid transparent; }
.forgot-link:hover { color: var(--brand-accent); border-bottom-color: color-mix(in srgb, var(--brand-accent) 40%, transparent); }

.control { position: relative; }
.input {
    width: 100%; height: 48px; padding: 0 15px; border-radius: 11px;
    border: 1px solid var(--line-strong); background: var(--card-bg); color: var(--ink);
    font-family: var(--font-sans); font-size: 15px; outline: none;
    transition: border-color .16s ease, box-shadow .16s ease, background .16s ease;
}
.input::placeholder { color: var(--muted-2); }
.input:hover { border-color: color-mix(in srgb, var(--ink) 28%, transparent); }
.input:focus { border-color: var(--brand-accent); box-shadow: 0 0 0 3.5px color-mix(in srgb, var(--brand-accent) 16%, transparent); background: #fff; }
.control--password .input { padding-right: 48px; }

.pw-toggle {
    position: absolute; top: 0; right: 0; width: 46px; height: 48px;
    display: flex; align-items: center; justify-content: center;
    border: none; background: transparent; color: var(--muted); cursor: pointer;
}
.pw-toggle:hover { color: var(--ink); }
.pw-toggle svg { display: block; }
.pw-toggle .icon-eye-off { display: none; }
.pw-toggle.showing .icon-eye { display: none; }
.pw-toggle.showing .icon-eye-off { display: block; }

/* ------------------------------------------------- password strength bars */
.strength { display: flex; gap: 6px; margin-top: 9px; }
.strength span { flex: 1; height: 4px; border-radius: 2px; background: rgba(20, 26, 22, .1); transition: background .15s ease; }
.strength[data-score="1"] span:nth-child(-n+1),
.strength[data-score="2"] span:nth-child(-n+2),
.strength[data-score="3"] span:nth-child(-n+3),
.strength[data-score="4"] span:nth-child(-n+4) { background: var(--brand-accent); }

/* ------------------------------------------------------------ submit + cta */
.submit {
    width: 100%; height: 50px; margin-top: 10px; border: none; border-radius: 11px; color: var(--on-brand);
    font-family: var(--font-sans); font-size: 15px; font-weight: 700; letter-spacing: .01em; cursor: pointer;
    background: var(--brand-accent); /* fallback */
    background: linear-gradient(135deg, var(--brand-accent) 0%, var(--brand-accent-2) 100%);
    box-shadow: 0 10px 24px -12px color-mix(in srgb, var(--brand-accent) 70%, transparent);
    transition: transform .12s ease, box-shadow .16s ease, filter .16s ease;
}
.submit:hover { filter: brightness(1.06); transform: translateY(-1px); box-shadow: 0 14px 30px -12px color-mix(in srgb, var(--brand-accent) 78%, transparent); }
.submit:active { transform: translateY(0); filter: brightness(.97); }

.switch { margin: 24px 0 0; text-align: center; font-size: 14px; color: var(--muted); }
.switch a { color: var(--brand-accent); font-weight: 600; text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--brand-accent) 35%, transparent); }
.switch a:hover { border-bottom-color: var(--brand-accent); }
/* Sign-out is a POST (a GET would be triggerable from any third-party page), so it is a button.
   Styled as the links beside it: the affordance is a text action either way. */
.switch button { padding: 0; border: 0; border-bottom: 1px solid color-mix(in srgb, var(--brand-accent) 35%, transparent); background: none; color: var(--brand-accent); font-family: inherit; font-size: inherit; font-weight: 600; cursor: pointer; }
.switch button:hover { border-bottom-color: var(--brand-accent); }

/* ------------------------------------------------------------------ error */
.alert {
    margin-bottom: 20px; padding: 12px 14px; border-radius: 11px;
    border: 1px solid color-mix(in srgb, #b23b2e 40%, transparent);
    background: color-mix(in srgb, #b23b2e 9%, transparent);
    color: #7a271c; font-size: 13.5px; line-height: 1.4;
}

/* -------------------------------------------------------- mode visibility */
/* Le serveur pose data-mode sur <body> ; le JS peut le flipper. Marche sans JS. */
[data-mode="login"] .js-register,
[data-mode="register"] .js-login { display: none; }

:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 2px; }
