/* ============================================================================= * UltiSuite — habillage des flows Authentik (login / signup / recovery / MFA) * ----------------------------------------------------------------------------- * Injection : ce fichier est monté sur /web/dist/custom.css dans le conteneur * authentik-server (cf. deploy/docker-compose.yml). Authentik le sert avec * l'attribut `data-inject` : * * Le bundle flow récupère le texte de chaque `link[data-inject]` et l'adopte * (adoptedStyleSheets) dans le shadow root de CHAQUE composant Lit/PatternFly. * => nos sélecteurs `.pf-c-*` atteignent l'intérieur des web components. * * Conséquences (shadow DOM) : * - Les variables custom (`:root`) cascadent via héritage dans tous les roots. * - Les sélecteurs descendants NE TRAVERSENT PAS les frontières de shadow root. * Pour cibler le chrome porté par l'executor on utilise `:host([flowslug=…])` * (l'hôte du shadow root de l'executor est ``). * - Les éléments internes d'une étape (formulaire, champs, bouton) vivent dans * le shadow root `` : on les style globalement (look partagé). * * Carte de la structure (flow login `default-authentication-flow`) : * ak-flow-executor[flowslug] (shadow #1) * .pf-c-background-image ← fond plein écran * .pf-c-login.stacked > .ak-login-container * .pf-c-login__main ← LA CARTE * .pf-c-login__main-header.pf-c-brand.ak-brand > img ← logo * ak-stage-identification (shadow #2) * header.pf-c-login__main-header > h1.pf-c-title ← titre * .pf-c-login__main-body > form.pf-c-form * ak-form-element.pf-c-form__group (shadow #3 : label) + input.pf-c-form-control * .pf-c-form__group.pf-m-action > button.pf-c-button.pf-m-primary * footer.pf-c-login__main-footer * .pf-c-login__main-footer-band > p > a#enroll ← "Créer un compte" * .pf-c-login__footer ← "Powered by authentik" (masqué) * ========================================================================== */ /* ---- Angle animé pour les anneaux arc-en-ciel (carte + bouton) ---------- */ @property --ulti-ring-angle { syntax: ""; inherits: true; initial-value: 145deg; } /* ---- Jetons de design (repris de .ultimail-login du frontend) ----------- */ :root { --ulti-bg: #f7f8fc; --ulti-line: rgba(21, 24, 30, 0.07); --ulti-glow-a: #4f6df5; --ulti-glow-b: #9a5cf0; --ulti-glow-c: #1fb6c9; --ulti-card-glass: rgba(255, 255, 255, 0.62); --ulti-card-border: rgba(21, 24, 30, 0.1); --ulti-card-highlight: rgba(255, 255, 255, 0.72); --ulti-text: #3c4043; --ulti-text-strong: #202124; --ulti-text-muted: #5f6368; --ulti-link: #1a73e8; --ulti-input-bg: #ffffff; --ulti-input-border: rgba(21, 24, 30, 0.16); --ulti-rainbow: conic-gradient( from var(--ulti-ring-angle), #1a73e8, #34a853, #fbbc04, #ea4335, #1a73e8 ); /* Remplace l'accent corail Authentik (#fd4b2d) — utilisé pour les scrollbars. */ --ulti-scrollbar-thumb: color-mix(in srgb, var(--ulti-text-muted) 55%, transparent); --ulti-scrollbar-thumb-hover: color-mix(in srgb, var(--ulti-text-muted) 75%, transparent); --ak-accent: var(--ulti-scrollbar-thumb); /* Boutons primaires — gris neutre */ --ulti-btn-primary-bg: #f4f4f5; --ulti-btn-primary-fg: #18181b; --ulti-btn-primary-bg-hover: #e4e4e7; --ulti-btn-primary-border: color-mix(in srgb, var(--ulti-text-strong) 14%, transparent); --ulti-btn-primary-border-width: 2px; --ulti-btn-primary-border-hover: color-mix(in srgb, var(--ulti-text-muted) 42%, transparent); --ulti-btn-primary-shadow: none; --ulti-btn-primary-shadow-hover: none; --ulti-btn-primary-ring: color-mix(in srgb, var(--ulti-text-muted) 35%, transparent); --ulti-link-ui: var(--ulti-text-muted); --ulti-link-ui-hover: var(--ulti-text); --pf-global--link--Color: var(--ulti-link-ui); --pf-global--link--Color--hover: var(--ulti-link-ui-hover); --pf-global--link--Color--light: var(--ulti-link-ui); --pf-global--link--Color--dark: var(--ulti-link-ui-hover); --ulti-card-backdrop: blur(16px) saturate(1.2); } @media (prefers-color-scheme: dark) { :root { --ulti-bg: #0b0d12; --ulti-line: rgba(238, 240, 246, 0.08); --ulti-glow-a: #5d7bff; --ulti-glow-b: #a86bff; --ulti-glow-c: #2cc8dc; --ulti-card-glass: rgba(30, 30, 33, 0.96); --ulti-card-border: rgba(255, 255, 255, 0.1); --ulti-card-highlight: rgba(255, 255, 255, 0.06); --ulti-card-backdrop: blur(12px); --ulti-text: #e8eaed; --ulti-text-strong: #ffffff; --ulti-text-muted: #bdc1c6; --ulti-link: #8ab4f8; --ulti-input-bg: rgba(0, 0, 0, 0.25); --ulti-input-border: rgba(255, 255, 255, 0.14); --ulti-scrollbar-thumb: color-mix(in srgb, var(--ulti-text-muted) 50%, transparent); --ulti-scrollbar-thumb-hover: color-mix(in srgb, var(--ulti-text-muted) 70%, transparent); --ak-accent: var(--ulti-scrollbar-thumb); --ulti-btn-primary-bg: #18181b; --ulti-btn-primary-fg: var(--ulti-text-strong); --ulti-btn-primary-bg-hover: #242428; --ulti-btn-primary-border-width: 1px; --ulti-btn-primary-border: rgba(255, 255, 255, 0.32); --ulti-btn-primary-border-hover: rgba(255, 255, 255, 0.44); --ulti-btn-primary-shadow: none; --ulti-btn-primary-shadow-hover: none; --ulti-btn-primary-ring: color-mix(in srgb, var(--ulti-text-muted) 42%, transparent); --ulti-link-ui: color-mix(in srgb, var(--ulti-text-muted) 92%, var(--ulti-text)); --ulti-link-ui-hover: var(--ulti-text-strong); } } /* Scrollbars — Authentik défaut utilise var(--ak-accent) corail sur le thumb. */ html { scrollbar-width: thin; scrollbar-color: var(--ulti-scrollbar-thumb) transparent; } ::-webkit-scrollbar { width: 8px; height: 8px; background-color: transparent; } ::-webkit-scrollbar-thumb { background-color: var(--ulti-scrollbar-thumb); border-radius: 9999px; } ::-webkit-scrollbar-thumb:hover { background-color: var(--ulti-scrollbar-thumb-hover); } ::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background-color: transparent; } /* =========================================================================== * 1. FOND — remplace la photo de route Authentik par l'aurore UltiSuite * ======================================================================== */ html, body { background: var(--ulti-bg) !important; overflow-x: hidden; min-height: 100dvh; } /* PatternFly laisse .pf-c-background-image à hauteur 0 en mode stacked — on la fixe * en plein écran pour que l'aurore / la grille soient visibles. */ .pf-c-background-image { position: fixed; inset: 0; z-index: 0; width: 100%; height: 100%; min-height: 100dvh; overflow: hidden; pointer-events: none; background-color: var(--ulti-bg) !important; background-image: radial-gradient( 40rem 36rem at 18% 8%, color-mix(in oklab, var(--ulti-glow-a) 60%, transparent), transparent 58% ), radial-gradient( 36rem 34rem at 84% 6%, color-mix(in oklab, var(--ulti-glow-b) 55%, transparent), transparent 60% ), radial-gradient( 40rem 36rem at 50% 104%, color-mix(in oklab, var(--ulti-glow-c) 55%, transparent), transparent 60% ), radial-gradient( 60% 50% at 50% 42%, color-mix(in oklab, var(--ulti-glow-a) 14%, transparent), transparent 70% ) !important; background-repeat: no-repeat !important; background-size: cover !important; filter: none !important; animation: ulti-aurora-drift 28s ease-in-out infinite alternate; } /* Orbe flottante A (cf. .ultimail-login-orb--a) */ .pf-c-background-image::before { content: ""; position: absolute; z-index: 0; width: 40rem; height: 40rem; top: -16rem; left: -12rem; border-radius: 9999px; pointer-events: none; background: radial-gradient( circle at 30% 30%, color-mix(in oklab, var(--ulti-glow-a) 85%, transparent), transparent 65% ); filter: blur(90px); opacity: 0.5; will-change: transform; animation: ulti-orb-drift-a 26s ease-in-out infinite alternate; } @media (prefers-color-scheme: dark) { .pf-c-background-image::before { opacity: 0.42; } } @media (max-width: 639px) { .pf-c-background-image::before { width: 28rem; height: 28rem; top: -10rem; left: -8rem; filter: blur(70px); } .pf-c-background-image { background-image: radial-gradient( 120% 80% at 10% 0%, color-mix(in oklab, var(--ulti-glow-a) 55%, transparent), transparent 55% ), radial-gradient( 100% 70% at 95% 8%, color-mix(in oklab, var(--ulti-glow-b) 50%, transparent), transparent 58% ), radial-gradient( 120% 80% at 50% 100%, color-mix(in oklab, var(--ulti-glow-c) 50%, transparent), transparent 60% ), radial-gradient( 90% 60% at 50% 45%, color-mix(in oklab, var(--ulti-glow-a) 16%, transparent), transparent 72% ) !important; } } /* Les filtres SVG / images PatternFly du fond ne servent plus. */ .pf-c-background-image > * { display: none !important; } /* Grille fine masquée par un dégradé radial (cf. .ultimail-login-backdrop). */ .pf-c-background-image::after { content: ""; position: absolute; z-index: 1; inset: 0; pointer-events: none; background-image: linear-gradient(to right, var(--ulti-line) 1px, transparent 1px), linear-gradient(to bottom, var(--ulti-line) 1px, transparent 1px); background-size: 56px 56px; -webkit-mask-image: radial-gradient( ellipse 80% 70% at 50% 42%, black 28%, transparent 80% ); mask-image: radial-gradient( ellipse 80% 70% at 50% 42%, black 28%, transparent 80% ); } /* =========================================================================== * 2. MISE EN PAGE — carte centrée, chrome transparent devant le fond fixe * ======================================================================== */ .pf-c-page__drawer, .pf-c-drawer, .pf-c-drawer__main, .pf-c-drawer__content, .pf-c-drawer__body { position: relative; z-index: 1; background: transparent !important; } .pf-c-login.stacked { box-sizing: border-box; width: 100%; min-height: 100dvh !important; display: flex !important; flex-direction: column !important; align-items: center !important; justify-content: center !important; padding: max(1rem, env(safe-area-inset-top)) 1rem max(1rem, env(safe-area-inset-bottom)) !important; } .pf-c-login.stacked .ak-login-container { width: 100%; max-width: min(26rem, 100%); margin-inline: auto; flex: 0 1 auto; display: flex; flex-direction: column; justify-content: center; } .pf-c-login__main { position: relative; isolation: isolate; box-sizing: border-box; width: 100%; max-width: 100%; /* visible : le hover du bouton (translateY + ombre) ne doit pas être rogné */ overflow: visible; padding: 1.5rem 2rem 1.25rem !important; border-radius: 2.25rem !important; background: var(--ulti-card-glass) !important; border: 1px solid var(--ulti-card-border) !important; box-shadow: inset 0 1px 0 var(--ulti-card-highlight), 0 16px 44px -16px rgba(0, 0, 0, 0.28) !important; -webkit-backdrop-filter: var(--ulti-card-backdrop, blur(16px) saturate(1.2)); backdrop-filter: var(--ulti-card-backdrop, blur(16px) saturate(1.2)); } /* Anneau arc-en-ciel confiné au bord via masque (padding ring). */ .pf-c-login__main::before { content: ""; position: absolute; inset: 0; z-index: 3; border-radius: inherit; padding: 2.5px; background: var(--ulti-rainbow); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; pointer-events: none; animation: ulti-ring-spin 9s linear infinite; } /* Logo UltiSuite (header executor) — variante thème via content:url(). */ .pf-c-login__main-header.pf-c-brand, .ak-brand { padding-top: 0.25rem !important; padding-bottom: 0.75rem !important; margin-bottom: 0 !important; } .pf-c-login__main-header.pf-c-brand img, .ak-brand img, .pf-c-brand img { max-height: 52px; width: auto; max-width: min(280px, 78vw); content: url("/auth/static/dist/assets/branding/ultisuite-logo-light.png"); } @media (prefers-color-scheme: dark) { .pf-c-login__main-header.pf-c-brand img, .ak-brand img, .pf-c-brand img { content: url("/auth/static/dist/assets/branding/ultisuite-logo-dark.png"); } } /* =========================================================================== * 3. TITRE + DESCRIPTION DE L'ÉTAPE * ======================================================================== */ .pf-c-login__main-body, .pf-c-login__main-header { background: transparent !important; } /* Titre d'étape (identification, mot de passe, etc.) — pas le bandeau logo */ .pf-c-login__main-header:not(.pf-c-brand):not(.ak-brand) { padding: 0 0 1rem !important; margin: 0 !important; } .pf-c-title { text-align: center; color: var(--ulti-text-strong) !important; font-weight: 600 !important; margin: 0 !important; line-height: 1.35 !important; } .pf-c-title.pf-m-3xl { font-size: 1.125rem !important; } /* Bandeau utilisateur (avatar + « Pas vous ? ») sur l'étape mot de passe */ .pf-c-login__main-body .pf-c-login__main-header, .pf-c-form .pf-c-login__main-header { padding: 0 0 1rem !important; } /* =========================================================================== * 4. FORMULAIRE — labels, champs (.pf-c-form-control) * ======================================================================== */ .pf-c-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 0.75rem; row-gap: 0; align-items: center; } .pf-c-form > ak-form-static, .pf-c-form > input, .pf-c-form > ak-flow-input-password, .pf-c-form > ak-form-element, .pf-c-form > .pf-c-form__group:not(.pf-m-action), .pf-c-form > p { grid-column: 1 / -1; } /* Mot de passe oublié + bouton : même ligne, lien à gauche / bouton à droite */ .pf-c-form > a:has(+ .pf-c-form__group.pf-m-action) { grid-column: 1; justify-self: start; align-self: center; margin: 0.175rem 0 0.25rem !important; } .pf-c-form > a + .pf-c-form__group.pf-m-action { grid-column: 2; justify-self: end; align-self: center; margin: 0.175rem 0 0.25rem !important; } /* Bouton seul (sans lien juste avant) */ .pf-c-form > .pf-c-form__group.pf-m-action { grid-column: 2; margin: 0.175rem 0 0.25rem !important; } .pf-c-form__group { margin-bottom: 0.5rem !important; } /* Liens auxiliaires (mot de passe oublié, « Pas vous ? », inscription…) */ .pf-c-login__main a, .pf-c-form a, ak-form-static a { color: var(--ulti-link-ui) !important; font-size: 0.8125rem; font-weight: 500; text-decoration: underline; text-underline-offset: 0.15em; transition: color 0.18s ease; } .pf-c-login__main a:hover, .pf-c-form a:hover, ak-form-static a:hover { color: var(--ulti-link-ui-hover) !important; } .pf-c-form__group.pf-m-action { margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; overflow: visible !important; display: var(--ulti-action-group-display, block); justify-content: var(--ulti-action-group-justify, normal); } .pf-c-login__main-body { padding: 0 !important; overflow: visible !important; } .pf-c-form__label-text { color: var(--ulti-text-muted) !important; font-size: 0.8rem; font-weight: 500; } .pf-c-form__label-required { color: var(--ulti-link) !important; } .pf-c-form-control { height: 2.6rem; padding: 0 0.85rem !important; font-size: 0.9rem !important; color: var(--ulti-text) !important; background: var(--ulti-input-bg) !important; border: 1px solid var(--ulti-input-border) !important; border-radius: 0.6rem !important; box-shadow: none !important; transition: border-color 0.18s ease, box-shadow 0.18s ease; } .pf-c-form-control:hover { border-color: color-mix(in srgb, var(--ulti-link) 45%, var(--ulti-input-border)) !important; } .pf-c-form-control:focus, .pf-c-form-control:focus-visible { border-color: var(--ulti-link) !important; box-shadow: 0 0 0 3px color-mix(in srgb, var(--ulti-link) 25%, transparent) !important; outline: none !important; } /* =========================================================================== * 4b. TEXTES D'AIDE / DESCRIPTION D'ÉTAPE * ----------------------------------------------------------------------------- * Les étapes prompt/identification injectent des paragraphes bruts dans le * corps (description de l'étape, suffixe de domaine "@ultisuite.fr", aide de * champ). Sans règle ils héritent de la couleur PatternFly par défaut — peu * lisible en sombre. On les aligne sur le texte atténué partagé. * (Recovery : description "Enter the email…". Enrollment : "@ultisuite.fr".) * ======================================================================== */ .pf-c-login__main-body > p, .pf-c-form > p, .pf-c-form__helper-text { color: var(--ulti-text-muted) !important; font-size: 0.85rem; line-height: 1.45; } /* Suffixe de domaine d'enrollment : rapproché du champ e-mail qu'il complète. */ .pf-c-form > p { margin-top: -0.35rem !important; margin-bottom: 0.125rem !important; } /* =========================================================================== * 4c. INSCRIPTION (ulti-enrollment) — e-mail suffixé, mots de passe * ======================================================================== */ ak-flow-executor[flowslug="ulti-enrollment"] ak-form-element:has(input[name="password"]).pf-c-form__group, ak-flow-executor[flowslug="ulti-enrollment"] ak-form-element:has(input[name="password"]) .pf-c-form__group { margin-bottom: 0.175rem !important; } ak-flow-executor[flowslug="ulti-enrollment"] .ulti-password-strength { grid-column: 1 / -1; margin: 0.125rem 0 0.075rem !important; } ak-flow-executor[flowslug="ulti-enrollment"] ak-form-element:has(input[name="password_repeat"]).pf-c-form__group, ak-flow-executor[flowslug="ulti-enrollment"] ak-form-element:has(input[name="password_repeat"]) .pf-c-form__group { margin-bottom: 0.25rem !important; } ak-flow-executor[flowslug="ulti-enrollment"] .ulti-password-match { grid-column: 1 / -1; margin: 0.075rem 0 0.175rem !important; } ak-flow-executor[flowslug="ulti-enrollment"] .ulti-email-availability { grid-column: 1 / -1; margin: 0.075rem 0 0.175rem !important; font-size: 0.75rem; line-height: 1.4; } .ulti-email-availability.muted, .ulti-email-availability.checking { color: var(--ulti-text-muted) !important; } .ulti-email-availability.ok { color: #10b981 !important; } .ulti-email-availability.bad { color: #ef4444 !important; } .pf-c-button.pf-m-primary:disabled, .pf-c-button.pf-m-primary[disabled] { opacity: 0.55; cursor: not-allowed; } .ulti-email-input-group { display: flex; align-items: stretch; width: 100%; } .ulti-email-input-group input[name="username"] { flex: 1 1 auto; min-width: 0; border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; border-right: none !important; } .ulti-email-suffix { display: flex; align-items: center; flex: 0 0 auto; padding: 0 0.75rem; border: 1px solid var(--ulti-input-border); border-left: none; border-radius: 0 0.375rem 0.375rem 0; background: color-mix(in srgb, var(--ulti-input-bg) 90%, var(--ulti-text-muted)); color: var(--ulti-text-muted); font-size: 0.9375rem; white-space: nowrap; user-select: none; } .ulti-password-wrap { position: relative; width: 100%; } .ulti-password-input { width: 100%; padding-right: 2.5rem !important; } .ulti-password-toggle { position: absolute; top: 0; right: 0; bottom: 0; width: 2.5rem; display: inline-flex; align-items: center; justify-content: center; margin: 0; padding: 0; border: none; background: transparent; color: var(--ulti-text-muted); cursor: pointer; border-radius: 0 0.375rem 0.375rem 0; transition: color 0.15s ease; } .ulti-password-toggle:hover { color: var(--ulti-text-strong); } .ulti-password-toggle:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ulti-btn-primary-ring); } .ulti-password-strength-bars { display: flex; gap: 0.25rem; } .ulti-password-strength-bars span { flex: 1; height: 0.25rem; border-radius: 999px; background: color-mix(in srgb, var(--ulti-text-muted) 22%, transparent); transition: background-color 0.15s ease; } .ulti-password-strength-bars span.active.weak { background: #ef4444; } .ulti-password-strength-bars span.active.fair { background: #f59e0b; } .ulti-password-strength-bars span.active.good { background: #10b981; } .ulti-password-strength-bars span.active.strong { background: #059669; } .ulti-password-strength-label { margin: 0.175rem 0 0 !important; font-size: 0.75rem; color: var(--ulti-text-muted) !important; } .ulti-password-strength-label strong { color: var(--ulti-text-strong); font-weight: 600; } .ulti-password-match { font-size: 0.75rem; } .ulti-password-match.ok { color: #10b981 !important; } .ulti-password-match.bad { color: #ef4444 !important; } /* =========================================================================== * 5. BOUTONS PRIMAIRES — gris neutre, bordure 2px * ======================================================================== */ ak-flow-executor[flowslug="default-authentication-flow"], ak-flow-executor[flowslug="ulti-enrollment"], ak-flow-executor[flowslug="ulti-recovery"] { --ulti-action-group-display: flex; --ulti-action-group-justify: flex-end; --ulti-primary-btn-width: auto; --ulti-primary-btn-height: 2.625rem; --ulti-primary-btn-min-height: 2.625rem; --ulti-primary-btn-padding: 0 1rem; --ulti-primary-btn-radius: 0.6rem; --ulti-primary-btn-font-size: 0.9375rem; --ulti-primary-btn-weight: 600; } .pf-c-button.pf-m-primary { display: var(--ulti-primary-btn-display, inline-flex); align-items: center; justify-content: center; box-sizing: border-box; width: var(--ulti-primary-btn-width, auto); height: var(--ulti-primary-btn-height, auto); min-height: var(--ulti-primary-btn-min-height, 2.25rem); margin: 0 !important; padding: var(--ulti-primary-btn-padding, 0.4375rem 0.875rem) !important; border: var(--ulti-btn-primary-border-width, 2px) solid var(--ulti-btn-primary-border, transparent) !important; border-radius: var(--ulti-primary-btn-radius, 0.375rem) !important; font-size: var(--ulti-primary-btn-font-size, 0.9375rem) !important; font-weight: var(--ulti-primary-btn-weight, 600) !important; line-height: 1 !important; letter-spacing: normal; color: var(--ulti-btn-primary-fg) !important; text-shadow: none; background-color: var(--ulti-btn-primary-bg) !important; background-image: none !important; box-shadow: var(--ulti-btn-primary-shadow, none) !important; transition: background-color 0.18s ease, border-color 0.18s ease, opacity 0.15s ease; } .pf-c-button.pf-m-primary:hover { background-color: var(--ulti-btn-primary-bg-hover) !important; border-color: var(--ulti-btn-primary-border-hover) !important; } .pf-c-button.pf-m-primary:active { opacity: 0.94; } .pf-c-button.pf-m-primary:focus-visible { outline: none !important; border-color: var(--ulti-btn-primary-border-hover) !important; box-shadow: 0 0 0 3px var(--ulti-btn-primary-ring) !important; } .pf-c-form__group.pf-m-action .pf-c-button.pf-m-primary { width: var(--ulti-primary-btn-width, 100%) !important; max-width: 100%; } /* Overlay de chargement Authentik (après « Continuer ») — aligné sur la carte. */ ak-loading-overlay { position: absolute !important; inset: 0 !important; top: 0 !important; left: 0 !important; width: 100% !important; height: 100% !important; margin: 0 !important; border-radius: inherit !important; background: color-mix(in srgb, var(--ulti-card-glass) 82%, transparent) !important; -webkit-backdrop-filter: blur(6px) saturate(1.2); backdrop-filter: blur(6px) saturate(1.2); display: flex !important; align-items: center !important; justify-content: center !important; z-index: 10; } ak-loading-overlay .pf-c-empty-state { padding: 0 !important; background: transparent !important; } ak-loading-overlay .pf-c-spinner { --pf-c-spinner--Color: var(--ulti-link); } /* =========================================================================== * 6. PIED DE CARTE — bande "Créer un compte" / liens auxiliaires * ======================================================================== */ .pf-c-login__main-footer { background: transparent !important; } .pf-c-login__main-footer-band { margin-top: 0.5rem !important; padding: 0.875rem 0 0.25rem !important; background: transparent !important; border: 0 !important; text-align: center; } /* Liens auxiliaires (mot de passe oublié, inscription, etc.) */ .pf-c-login__main-footer-links { margin: 0.15rem 0 0 !important; padding: 0 !important; list-style: none !important; display: flex; flex-direction: column; align-items: flex-end; gap: 0.15rem; } .pf-c-login__main-footer-links li { margin: 0 !important; padding: 0 !important; } .pf-c-login__main-footer-band-item { color: var(--ulti-text-muted) !important; font-size: 0.85rem; } /* =========================================================================== * 7. MASQUAGE DU BRANDING AUTHENTIK * ======================================================================== */ .pf-c-login__footer, ak-branding-footer, .pf-c-login__footer-text, a[href*="goauthentik.io"], a[href*="authentik.io"] { display: none !important; visibility: hidden !important; height: 0 !important; overflow: hidden !important; } ak-flow-executor::part(footer) { display: none !important; } /* =========================================================================== * 8. MODE EMBARQUÉ — surfaces Authentik intégrées en iframe dans UltiSuite * ----------------------------------------------------------------------------- * Deux familles de surfaces sont embarquées dans le panneau « réglages » * d'UltiSuite (chrome Authentik masqué → seul le panneau utile reste visible) : * * A) La SPA user-settings : `/auth/if/user/#/settings;{"page":""}` * Hôtes : → (shadow) * → (shadow) → (shadow) . * Pages deep-linkables via le hash (ex. `#/settings;{"page":"page-mfa"}`) : * • MFA / authentificateurs : page-mfa → * • Sessions actives : page-sessions → * (autres : page-details, page-consents, page-sources, page-tokens) * * B) Les flows de configuration MFA, ouverts en plein écran depuis le menu * « Enroll » de la page MFA (configure flow → ) : * • default-authenticator-totp-setup * • default-authenticator-webauthn-setup * • default-authenticator-static-setup * • default-password-change (bouton « Change password », page-details) * • ulti-post-migration-security (blueprint 04 — sécuriser le compte) * * HYPOTHÈSE DE SCOPING (assumée, cf. brief) : la SPA user-settings n'est JAMAIS * montrée en standalone aux utilisateurs finaux — uniquement embarquée dans * UltiSuite. On dépouille donc son chrome INCONDITIONNELLEMENT, mais en scopant * aux hôtes de l'INTERFACE UTILISATEUR (`ak-interface-user-presentation`, * `ak-user-settings`, `ak-user-*-list/mfa`) afin de NE PAS toucher : * - l'interface ADMIN (`if/admin`, hôtes `ak-interface-admin*`) ; * - les FLOWS de login/signup/recovery (carte + branding conservés). * Les flows de config MFA listés en B) ne sont atteints QUE depuis les réglages * (le login garde son slug `default-authentication-flow`) → strip sûr. * * NOTE Firefox : la règle 8.3 (masquage de la nav d'onglets) repose sur * `:host-context()`, non implémenté par Firefox. Cibles principales (Chrome, * Edge, WebView Android, WKWebView/WebKitGTK de Tauri) OK ; sous Firefox la * barre d'onglets verticale resterait visible (dégradation, pas de casse). * ======================================================================== */ /* ---- 8.1 SPA : masquage du chrome global (header, fond, marges) --------- */ /* Hôte = (porte le shadow contenant header * + fond + drawer). Scope strict : n'atteint pas l'admin ni les flows. */ :host(ak-interface-user-presentation) .pf-c-page__header, :host(ak-interface-user-presentation) .background-wrapper { display: none !important; } :host(ak-interface-user-presentation) .pf-c-page, :host(ak-interface-user-presentation) .pf-c-page__drawer, :host(ak-interface-user-presentation) .pf-c-drawer, :host(ak-interface-user-presentation) .pf-c-drawer__main, :host(ak-interface-user-presentation) .pf-c-drawer__content, :host(ak-interface-user-presentation) .pf-c-drawer__body { background: transparent !important; } :host(ak-interface-user-presentation) .pf-c-page__main { margin: 0 !important; padding: 0 !important; } /* ---- 8.2 SPA : page de réglages à plat (transparente, sans marges) ------ */ :host(ak-user-settings) .pf-c-page, :host(ak-user-settings) .pf-c-page__main { background: transparent !important; padding: 0 !important; margin: 0 !important; } :host(ak-user-settings) .pf-c-page__main-section { padding: 0 !important; background: transparent !important; } /* La carte qui enveloppe chaque panneau (MFA / sessions) devient le panneau * UltiSuite lui-même : fond/ombre/bordure retirés pour fondre dans l'iframe. */ :host(ak-user-settings) .pf-c-card { background: transparent !important; box-shadow: none !important; border: 0 !important; border-radius: 0 !important; } :host(ak-user-settings) .pf-c-card__body { padding: 0 !important; } /* ---- 8.3 SPA : masquage de la barre d'onglets verticale (cf. NOTE) ------ */ /* est générique (réutilisé par l'admin) : on le restreint au seul * réglage utilisateur via :host-context(ak-user-settings). Le panneau actif * (slot page-*) reste affiché ; seule la nav latérale disparaît. */ :host-context(ak-user-settings) .pf-c-tabs.pf-m-vertical { display: none !important; } /* ---- 8.4 SPA : look UltiSuite des listes MFA & sessions ----------------- */ /* Scopé aux hôtes propres à l'interface utilisateur (jamais en admin/flows). */ :host(ak-user-settings-mfa) .pf-c-table, :host(ak-user-session-list) .pf-c-table { background: transparent !important; color: var(--ulti-text) !important; } :host(ak-user-settings-mfa) .pf-c-table th, :host(ak-user-settings-mfa) .pf-c-table td, :host(ak-user-session-list) .pf-c-table th, :host(ak-user-session-list) .pf-c-table td { color: var(--ulti-text) !important; border-color: var(--ulti-line) !important; } :host(ak-user-settings-mfa) .pf-c-table th, :host(ak-user-session-list) .pf-c-table th { color: var(--ulti-text-muted) !important; } :host(ak-user-settings-mfa) .pf-c-toolbar, :host(ak-user-session-list) .pf-c-toolbar { background: transparent !important; padding-inline: 0 !important; } /* Boutons réglages / MFA */ :host(ak-user-settings-mfa) .pf-c-dropdown__toggle.pf-m-primary, :host(ak-user-settings) .pf-c-button.pf-m-primary, :host(ak-user-settings-mfa) .pf-c-button.pf-m-primary, :host(ak-user-session-list) .pf-c-button.pf-m-primary { border-radius: 0.375rem !important; padding: 0.4375rem 0.875rem !important; } :host(ak-user-settings-mfa) .pf-c-dropdown__toggle.pf-m-primary { border: 0 !important; } /* ---- 8.5 Flows de configuration MFA / sécurité : chrome dépouillé ------- */ /* Mêmes effets que l'ancien stub, appliqués aux VRAIS slugs embarqués. */ :host([flowslug="default-authenticator-totp-setup"]) .pf-c-background-image, :host([flowslug="default-authenticator-totp-setup"]) .pf-c-login__footer, :host([flowslug="default-authenticator-totp-setup"]) .pf-c-login__main-header.pf-c-brand, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-background-image, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-login__footer, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-login__main-header.pf-c-brand, :host([flowslug="default-authenticator-static-setup"]) .pf-c-background-image, :host([flowslug="default-authenticator-static-setup"]) .pf-c-login__footer, :host([flowslug="default-authenticator-static-setup"]) .pf-c-login__main-header.pf-c-brand, :host([flowslug="default-password-change"]) .pf-c-background-image, :host([flowslug="default-password-change"]) .pf-c-login__footer, :host([flowslug="default-password-change"]) .pf-c-login__main-header.pf-c-brand, :host([flowslug="ulti-post-migration-security"]) .pf-c-background-image, :host([flowslug="ulti-post-migration-security"]) .pf-c-login__footer, :host([flowslug="ulti-post-migration-security"]) .pf-c-login__main-header.pf-c-brand { display: none !important; } :host([flowslug="default-authenticator-totp-setup"]) .pf-c-login.stacked, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-login.stacked, :host([flowslug="default-authenticator-static-setup"]) .pf-c-login.stacked, :host([flowslug="default-password-change"]) .pf-c-login.stacked, :host([flowslug="ulti-post-migration-security"]) .pf-c-login.stacked { background: transparent !important; } :host([flowslug="default-authenticator-totp-setup"]) .pf-c-login.stacked .ak-login-container, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-login.stacked .ak-login-container, :host([flowslug="default-authenticator-static-setup"]) .pf-c-login.stacked .ak-login-container, :host([flowslug="default-password-change"]) .pf-c-login.stacked .ak-login-container, :host([flowslug="ulti-post-migration-security"]) .pf-c-login.stacked .ak-login-container { max-width: none !important; margin: 0 !important; } :host([flowslug="default-authenticator-totp-setup"]) .pf-c-login__main, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-login__main, :host([flowslug="default-authenticator-static-setup"]) .pf-c-login__main, :host([flowslug="default-password-change"]) .pf-c-login__main, :host([flowslug="ulti-post-migration-security"]) .pf-c-login__main { max-width: none !important; padding: 0 !important; border: 0 !important; border-radius: 0 !important; background: transparent !important; box-shadow: none !important; -webkit-backdrop-filter: none; backdrop-filter: none; } :host([flowslug="default-authenticator-totp-setup"]) .pf-c-login__main::before, :host([flowslug="default-authenticator-webauthn-setup"]) .pf-c-login__main::before, :host([flowslug="default-authenticator-static-setup"]) .pf-c-login__main::before, :host([flowslug="default-password-change"]) .pf-c-login__main::before, :host([flowslug="ulti-post-migration-security"]) .pf-c-login__main::before { display: none !important; } /* =========================================================================== * 9. ANIMATIONS / ACCESSIBILITÉ * ======================================================================== */ @keyframes ulti-ring-spin { to { --ulti-ring-angle: 505deg; } } @keyframes ulti-aurora-drift { from { background-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%; } to { background-size: 112% 108%, 108% 112%, 110% 105%, 106% 104%; } } @keyframes ulti-orb-drift-a { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(6rem, 4rem, 0) scale(1.12); } } /* Évite le rognage du bouton / ombre de carte par les conteneurs PatternFly */ .pf-c-login.stacked, .pf-c-login.stacked .ak-login-container, .pf-c-page__drawer .pf-c-drawer__body, .pf-c-page__drawer .pf-c-drawer__content { overflow: visible !important; } @media (max-width: 639px) { .pf-c-login__main { padding: 1.25rem 1.25rem 1rem !important; border-radius: 1.75rem !important; } .pf-c-login__main-header.pf-c-brand img, .ak-brand img, .pf-c-brand img { max-height: 44px; max-width: min(240px, 72vw); } .pf-c-title.pf-m-3xl { font-size: 1.05rem !important; } .pf-c-form-control { height: 2.75rem; font-size: 16px !important; /* évite le zoom iOS */ } ak-flow-executor[flowslug="default-authentication-flow"], ak-flow-executor[flowslug="ulti-enrollment"], ak-flow-executor[flowslug="ulti-recovery"] { --ulti-primary-btn-height: 2.625rem; --ulti-primary-btn-min-height: 2.625rem; } } @media (prefers-reduced-motion: reduce) { .pf-c-background-image, .pf-c-background-image::before { animation: none !important; } .pf-c-login__main::before { animation: none !important; } }