/* ── Collegeuur — Keycloak login theme ────────────────────────────────────────
   Restyles Keycloak's sign-in, registration, password-reset and error screens
   to match the application's design system.

   Keycloak serves these pages from its own container — it cannot import
   `apps/web/app/styles/tokens.css`, so the tokens below are transcribed from
   it. **If the design tokens change, change them here too**; nothing ties the
   two together at build time.

   Loaded last in theme.properties so these rules win over PatternFly and the
   base login.css. Selectors are doubled up (`.pf-c-*` alongside the older
   PatternFly 3 names) because which family Keycloak emits varies by screen and
   by version. */

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap");

:root {
  /* Transcribed from app/styles/tokens.css — dark is the signature theme. */
  --violet-300: #a99af5;
  --violet-400: #8b7cf0;
  --violet-500: #7a68eb;
  --violet-600: #6d5ae6;
  --violet-700: #5a46d1;

  --bg-canvas: #0e0e10;
  --bg-surface: #16161a;
  --bg-raised: #1b1b20;
  --bg-input: #111113;
  --bg-inset: rgba(0, 0, 0, 0.25);

  --border: rgba(255, 255, 255, 0.09);
  --border-strong: rgba(255, 255, 255, 0.16);
  --border-input: rgba(255, 255, 255, 0.13);

  --text: #ececf1;
  --text-strong: #ffffff;
  --text-muted: #9a9aa8;
  --text-subtle: #6e6e7c;
  --text-link: var(--violet-300);

  --accent: var(--violet-600);
  --accent-hover: var(--violet-500);
  --focus-ring: var(--violet-400);

  /* Used by the hero: the accent gradient and two of the three auroras. */
  --teal-500: #2eb8ac;
  --blue-500: #4c8df6;
  --dv-grid: rgba(255, 255, 255, 0.045);

  --danger-bg: rgba(229, 72, 77, 0.1);
  --danger-bd: rgba(229, 72, 77, 0.3);
  --danger-fg: #f09296;
  --warn-bg: rgba(232, 163, 61, 0.1);
  --warn-bd: rgba(232, 163, 61, 0.3);
  --warn-fg: #f4c77a;
  --success-bg: rgba(63, 185, 80, 0.1);
  --success-bd: rgba(63, 185, 80, 0.28);
  --success-fg: #7fd68c;
  --info-bg: rgba(76, 141, 246, 0.1);
  --info-bd: rgba(76, 141, 246, 0.28);
  --info-fg: #9bc0fa;

  --font-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 20px;
  --sh-4: 0 8px 16px rgba(0, 0, 0, 0.36), 0 24px 56px rgba(0, 0, 0, 0.46);
  --highlight-top: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* The operating-system preference is the fallback, used when no theme cookie
   was sent — a first visit, or a deployment where the app and Keycloak are not
   on the same host. `resources/js/theme.js` sets `data-theme` from the cookie
   when it can, and the rule below that one wins over this. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg-canvas: #f7f7f9;
    --bg-surface: #ffffff;
    --bg-raised: #ffffff;
    --bg-input: #ffffff;
    --bg-inset: #f2f2f5;

    --border: rgba(10, 10, 11, 0.1);
    --border-strong: rgba(10, 10, 11, 0.18);
    --border-input: rgba(10, 10, 11, 0.16);

    --text: #1b1b20;
    --text-strong: #0a0a0b;
    --text-muted: #5e5e6b;
    --text-subtle: #86868f;
    --text-link: var(--violet-700);

    --danger-bg: #feeeee;  --danger-bd: #f8d2d3;  --danger-fg: #9b2226;
    --warn-bg: #fef6e9;    --warn-bd: #f6e2bf;    --warn-fg: #8a5b12;
    --success-bg: #eaf7ec; --success-bd: #c5e9cc; --success-fg: #1b6b2a;
    --info-bg: #edf4fe;    --info-bd: #cadefb;    --info-fg: #1f55ae;

    --sh-4: 0 4px 12px rgba(16, 18, 30, 0.1), 0 24px 48px rgba(16, 18, 30, 0.12);
    --highlight-top: none;
  }
}

/* The app's own choice, carried across in the cookie, overrides the OS. */
:root[data-theme="light"] {
  --bg-canvas: #f7f7f9;
  --bg-surface: #ffffff;
  --bg-raised: #ffffff;
  --bg-input: #ffffff;
  --bg-inset: #f2f2f5;

  --border: rgba(10, 10, 11, 0.1);
  --border-strong: rgba(10, 10, 11, 0.18);
  --border-input: rgba(10, 10, 11, 0.16);

  --text: #1b1b20;
  --text-strong: #0a0a0b;
  --text-muted: #5e5e6b;
  --text-subtle: #86868f;
  --text-link: var(--violet-700);

  --danger-bg: #feeeee;  --danger-bd: #f8d2d3;  --danger-fg: #9b2226;
  --warn-bg: #fef6e9;    --warn-bd: #f6e2bf;    --warn-fg: #8a5b12;
  --success-bg: #eaf7ec; --success-bd: #c5e9cc; --success-fg: #1b6b2a;
  --info-bg: #edf4fe;    --info-bd: #cadefb;    --info-fg: #1f55ae;

  --sh-4: 0 4px 12px rgba(16, 18, 30, 0.1), 0 24px 48px rgba(16, 18, 30, 0.12);
  --highlight-top: none;
  --dv-grid: rgba(10, 10, 11, 0.05);
}

/* The aurora is tuned for a dark canvas; on light it reads as a smudge. */
:root[data-theme="light"] .login-pf-page::before,
:root[data-theme="light"] .login-pf body::before {
  opacity: 0.55;
}

/* ── Canvas ──────────────────────────────────────────────────────────────────
   PatternFly paints a dark hero image across the page. Replace it with the
   app's canvas plus the landing page's aurora wash, so arriving here from the
   sign-in button does not feel like leaving the product. */
html,
body.login-pf,
.login-pf body {
  background: var(--bg-canvas);
}
.login-pf-page {
  position: relative;
  isolation: isolate;
  background: var(--bg-canvas);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 0.875rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  padding-top: 9vh;
  padding-bottom: 8vh;
  min-height: 100vh;
}
.login-pf body::before,
.login-pf-page::before {
  content: "" !important;
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(60rem 40rem at 15% -10%, rgba(109, 90, 230, 0.22), transparent 60%),
    radial-gradient(48rem 34rem at 95% 10%, rgba(46, 184, 172, 0.14), transparent 60%);
  pointer-events: none;
}

/* ── Brand header ────────────────────────────────────────────────────────────
   Keycloak prints the realm's display name here, and the realm is named
   "Collegeuur" — so this is the wordmark, not a deployment artefact, and it is
   dressed to match `.brand` in the application's own header.

   The mark and the tagline are drawn with generated content because the base
   theme's `#kc-header-wrapper` holds a bare text node and nothing else.
   Overriding `template.ftl` to add real elements would pin this theme to one
   Keycloak version's markup; this does not. */
#kc-header {
  width: min(100%, 440px);
  margin: 0 auto 18px;
  padding: 0;
}
#kc-header-wrapper {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  justify-items: start;
  column-gap: 10px;
  padding: 0;
  /* The base theme centres this; the brand reads as a left-aligned lockup. */
  text-align: left;
  color: var(--text-strong);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.014em;
  line-height: 1.2;
  text-transform: none;
  white-space: normal;
}
/* The violet rounded square with the sparkle, as `.brand-mark` draws it. The
   glyph is the design system's `sparkle` icon, verbatim. A background image
   cannot resolve `currentColor`, so the stroke is written out as white — which
   is what it is on this tile in both themes. */
#kc-header-wrapper::before {
  content: "";
  grid-row: 1 / 3;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 3 1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9Z'/%3E%3Cpath d='M18.5 16.5 19 18l1.5.5L19 19l-.5 1.5L18 19l-1.5-.5L18 18Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 20px 20px;
  box-shadow: 0 2px 10px rgba(109, 90, 230, 0.35);
}
/* `brand.tagline`. Generated content cannot read the message bundle, so the
   translation hangs off the `lang` attribute Keycloak sets on <html>. */
#kc-header-wrapper::after {
  content: "Declarations for higher education";
  grid-column: 2;
  color: var(--text-subtle);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0;
}
html[lang="nl"] #kc-header-wrapper::after {
  content: "Declaraties voor het hoger onderwijs";
}

/* ── The card ────────────────────────────────────────────────────────────────
   Matches `.signin` on the application's own landing page. */
.login-pf-page .card-pf,
.login-pf-page .pf-c-card {
  width: min(100%, 440px);
  margin: 0 auto;
  padding: 32px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-4), var(--highlight-top);
}

#kc-content-wrapper {
  margin-top: 0;
}
/* Keycloak wraps the title in a Bootstrap `.col-md-10`, which indents it and
   centres the text inside a card that is already the right width. Undo the
   grid rather than fight it. */
.login-pf-page .login-pf-header,
.login-pf-page .login-pf-header > div,
.login-pf-page [class^="col-md-"],
.login-pf-page [class*=" col-md-"],
.login-pf-page [class^="col-sm-"],
.login-pf-page [class*=" col-sm-"] {
  width: 100%;
  max-width: none;
  padding-left: 0;
  padding-right: 0;
  float: none;
  text-align: left;
}
/* PatternFly's `.form-horizontal .form-group` carries `margin: 0 -20px` to
   cancel a grid gutter this card does not use, so every field sat 20px to the
   left of the title above it. */
.login-pf-page .card-pf .row,
.login-pf-page .form-group,
.login-pf-page #kc-form,
.login-pf-page #kc-form-wrapper {
  margin-left: 0;
  margin-right: 0;
}
#kc-page-title {
  margin: 0 0 20px;
  font-family: var(--font-sans);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.28;
  letter-spacing: -0.021em;
  color: var(--text-strong);
  text-align: left;
}
/* The "* Required fields" note Keycloak prints above the title. */
.login-pf-page .required,
.login-pf-page #kc-registration-required-fields,
.login-pf-page .pf-c-form__label-required {
  color: var(--danger-fg);
}
.login-pf-page .subtitle {
  margin: 0 0 6px;
  color: var(--text-subtle);
  font-size: 0.75rem;
  text-align: left;
}

/* Shown on the "confirm your account" screens. */
#kc-username {
  margin-bottom: 16px;
  color: var(--text-muted);
  font-size: 0.8125rem;
}
#kc-username a {
  color: var(--text-link);
}

/* ── Form fields ─────────────────────────────────────────────────────────── */
/* `inline-block`, not `block`: Keycloak renders the required marker as a
   *sibling* `<span class="required">*</span>` after the label, so a block label
   pushes the asterisk onto a line of its own. */
.login-pf-page label,
.login-pf-page .control-label,
.login-pf-page .pf-c-form__label,
.login-pf-page .pf-c-form__label-text {
  display: inline-block;
  margin-bottom: 6px;
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: -0.012em;
}
/* …and the field itself then has to start a new line. */
.login-pf-page .form-group > input,
.login-pf-page .form-group > select,
.login-pf-page .pf-c-form__group-control {
  display: block;
  clear: both;
}

.login-pf-page input[type="text"],
.login-pf-page input[type="email"],
.login-pf-page input[type="password"],
.login-pf-page input[type="tel"],
.login-pf-page input[type="number"],
.login-pf-page select,
.login-pf-page .form-control,
.login-pf-page .pf-c-form-control {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  background: var(--bg-input);
  border: 1px solid var(--border-input);
  border-radius: var(--r-md);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 0.875rem;
  box-shadow: none;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.login-pf-page input::placeholder {
  color: var(--text-subtle);
}
.login-pf-page input:focus,
.login-pf-page select:focus,
.login-pf-page .form-control:focus,
.login-pf-page .pf-c-form-control:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(109, 90, 230, 0.22);
}
/* Newer PatternFly styles the field through custom properties rather than
   ordinary declarations, so the plain rules above never reach it. */
.login-pf-page .pf-c-form-control {
  --pf-c-form-control--BorderBottomColor: var(--border-input);
  --pf-c-form-control--BackgroundColor: var(--bg-input);
  --pf-c-form-control--Color: var(--text);
}

.login-pf-page .form-group,
.login-pf-page .pf-c-form__group {
  margin-bottom: 16px;
}

/* The mail and lock glyphs the design puts inside the field, drawn as the
   design system's `mail` and `lock` icons.

   One neutral grey serves both themes: a background image cannot inherit
   `currentColor`, and the app's own two values (#6e6e7c on dark, #86868f on
   light) are close enough that a single mid-grey reads correctly on the dark
   and the white input alike. The 34px inset matches `.input-group .input`. */
.login-pf-page #username,
.login-pf-page #email,
.login-pf-page #password,
.login-pf-page #password-confirm,
.login-pf-page #password-new {
  padding-left: 34px;
  background-repeat: no-repeat;
  background-position: 11px center;
  background-size: 17px 17px;
}
.login-pf-page #username,
.login-pf-page #email {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a96' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2.5' y='5' width='19' height='14' rx='2.5'/%3E%3Cpath d='m3.5 7 8.5 6 8.5-6'/%3E%3C/svg%3E");
}
.login-pf-page #password,
.login-pf-page #password-confirm,
.login-pf-page #password-new {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a96' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4.5' y='10' width='15' height='10.5' rx='2'/%3E%3Cpath d='M8 10V7.5a4 4 0 0 1 8 0V10'/%3E%3C/svg%3E");
}
/* On the sign-in form `#username` *is* the email address, so the envelope is
   right there. On the registration form it is a separate username beside its
   own email field, so that one takes the `user` glyph instead. */
.login-pf-page #kc-register-form #username {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a8a96' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21v-1a6 6 0 0 1 6-6h4a6 6 0 0 1 6 6v1'/%3E%3C/svg%3E");
}

/* The show/hide password toggle Keycloak renders beside the field.

   Field and toggle have to read as one control, so the field gives up the two
   corners where they meet and the toggle gives up the border between them —
   otherwise the field's 10px radius leaves a notch against the toggle's flat
   edge. */
.login-pf-page .pf-c-input-group,
.login-pf-page .pf-c-input-group__item {
  background: transparent;
  border: 0;
}
.login-pf-page .pf-c-input-group > .pf-c-form-control,
.login-pf-page .pf-c-input-group > input {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.login-pf-page .pf-c-button.pf-m-control {
  flex: none;
  min-height: 40px;
  padding: 0 12px;
  background: transparent;
  border: 1px solid var(--border-input);
  border-left: 0;
  border-radius: 0 var(--r-md) var(--r-md) 0;
  color: var(--text-subtle);
  transition: border-color 120ms ease;
}
/* …which also means the toggle picks up the focus border, rather than leaving
   the control lit down one half only. */
@supports selector(:has(*)) {
  .login-pf-page .pf-c-input-group:has(input:focus) .pf-c-button.pf-m-control {
    border-color: var(--accent);
  }
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.login-pf-page .btn-primary,
.login-pf-page .pf-c-button.pf-m-primary,
.login-pf-page input[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  padding: 0 18px;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.012em;
  text-shadow: none;
  box-shadow: 0 2px 10px rgba(109, 90, 230, 0.35);
  transition: background 120ms ease, transform 120ms ease;
}
.login-pf-page .btn-primary:hover,
.login-pf-page .pf-c-button.pf-m-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}
.login-pf-page .btn-primary:active,
.login-pf-page .pf-c-button.pf-m-primary:active {
  transform: translateY(1px);
}

.login-pf-page .btn-default,
.login-pf-page .pf-c-button.pf-m-secondary {
  min-height: 40px;
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text);
  font-weight: 500;
}

.login-pf-page a {
  color: var(--text-link);
  text-decoration: none;
}
.login-pf-page a:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

:where(.login-pf-page) :focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ── Remember me / forgot password row ───────────────────────────────────── */
#kc-form-options,
.login-pf-page .login-pf-settings {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  font-size: 0.8125rem;
  color: var(--text-muted);
}
#kc-form-options .checkbox label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  color: var(--text-muted);
  font-size: 0.8125rem;
  font-weight: 400;
}
#kc-form-options input[type="checkbox"] {
  width: auto;
  height: auto;
  accent-color: var(--accent);
}

/* ── The info area under the form ────────────────────────────────────────────
   On the sign-in screen this holds the "Create an account" button; on
   verify-email and reset-password it holds a sentence.

   The base theme treats it as a footer band: `#kc-info` carries
   `margin: 20px -40px -30px` to bleed past the card's padding, and
   `#kc-info-wrapper` paints grey behind it. This card has no such band, so the
   three nested wrappers are flattened to the width of the form above them.
   They must not be narrowed or centred independently — anything that boxes
   them leaves the button a different width from, and off-centre to, the Sign
   in button it pairs with. */
#kc-info {
  width: 100%;
  max-width: none;
  /* Collapses with the submit button's `.form-group` margin, so the two
     buttons sit exactly one field-gap apart. */
  margin: 16px 0 0;
  padding: 0;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--text-muted);
}
#kc-info-wrapper,
#kc-registration-container,
#kc-registration {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  font-size: inherit;
  color: inherit;
}

/* The second action on the card. login.ftl renders it as a button rather than
   PatternFly's "New user? Register" sentence, so the anchor is styled as the
   secondary button it now is — the same box as the Sign in button above it,
   which is the whole point of the pair. Keep the metrics in step with
   `.btn-primary` above. */
#cu-register-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: 0 18px;
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.012em;
  transition: border-color 120ms ease, background 120ms ease, transform 120ms ease;
}
#cu-register-btn:hover {
  border-color: var(--accent);
  text-decoration: none;
}
#cu-register-btn:active {
  transform: translateY(1px);
}

/* The way back to the application on the terminal message screens (info.ftl).
   `.btn-primary` above already draws the box; this only keeps the generic link
   rules from treating it as a sentence, and lifts it clear of the message. */
#cu-app-btn {
  margin-top: 8px;
}
#cu-app-btn,
#cu-app-btn:hover {
  color: #fff;
  text-decoration: none;
}

/* ── Create an account ───────────────────────────────────────────────────── */
/* The line under the title explaining what the form leads to. */
.cu-form-sub {
  margin: -8px 0 20px;
  color: var(--text-muted);
  font-size: 0.8125rem;
  line-height: 1.55;
}

/* First and last name are short and belong together, so they share a row —
   the pairing the design uses wherever two narrow fields sit side by side.
   `:has()` because the field order comes from the realm's user profile, not
   from the template, so there is no class to hang this on. */
@supports selector(:has(*)) {
  #kc-register-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 12px;
  }
  #kc-register-form > * {
    grid-column: 1 / -1;
    min-width: 0;
  }
  #kc-register-form > .form-group:has(#firstName) {
    grid-column: 1 / 2;
  }
  #kc-register-form > .form-group:has(#lastName) {
    grid-column: 2 / 3;
  }
}

/* "Back to sign in", now under the submit button rather than above it.
   `justify-content`, not `text-align`: this is the same `#kc-form-options`
   flex row the sign-in card uses for remember-me / forgot-password. */
#kc-form-options.cu-form-back {
  justify-content: center;
  margin-top: 14px;
  margin-bottom: 0;
  font-size: 0.8125rem;
}

/* The required-fields note, now under the title rather than above it. */
.login-pf-page .subtitle {
  margin: -12px 0 18px;
}

/* ── Alerts ──────────────────────────────────────────────────────────────── */
.login-pf-page .alert,
.login-pf-page .pf-c-alert {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 18px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-inset);
  color: var(--text);
  font-size: 0.8125rem;
  box-shadow: none;
}
.login-pf-page .alert-error,
.login-pf-page .pf-m-danger {
  background: var(--danger-bg);
  border-color: var(--danger-bd);
  color: var(--danger-fg);
}
.login-pf-page .alert-warning,
.login-pf-page .pf-m-warning {
  background: var(--warn-bg);
  border-color: var(--warn-bd);
  color: var(--warn-fg);
}
.login-pf-page .alert-success,
.login-pf-page .pf-m-success {
  background: var(--success-bg);
  border-color: var(--success-bd);
  color: var(--success-fg);
}
.login-pf-page .alert-info,
.login-pf-page .pf-m-info {
  background: var(--info-bg);
  border-color: var(--info-bd);
  color: var(--info-fg);
}

/* Per-field validation text under an input. */
.login-pf-page .pf-c-form__helper-text.pf-m-error,
.login-pf-page #input-error,
.login-pf-page .kcInputErrorMessageClass {
  display: block;
  margin-top: 6px;
  color: var(--danger-fg);
  font-size: 0.75rem;
}
.login-pf-page .has-error input,
.login-pf-page .pf-m-error .pf-c-form-control {
  border-color: var(--danger-bd);
}

/* ── Language picker ─────────────────────────────────────────────────────── */
#kc-locale {
  width: min(100%, 440px);
  margin: 0 auto 8px;
  text-align: right;
}
#kc-locale-dropdown a,
#kc-current-locale-link {
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
#kc-locale ul {
  padding: 4px;
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  box-shadow: var(--sh-4);
}
#kc-locale ul li a {
  display: block;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  color: var(--text);
  text-transform: none;
  letter-spacing: 0;
}
#kc-locale ul li a:hover {
  background: rgba(255, 255, 255, 0.05);
  text-decoration: none;
}

/* ── Social / identity-provider buttons ──────────────────────────────────── */
#kc-social-providers ul {
  display: grid;
  gap: 8px;
  padding: 0;
  margin: 18px 0 0;
  list-style: none;
}
#kc-social-providers li a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 40px;
  background: var(--bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text);
  font-size: 0.875rem;
}
#kc-social-providers li a:hover {
  text-decoration: none;
  border-color: var(--accent);
}

@media (max-width: 520px) {
  .login-pf-page {
    padding-top: 5vh;
  }
  .login-pf-page .card-pf,
  .login-pf-page .pf-c-card {
    padding: 24px 20px;
    border-radius: var(--r-lg);
  }
}

/* ══ The welcome page, on the sign-in screen ═════════════════════════════════
   Rendered by template.ftl when `pageId` is `login.ftl`. Everything below is
   scoped to `[data-cu-landing]` so registration, password reset and the error
   screens keep the plain centred card.

   Values are transcribed from apps/web/app/styles/{auth,animations}.css. The
   spacing and type scales are not available here, so they are written out. */

[data-cu-landing] .login-pf-page {
  /* The header and hero own the vertical rhythm on this page. */
  padding-top: 0;
  padding-bottom: 0;
}
/* The realm display name, replaced by the brand lockup in the top bar. */
[data-cu-landing] #kc-header {
  display: none;
}

/* ── Top bar ─────────────────────────────────────────────────────────────── */
.cu-top {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 16px;
  height: 60px;
  padding: 0 24px;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--border);
}
.cu-grow {
  flex: 1 1 auto;
}
.cu-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.cu-brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  box-shadow: 0 2px 10px rgba(109, 90, 230, 0.35);
}
.cu-brand-mark svg {
  width: 20px;
  height: 20px;
}
.cu-brand-mark-sm {
  width: 22px;
  height: 22px;
  border-radius: 6px;
}
.cu-brand-mark-sm svg {
  width: 13px;
  height: 13px;
}
.cu-brand-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.cu-brand-name {
  color: var(--text-strong);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.014em;
  line-height: 1.2;
}
.cu-brand-sub {
  color: var(--text-subtle);
  font-size: 0.75rem;
  line-height: 1.3;
}

/* EN / NL, as the application's own toggle draws it. */
.cu-lang {
  display: inline-flex;
  flex: none;
  padding: 2px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.cu-lang a {
  padding: 3px 9px;
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.cu-lang a:hover {
  text-decoration: none;
  color: var(--text);
}
.cu-lang a[aria-current="true"] {
  background: var(--accent);
  color: #fff;
}
.cu-theme-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 32px;
  height: 32px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 8px;
  color: var(--text-muted);
  cursor: pointer;
}
.cu-theme-btn:hover {
  background: var(--bg-inset);
  color: var(--text);
}
.cu-theme-btn svg {
  width: 17px;
  height: 17px;
}

/* ── Hero ────────────────────────────────────────────────────────────────── */
.cu-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 80px 24px 64px;
}
.cu-hero-inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(340px, 0.85fr);
  gap: 64px;
  align-items: center;
  max-width: 1440px;
  margin: 0 auto;
}
.cu-hero-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--dv-grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--dv-grid) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(ellipse 78% 62% at 50% 34%, #000 30%, transparent 78%);
  mask-image: radial-gradient(ellipse 78% 62% at 50% 34%, #000 30%, transparent 78%);
}
.cu-aurora {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  border-radius: 50%;
  filter: blur(78px);
  opacity: 0.5;
}
:root[data-theme="light"] .cu-aurora {
  opacity: 0.34;
}
.cu-aurora-a { width: 460px; height: 460px; background: var(--violet-600); top: -140px; left: -80px; }
.cu-aurora-b { width: 380px; height: 380px; background: var(--teal-500); top: 120px; right: 8%; }
.cu-aurora-c { width: 300px; height: 300px; background: var(--blue-500); bottom: -120px; left: 34%; }

.cu-eyebrow {
  margin: 0;
  color: var(--text-subtle);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.cu-h1 {
  margin: 12px 0 0;
  color: var(--text-strong);
  font-size: clamp(2.25rem, 5.2vw, 3.25rem);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.cu-accent {
  background: linear-gradient(96deg, var(--violet-400), var(--teal-500) 68%, var(--blue-500));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.cu-hero-body {
  max-width: 54ch;
  margin: 20px 0 0;
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1.6;
  text-wrap: pretty;
}
.cu-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.cu-stat-value {
  color: var(--text-strong);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.021em;
  font-variant-numeric: tabular-nums;
}
.cu-stat-label {
  margin-top: 2px;
  color: var(--text-subtle);
  font-size: 0.75rem;
}

/* The column holding Keycloak's card. The card keeps its own styling; this
   only stops `margin: 0 auto` from centring it inside a column narrower than
   its 440px maximum. */
.cu-signin-col {
  min-width: 0;
}
[data-cu-landing] .login-pf-page .card-pf,
[data-cu-landing] .login-pf-page .pf-c-card {
  /* Fills its grid column, as `.signin` does in the design — PatternFly's own
     500px cap would otherwise leave it floating inside the column. */
  width: 100%;
  max-width: none;
  margin: 0;
}

/* ── Features ────────────────────────────────────────────────────────────── */
.cu-features {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 24px 48px;
}
.cu-features .cu-card {
  padding: 24px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
}
.cu-feat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  margin-bottom: 16px;
  border-radius: 10px;
  background: rgba(109, 90, 230, 0.12);
  border: 1px solid rgba(109, 90, 230, 0.22);
  color: var(--violet-300);
}
:root[data-theme="light"] .cu-feat-icon {
  color: var(--violet-700);
}
.cu-feat-icon svg {
  width: 19px;
  height: 19px;
}
.cu-feat-title {
  margin: 0 0 8px;
  color: var(--text-strong);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.014em;
}
.cu-feat-body {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.8125rem;
  line-height: 1.55;
  text-wrap: pretty;
}

/* ── Footer ──────────────────────────────────────────────────────────────── */
.cu-foot {
  border-top: 1px solid var(--border);
}
.cu-foot-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  max-width: 1440px;
  margin: 0 auto;
  padding: 20px 24px;
  color: var(--text-subtle);
  font-size: 0.75rem;
}
.cu-foot-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* ── Narrow ──────────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  .cu-hero-inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
  }
  .cu-hero {
    padding: 40px 20px 40px;
  }
  .cu-features {
    grid-template-columns: minmax(0, 1fr);
    padding-bottom: 32px;
  }
  .cu-brand-sub {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .login-pf-page * {
    transition: none !important;
    animation: none !important;
  }
}
