/* Fiscus Keycloak login theme.
 *
 * Loaded after the stock `css/login.css`, so equal-specificity rules here win by
 * source order — that is how the PatternFly defaults get replaced below.
 *
 * Colours mirror the nuxt-bff design tokens (app/assets/css/root.css). They are
 * written as hex rather than oklch() so the login page has no dependency on
 * colour-space support, and are converted from the same source values, e.g.
 * --brand oklch(0.4 0.045 164) == #304F41. Keep the two in sync.
 */

:root {
  --fx-bg: #FAF8F6;
  --fx-surface: #FFFFFF;
  --fx-surface-muted: #F6F3F0;
  --fx-fg: #13161A;
  --fx-fg-soft: #343A40;
  --fx-fg-muted: #52585F;
  --fx-border: #E7E4E1;
  --fx-border-strong: #CDCAC6;

  --fx-brand: #304F41;
  --fx-brand-hover: #233F32;
  --fx-on-brand: #FFFFFF;
  --fx-gold: #D3AE3F;

  --fx-link: #0072D5;
  --fx-link-hover: #0061CE;

  --fx-danger: #E7000B;
  --fx-danger-soft: #FFE8E3;
  --fx-success: #0F7A4E;
  --fx-success-soft: #DEFAE6;
  --fx-warning: #8A5A0B;
  --fx-warning-soft: #FFF0CC;
  --fx-info: #2867E4;
  --fx-info-soft: #E0F4FF;

  --fx-ring: #304F41;
  --fx-ring-shadow: 0 0 0 3px rgba(48, 79, 65, 0.18);
  --fx-shadow: 0 4px 12px -2px rgba(28, 24, 20, 0.10), 0 2px 6px -2px rgba(28, 24, 20, 0.06);
  /* Brand hue 164, but lighter and more chromatic than --brand (#304F41).
   * A dark green at burst alpha over the warm off-white leaves only ~5% chroma
   * — it reads as grey haze, not as a colour. This is the same move root.css
   * already makes for dark mode (#43D39E): same hue, different lightness.
   * oklch(0.62 0.13 164) == #0C9E71. */
  --fx-glow-a: rgba(12, 158, 113, 0.32);
  --fx-glow-a-soft: rgba(12, 158, 113, 0.13);
  --fx-glow-b: rgba(211, 174, 63, 0.40);
  --fx-glow-b-soft: rgba(211, 174, 63, 0.17);

  --fx-logo: url(../img/logo.svg);
  --fx-radius: 12px;
  --fx-radius-sm: 8px;
}

/* The app ships both themes; follow the OS so Keycloak does not flash a bright
 * page at someone who is already using Fiscus in dark mode. */
@media (prefers-color-scheme: dark) {
  :root {
    --fx-bg: #161310;
    --fx-surface: #221F1B;
    --fx-surface-muted: #2B2825;
    --fx-fg: #E8EAED;
    --fx-fg-soft: #C9CDD2;
    --fx-fg-muted: #94A3B8;
    --fx-border: #36322E;
    --fx-border-strong: #4B4742;

    --fx-brand: #43D39E;
    --fx-brand-hover: #33A57A;
    --fx-on-brand: #13161A;
    --fx-gold: #DEB95C;

    --fx-link: #4BA3F7;
    --fx-link-hover: #6AB3FD;

    --fx-danger: #FB2C36;
    --fx-danger-soft: #3B1C19;
    --fx-success: #3FBF86;
    --fx-success-soft: #0D2E1D;
    --fx-warning: #EBA941;
    --fx-warning-soft: #2E220B;
    --fx-info: #719DEF;
    --fx-info-soft: #192437;

    --fx-ring: #43D39E;
    --fx-ring-shadow: 0 0 0 3px rgba(67, 211, 158, 0.25);
    --fx-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.60), 0 2px 8px -2px rgba(0, 0, 0, 0.45);
    --fx-glow-a: rgba(67, 211, 158, 0.32);
    --fx-glow-a-soft: rgba(67, 211, 158, 0.13);
    --fx-glow-b: rgba(222, 185, 92, 0.26);
    --fx-glow-b-soft: rgba(222, 185, 92, 0.11);

    --fx-logo: url(../img/logo-dark.svg);
  }
}

/* ── Page shell ─────────────────────────────────────────────────────────── */

/* PatternFly puts its stock grey-polygon photo on BOTH the html element and the
 * body (`background: #030303 url(../img/bg-login.jpg)`), so both need clearing. */
.login-pf,
.login-pf body {
  background-image: none;
}

/* The page colour lives on html, and body stays transparent on purpose. A
 * background on body paints in the same stacking context as the glow layers but
 * later in the order, so an opaque body would hide every `z-index: -1` layer
 * behind it. */
.login-pf {
  background-color: var(--fx-bg);
}

.login-pf body {
  background-color: transparent;
  /* `Golos Text` matches nuxt-bff and is used when the visitor already has it;
   * the login page deliberately loads no external webfont. */
  font-family: 'Golos Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
  color: var(--fx-fg);
}

/* ── Background: a very blurred, slow-motion firework ──────────────────────
 *
 * Ten bursts in the brand green and gold, scattered across the viewport. Each
 * one grows out of a point at a constant rate, brightens and fades, then lies
 * dark for the rest of its cycle — so bursts read as separate events rather
 * than as one continuous pulse.
 *
 * Every burst is filled at the centre: the gradient runs from the core colour
 * outwards, never from `transparent`, so none of them read as a ring.
 *
 * Three size tiers run at once — small bursts stay local while the large ones
 * sweep most of the screen — which is what keeps the background from reading as
 * one repeated shape. Larger bursts are given longer cycles, because covering
 * more ground in the same time would read as moving faster.
 *
 * Peak opacity is kept low (~0.5) on purpose: with bursts this large, that is
 * what stops the background pulling the eye off the form.
 *
 * The blur comes from the gradient stops themselves, not from `filter: blur()`.
 * A radial gradient *is* the blur of a point, and it costs nothing; a real blur
 * filter on a layer that is simultaneously being scaled forces Chrome to
 * re-rasterise it every frame.
 *
 * Only `transform` and `opacity` animate — both are composited, so the
 * animation never triggers layout or paint and cannot compete with typing in
 * the form. (The theme this replaced animated `background-position` on a
 * full-page gradient, which repaints the whole page every frame.)
 *
 * Cycles run 26–44s, are mutually unrelated, and the negative delays scatter
 * the bursts in time, so the show never visibly loops. `position: fixed` keeps
 * the layers out of the scrollable overflow, so they cannot widen the page on
 * a phone.
 *
 * The layers hang off html, body, the page wrapper, the header and the content
 * box — the only elements every Keycloak login template is guaranteed to have.
 */

.login-pf::after,
#kc-content::before,
#kc-header::after,
.login-pf::before,
.login-pf-page::before,
.login-pf body::before,
#kc-header::before,
.login-pf body::after,
.login-pf-page::after,
#kc-content::after {
  content: "";
  position: fixed;
  z-index: -1;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
}

/* Content sits in its own stacking context above every burst. */
.login-pf-page {
  position: relative;
  z-index: 1;
}

/* large  — top-right */
.login-pf::after {
  top: 12vh;
  right: 8vw;
  width: 32vmax;
  height: 32vmax;
  background: radial-gradient(closest-side, var(--fx-glow-b) 0%, var(--fx-glow-b-soft) 44%, transparent 90%);
  animation: fxBurstLarge 44s linear -10s infinite;
}

/* large  — bottom-centre */
#kc-content::before {
  bottom: -4vh;
  left: 44vw;
  width: 29vmax;
  height: 29vmax;
  background: radial-gradient(closest-side, var(--fx-glow-a) 0%, var(--fx-glow-a-soft) 44%, transparent 90%);
  animation: fxBurstLarge 42s linear -7s infinite;
}

/* large  — mid-left */
#kc-header::after {
  top: 30vh;
  left: -6vw;
  width: 25vmax;
  height: 25vmax;
  background: radial-gradient(closest-side, var(--fx-glow-b) 0%, var(--fx-glow-b-soft) 44%, transparent 90%);
  animation: fxBurstLarge 40s linear -29s infinite;
}

/* medium — top-left */
.login-pf::before {
  top: 4vh;
  left: 6vw;
  width: 30vmax;
  height: 30vmax;
  background: radial-gradient(closest-side, var(--fx-glow-a) 0%, var(--fx-glow-a-soft) 44%, transparent 90%);
  animation: fxBurstMedium 34s linear -4s infinite;
}

/* medium — bottom-left */
.login-pf-page::before {
  bottom: 8vh;
  left: 14vw;
  width: 28vmax;
  height: 28vmax;
  background: radial-gradient(closest-side, var(--fx-glow-a) 0%, var(--fx-glow-a-soft) 44%, transparent 90%);
  animation: fxBurstMedium 36s linear -26s infinite;
}

/* medium — mid-right */
.login-pf body::before {
  top: 46vh;
  left: 62vw;
  width: 26vmax;
  height: 26vmax;
  background: radial-gradient(closest-side, var(--fx-glow-b) 0%, var(--fx-glow-b-soft) 44%, transparent 90%);
  animation: fxBurstMedium 38s linear -18s infinite;
}

/* small  — top-centre */
#kc-header::before {
  top: -6vh;
  left: 38vw;
  width: 27vmax;
  height: 27vmax;
  background: radial-gradient(closest-side, var(--fx-glow-a) 0%, var(--fx-glow-a-soft) 44%, transparent 90%);
  animation: fxBurstSmall 26s linear -12s infinite;
}

/* small  — bottom-right */
.login-pf body::after {
  bottom: 18vh;
  right: 16vw;
  width: 26vmax;
  height: 26vmax;
  background: radial-gradient(closest-side, var(--fx-glow-a) 0%, var(--fx-glow-a-soft) 44%, transparent 90%);
  animation: fxBurstSmall 28s linear -22s infinite;
}

/* small  — lower-left */
.login-pf-page::after {
  top: 62vh;
  left: 2vw;
  width: 24vmax;
  height: 24vmax;
  background: radial-gradient(closest-side, var(--fx-glow-b) 0%, var(--fx-glow-b-soft) 44%, transparent 90%);
  animation: fxBurstSmall 30s linear -34s infinite;
}

/* small  — right-edge */
#kc-content::after {
  top: 24vh;
  right: -4vw;
  width: 23vmax;
  height: 23vmax;
  background: radial-gradient(closest-side, var(--fx-glow-b) 0%, var(--fx-glow-b-soft) 44%, transparent 90%);
  animation: fxBurstSmall 32s linear -37s infinite;
}

/* `transform` is declared only at the ends of the burst, so with `linear` timing
 * the layer expands at a genuinely constant rate — no flare at the start, no
 * deceleration at the end. `opacity` carries its own stops in between; CSS
 * interpolates each property independently between the keyframes that declare
 * it, so the extra opacity stops do not break the even expansion.
 *
 * The hold to 100% is the dark gap before the next burst. Opacity is already 0
 * there, so the loop back to the small scale is never visible. */
@keyframes fxBurstSmall {
  0% { transform: scale(0.35); opacity: 0; }
  34% { opacity: 0.52; }
  62% { transform: scale(1.1); opacity: 0; }
  100% { transform: scale(1.1); opacity: 0; }
}

@keyframes fxBurstMedium {
  0% { transform: scale(0.4); opacity: 0; }
  35% { opacity: 0.5; }
  64% { transform: scale(1.75); opacity: 0; }
  100% { transform: scale(1.75); opacity: 0; }
}

@keyframes fxBurstLarge {
  0% { transform: scale(0.45); opacity: 0; }
  36% { opacity: 0.48; }
  66% { transform: scale(2.5); opacity: 0; }
  100% { transform: scale(2.5); opacity: 0; }
}

/* Motion is pure decoration here; when the OS asks for less of it the layers
 * hold a still composition instead of disappearing entirely. */
@media (prefers-reduced-motion: reduce) {
  .login-pf::after,
  #kc-content::before,
  #kc-header::after,
  .login-pf::before,
  .login-pf-page::before,
  .login-pf body::before,
  #kc-header::before,
  .login-pf body::after,
  .login-pf-page::after,
  #kc-content::after {
    animation: none;
    transform: scale(1);
    opacity: 0.3;
  }
}

/* ── Header / logo ──────────────────────────────────────────────────────── */

#kc-header {
  color: var(--fx-fg);
  white-space: nowrap;
}

/* Also the fallback rendering: if `displayNameHtml` is ever cleared, the realm
 * display name lands here as plain text and must still look intentional. */
#kc-header-wrapper {
  padding: 48px 16px 28px;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.2;
  text-transform: none;
  color: var(--fx-fg);
  white-space: normal;
}

/* Rendered from the realm's `displayNameHtml`, which is
 * `<div class="kc-logo-text"><span>Fiscus</span></div>`. The span stays in the
 * DOM as the accessible name and is hidden by the parent theme. */
div.kc-logo-text {
  width: 208px;
  height: 58px;
  margin: 0 auto;
  background-image: var(--fx-logo);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

div.kc-logo-text span {
  display: none;
}

/* ── Card ───────────────────────────────────────────────────────────────── */

.card-pf,
.login-pf-page .card-pf {
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
  padding: 28px 28px 28px;
  background: var(--fx-surface);
  /* The stock card has a 4px accent bar on top; a hairline reads calmer. */
  border: 1px solid var(--fx-border);
  border-top: 1px solid var(--fx-border);
  border-radius: var(--fx-radius);
  box-shadow: var(--fx-shadow);
}

.login-pf-page .card-pf header {
  margin-bottom: 4px;
}

/* The header lays its children out as floated Bootstrap columns. */
.login-pf-page .card-pf header::after {
  content: "";
  display: table;
  clear: both;
}

/* `displayRequiredFields` wraps the title in col-md-10, which knocks it off
 * centre and leaves a 2-column gap next to it. */
.login-pf-page .card-pf header .col-md-10 {
  float: none;
  width: 100%;
  padding: 0;
}

#kc-page-title {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  color: var(--fx-fg);
}

/* The stock rule is `margin-top: 30px`, which drops this line on top of the
 * page title instead of above it. */
.subtitle {
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 1.4;
  text-align: right;
  color: var(--fx-fg-muted);
}

.required {
  color: var(--fx-danger);
}

#kc-content-wrapper {
  margin-top: 18px;
}

#kc-form-wrapper {
  margin-top: 0;
}

/* ── Fields ─────────────────────────────────────────────────────────────── */

.pf-c-form__label,
.pf-c-form__label-text,
#kc-form-login label,
#kc-register-form label {
  font-size: 14px;
  font-weight: 500;
  color: var(--fx-fg);
}

.form-group,
.pf-c-form__group {
  margin-bottom: 16px;
}

.pf-c-form-control,
input.pf-c-form-control,
.form-control,
textarea.form-control,
select.form-control {
  height: 44px;
  padding: 10px 14px;
  font-size: 15px;
  color: var(--fx-fg);
  /* `background-color`, not the `background` shorthand: PatternFly layers its
   * state icons on via `background-image` alone and inherits `no-repeat` from
   * its own base rule, so a shorthand here resets the repeat and tiles the
   * invalid-field icon across the whole input. */
  background-color: var(--fx-surface);
  background-repeat: no-repeat;
  border: 1px solid var(--fx-border-strong);
  border-radius: var(--fx-radius-sm);
  box-shadow: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  --pf-c-form-control--BorderBottomColor: var(--fx-border-strong);
}

/* Field state is carried by the border and the message under the input, so the
 * PatternFly status icon is dropped rather than restyled. */
.pf-c-form-control[aria-invalid="true"],
.pf-c-form-control.pf-m-success,
.pf-c-form-control.pf-m-warning {
  padding-right: 14px;
  background-image: none;
}

.pf-c-form-control[aria-invalid="true"] {
  border-color: var(--fx-danger);
}

.pf-c-input-group:has(.pf-c-form-control[aria-invalid="true"]) {
  border-color: var(--fx-danger);
}

.pf-c-form-control::placeholder,
.form-control::placeholder {
  color: var(--fx-fg-muted);
  opacity: 1;
}

/* The password fields wrap the input and the reveal button in an input group;
 * the visible border belongs to the group so the two read as one control. */
.pf-c-input-group {
  overflow: hidden;
  background-color: var(--fx-surface);
  border: 1px solid var(--fx-border-strong);
  border-radius: var(--fx-radius-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.pf-c-input-group .pf-c-form-control,
.pf-c-input-group input {
  border: 0;
  border-radius: 0;
  background: transparent;
}

.pf-c-input-group .pf-c-button.pf-m-control {
  padding: 0 14px;
  color: var(--fx-fg-muted);
  background: transparent;
  border: 0;
}

.pf-c-input-group .pf-c-button.pf-m-control:hover {
  color: var(--fx-fg);
  background: transparent;
}

/* PatternFly paints this button's border with a pseudo-element. */
.pf-c-button.pf-m-control::after {
  display: none;
}

/* Focus has to stay visible — the previous theme removed it outright. */
.pf-c-form-control:focus,
.form-control:focus,
input:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--fx-ring);
  box-shadow: var(--fx-ring-shadow);
}

.pf-c-input-group:focus-within {
  border-color: var(--fx-ring);
  box-shadow: var(--fx-ring-shadow);
}

.pf-c-input-group .pf-c-form-control:focus,
.pf-c-input-group input:focus {
  box-shadow: none;
}

a:focus-visible,
button:focus-visible,
.pf-c-button:focus-visible,
input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--fx-ring);
  outline-offset: 2px;
}

.pf-c-form__helper-text {
  font-size: 13px;
  color: var(--fx-fg-muted);
}

.pf-c-form__helper-text.pf-m-error,
.has-error .pf-c-form__helper-text {
  color: var(--fx-danger);
}

.has-error .pf-c-form-control,
.has-error .pf-c-input-group {
  border-color: var(--fx-danger);
}

/* ── Buttons ────────────────────────────────────────────────────────────── */

.pf-c-button.pf-m-primary,
.btn-primary,
.login-pf-page .btn-primary,
button[type="submit"],
input[type="submit"] {
  width: 100%;
  min-height: 44px;
  padding: 11px 18px;
  font-size: 15px;
  font-weight: 600;
  color: var(--fx-on-brand);
  background-color: var(--fx-brand);
  border: 1px solid var(--fx-brand);
  border-radius: var(--fx-radius-sm);
  box-shadow: none;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pf-c-button.pf-m-primary:hover,
.btn-primary:hover,
button[type="submit"]:hover,
input[type="submit"]:hover {
  color: var(--fx-on-brand);
  background-color: var(--fx-brand-hover);
  border-color: var(--fx-brand-hover);
}

/* The old theme painted these white, which made them invisible on the card. */
.pf-c-button.pf-m-secondary,
.btn-secondary,
a.btn-secondary,
.pf-c-button.pf-m-tertiary {
  min-height: 44px;
  color: var(--fx-fg);
  background-color: transparent;
  border: 1px solid var(--fx-border-strong);
  border-radius: var(--fx-radius-sm);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pf-c-button.pf-m-secondary:hover,
.btn-secondary:hover,
a.btn-secondary:hover {
  color: var(--fx-fg);
  background-color: var(--fx-surface-muted);
  border-color: var(--fx-border-strong);
}

#kc-form-buttons {
  margin-top: 20px;
}

/* ── Links and form options ─────────────────────────────────────────────── */

a {
  color: var(--fx-link);
  text-decoration: none;
  transition: color 0.15s ease;
}

a:hover {
  color: var(--fx-link-hover);
  text-decoration: underline;
}

#kc-form-options,
.login-pf-settings {
  margin-bottom: 4px;
  font-size: 14px;
}

#kc-form-options .checkbox,
.pf-c-check__label {
  font-size: 14px;
  color: var(--fx-fg-muted);
}

#kc-username {
  text-align: center;
}

#kc-attempted-username {
  font-size: 16px;
  font-weight: 500;
  color: var(--fx-fg);
}

/* ── Alerts ─────────────────────────────────────────────────────────────── */

.pf-c-alert {
  align-items: flex-start;
  padding: 12px 14px;
  margin-bottom: 16px;
  border: 1px solid transparent;
  border-radius: var(--fx-radius-sm);
}

/* The stock size is `--pf-global--FontSize--xs`, too small for error text. */
.pf-c-alert__title,
.kc-feedback-text {
  font-size: 14px;
  line-height: 1.45;
  color: inherit;
}

.pf-c-alert.pf-m-danger,
.alert-error {
  color: var(--fx-fg);
  background: var(--fx-danger-soft);
  border-color: var(--fx-danger);
}

.pf-c-alert.pf-m-danger .pf-c-alert__icon {
  color: var(--fx-danger);
}

.pf-c-alert.pf-m-success,
.alert-success {
  color: var(--fx-fg);
  background: var(--fx-success-soft);
  border-color: var(--fx-success);
}

.pf-c-alert.pf-m-success .pf-c-alert__icon {
  color: var(--fx-success);
}

.pf-c-alert.pf-m-warning,
.alert-warning {
  color: var(--fx-fg);
  background: var(--fx-warning-soft);
  border-color: var(--fx-warning);
}

.pf-c-alert.pf-m-warning .pf-c-alert__icon {
  color: var(--fx-warning);
}

.pf-c-alert.pf-m-info,
.alert-info {
  color: var(--fx-fg);
  background: var(--fx-info-soft);
  border-color: var(--fx-info);
}

.pf-c-alert.pf-m-info .pf-c-alert__icon {
  color: var(--fx-info);
}

/* ── Card footer (register prompt / reset instructions) ─────────────────── */

/* Stock is `margin: 20px -40px -30px` against 20px of card padding, so the bar
 * hangs 20px past both card edges — the source of the horizontal overflow on
 * narrow viewports. These offsets match the card padding exactly. */
#kc-info {
  margin: 28px -28px -28px;
}

#kc-info-wrapper {
  padding: 16px 28px;
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  color: var(--fx-fg-muted);
  background: var(--fx-surface-muted);
  border-top: 1px solid var(--fx-border);
  border-radius: 0 0 calc(var(--fx-radius) - 1px) calc(var(--fx-radius) - 1px);
}

.login-pf-page .login-pf-signup {
  font-size: 14px;
  color: var(--fx-fg-muted);
}

#kc-info-wrapper p.instruction {
  margin: 0;
}

/* The way back to the app on info pages (info.ftl) is a link drawn as the primary
 * button; without these the generic `a` rules would underline it on hover and the
 * label would sit at the top of the 44px box. */
#kc-info-action {
  margin: 20px 0 0;
}

a.pf-c-button.pf-m-primary {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

a.pf-c-button.pf-m-primary:hover {
  text-decoration: none;
}

/* ── Split layout: the page fits the viewport ───────────────────────────────
 *
 * Registration is the tallest page in the theme — six fields, the username hint
 * and the submit button — and stacked under a full-width logo it ran to roughly
 * 1010px, so on a 1440x900 window the submit button sat below the fold and the
 * whole page scrolled. Three things buy that back: the page centres itself in
 * one viewport instead of flowing from the top, the logo moves out of the form’s
 * way into the left half from 992px up, and the two natural pairs of fields sit
 * side by side. Registration then lands around 600px and fits a 1280x720 window
 * with room to spare; every other page in the theme is shorter than it.
 *
 * `min-height`, not `height`, and `safe center`, not `center`: a window too short
 * even for this (1024x600, a laptop under a video-call bar) gets an ordinary page
 * scrollbar rather than a card with its top or bottom cut off. Nothing here can
 * clip content — it only removes the scrollbar when there is nothing to scroll.
 *
 * `100dvh` rather than `100vh`: on mobile browsers `vh` is the *largest*
 * viewport, so a `100vh` page is taller than the visible area for as long as the
 * address bar is showing, which would put the scrollbar straight back.
 */

@media (min-width: 768px) {
  .login-pf body {
    margin: 0;
  }

  .login-pf-page {
    display: flex;
    flex-direction: column;
    align-items: safe center;
    justify-content: safe center;
    box-sizing: border-box;
    min-height: 100vh;
    min-height: 100dvh;
    padding: clamp(16px, 4vh, 40px) 24px;
  }

  #kc-header {
    flex: 0 0 auto;
  }

  #kc-header-wrapper {
    padding: 0 0 24px;
  }

  .login-pf-page .card-pf {
    margin: 0;
  }

  /* Tightened only where the viewport is the constraint. The narrow layout below
   * keeps the roomier rhythm — there the page is free to grow. */
  .form-group,
  .pf-c-form__group {
    margin-bottom: 12px;
  }

  #kc-content-wrapper {
    margin-top: 12px;
  }

  #kc-form-buttons {
    margin-top: 14px;
  }

  /* Password/confirm and first/last name are natural pairs, and pairing them is
   * what takes ~160px off registration. `:has()` is the only handle available:
   * Keycloak renders every attribute through one macro, so the groups are
   * identical apart from the input inside them. */
  #kc-register-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 16px;
  }

  #kc-register-form > * {
    grid-column: 1 / -1;
  }

  #kc-register-form > .form-group:has(#password),
  #kc-register-form > .form-group:has(#firstName) {
    grid-column: 1;
  }

  #kc-register-form > .form-group:has(#password-confirm),
  #kc-register-form > .form-group:has(#lastName) {
    grid-column: 2;
  }

  /* Bootstrap gives `.form-horizontal .form-group` a -15px side margin that the
   * `.col-*` children pay back as padding. The two cancel out in a block layout,
   * but as grid items the negative margins would push each field 15px into the
   * column gap and out over the card padding. */
  #kc-register-form > .form-group {
    margin-left: 0;
    margin-right: 0;
  }

  #kc-register-form > .form-group > [class*="col-"] {
    padding-left: 0;
    padding-right: 0;
  }
}

@media (min-width: 992px) {
  .login-pf-page {
    flex-direction: row;
    gap: clamp(32px, 6vw, 96px);
    padding: clamp(20px, 4vh, 48px) clamp(32px, 5vw, 72px);
  }

  /* Two halves meeting in the middle: the logo centred in its own half, the card
   * at its natural width against the gutter. */
  #kc-header {
    display: flex;
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
  }

  #kc-header-wrapper {
    padding: 0;
  }

  /* `aspect-ratio` rather than a second magic number: the box has to keep the
   * wordmark’s 208x58 proportions for `background-size: contain` to fill it. */
  div.kc-logo-text {
    width: clamp(240px, 24vw, 360px);
    height: auto;
    aspect-ratio: 208 / 58;
    margin: 0;
  }

  .login-pf-page .card-pf {
    flex: 0 1 480px;
    max-width: 480px;
  }
}

/* ── Narrow viewports ───────────────────────────────────────────────────── */

@media (max-width: 767px) {
  /* The parent theme drops the page background to plain white here and left-
   * aligns the header; both are undone so the page keeps one identity. The
   * colour goes on html — body must stay transparent or it covers the glows. */
  .login-pf {
    background-color: var(--fx-bg);
  }

  .login-pf body {
    background-color: transparent;
  }

  #kc-header {
    float: none;
    padding: 0 16px;
    text-align: center;
  }

  #kc-header-wrapper {
    padding: 28px 8px 20px;
    font-size: 20px;
    color: var(--fx-fg);
  }

  div.kc-logo-text {
    width: 154px;
    height: 43px;
    margin: 0 auto;
    background-size: contain;
  }

  .login-pf-page .card-pf {
    max-width: 100%;
    margin: 0;
    padding: 24px 20px;
    border: 1px solid var(--fx-border);
    border-radius: var(--fx-radius);
    box-shadow: var(--fx-shadow);
  }

  #kc-info {
    margin: 24px -20px -24px;
  }

  #kc-info-wrapper {
    padding: 14px 20px;
  }

  .login-pf .container {
    padding-bottom: 24px;
  }
}
