/* The Architect — the sign-in.
 *
 * The identity layer is the SYSTEM's, not this page's: the --ha-* scale below is
 * the same brass-on-ink one the hub, the task board and the provisioner console
 * already use, copied token for token from frontend-service's console.css. This
 * is the first page a visitor sees and the only one served by the engine, so a
 * sign-in that invented its own palette would make everything behind it look
 * like a different product.
 *
 * Colour carries one job here:
 *   --ha-brass   INTERACTION. Focus, the button you are about to press.
 *   --ha-danger  A REFUSAL. Nothing else on this page is red.
 *
 * PatternFly is not loaded — theme.properties empties stylesCommon — so every
 * rule here is the whole of what styles the element, and there is no framework
 * specificity to fight.
 */

:root {
  /* Both schemes are first-class; the OS decides. Declaring it makes native
     controls, the password reveal and scrollbars follow instead of rendering
     light chrome on ink. */
  color-scheme: light dark;

  --ha-bg: #eef0f5;
  --ha-panel: #ffffff;
  --ha-panel-2: #f7f8fb;
  --ha-line: #dfe3ec;
  --ha-line-strong: #c6cddd;
  --ha-fg: #141821;
  --ha-muted: #616a83;

  --ha-brass: #9a6a12;
  --ha-brass-tint: rgba(154, 106, 18, .10);
  --ha-signal: #157f4a;
  --ha-signal-tint: rgba(21, 127, 74, .12);
  --ha-danger: #b3261e;
  --ha-danger-tint: rgba(179, 38, 30, .09);

  --ha-shadow: 0 10px 30px rgba(20, 24, 33, .10);

  --ha-sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI",
             Roboto, "Helvetica Neue", Arial, sans-serif;
  --ha-mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono",
             "Cascadia Mono", Menlo, Consolas, monospace;

  --field-h: 40px;

  --radius-sm: 6px;
  --radius-md: 9px;
  --radius-lg: 14px;
  --gut: clamp(14px, 3vw, 28px);
}

@media (prefers-color-scheme: dark) {
  :root {
    --ha-bg: #0f121b;
    --ha-panel: #171c28;
    --ha-panel-2: #1c2230;
    --ha-line: #262d3f;
    --ha-line-strong: #39425c;
    --ha-fg: #e9ebf3;
    --ha-muted: #8d95ad;

    --ha-brass: #e0a950;
    --ha-brass-tint: rgba(224, 169, 80, .13);
    --ha-signal: #6ee7a8;
    --ha-signal-tint: rgba(110, 231, 168, .14);
    --ha-danger: #f0736a;
    --ha-danger-tint: rgba(240, 115, 106, .13);

    --ha-shadow: 0 12px 34px rgba(0, 0, 0, .45);
  }
}

*, *::before, *::after { box-sizing: border-box; }

.ha-html { height: 100%; }

.ha-body {
  margin: 0;
  min-height: 100dvh;
  background: var(--ha-bg);
  color: var(--ha-fg);
  font-family: var(--ha-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
@supports not (height: 100dvh) { .ha-body { min-height: 100vh; } }

/* Centred, holding nothing but the form. There is nowhere to navigate to yet,
   so there is no nav. */
.ha-login {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: var(--gut);
}
@supports not (height: 100dvh) { .ha-login { min-height: 100vh; } }

/* ── the page shell ───────────────────────────────────────────────── */
/*
 * These `pf-v5-c-*` names are NOT PatternFly. keycloak.v2's template.ftl writes
 * them into the markup literally rather than through a theme property, so they
 * cannot be renamed the way the form classes were — MEASURED against the
 * rendered page, which is why the theme styles them by their real names.
 *
 * PatternFly's stylesheet is not loaded (theme.properties empties stylesCommon),
 * so these are inert hooks and every rule below is the whole of what styles the
 * element. Overriding the templates to rename them was the alternative and was
 * rejected: those templates carry every flow this realm can enter, and forking
 * them to change a class name is how the flows nobody tested silently break.
 */

.pf-v5-c-login {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--gut);
}
@supports not (height: 100dvh) { .pf-v5-c-login { min-height: 100vh; } }

.pf-v5-c-login__container {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: min(360px, 100%);
}

.pf-v5-c-login__header, .ha-header { text-align: center; }

/* The brand mark is a background so the header text can stay whatever the realm
   put there — a display name, or HTML — without this file having to render it. */
.pf-v5-c-login__header::before,
.ha-header::before {
  content: "";
  display: block;
  width: 42px;
  height: 42px;
  margin: 0 auto 12px;
  background: url("../img/mark.svg") center / contain no-repeat;
}
.pf-v5-c-brand,
.ha-header-text {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ha-fg);
}
.pf-v5-c-brand a, .ha-header-text a { color: inherit; text-decoration: none; }

/* ── the card ─────────────────────────────────────────────────────── */

.pf-v5-c-login__main,
.ha-card {
  width: 100%;
  padding: 28px;
  background: var(--ha-panel);
  border: 1px solid var(--ha-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--ha-shadow);
}

.pf-v5-c-login__main-header, .ha-form-header { margin: 0 0 18px; }
.pf-v5-c-login__main-header h1,
.pf-v5-c-title,
.ha-form-header h1,
#kc-page-title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ha-fg);
}

.pf-v5-c-login__main-body, .ha-content { display: block; }

/* The footer holds the reset-password and register links. */
.pf-v5-c-login__main-footer {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--ha-line);
  font-size: 13px;
  color: var(--ha-muted);
}
/* The template emits this element with only whitespace in it when there is no
   reset-password or register link — and `:empty` does NOT match whitespace, so
   the first pass drew two rules under the button with nothing between them.
   `:has()` asks the real question: is there anything in here worth a border? */
.pf-v5-c-login__main-footer:not(:has(a, button, input, p, span)) { display: none; }
.pf-v5-c-login__main-footer > *:empty { display: none; }

/* PatternFly form wrappers the template writes literally. */
.pf-v5-c-form__label { display: block; }
.pf-v5-c-form__label-text { font-size: 12px; color: var(--ha-muted); }
.pf-v5-c-form__actions { margin-top: 4px; }
.pf-v5-c-form__helper-text, .pf-v5-c-helper-text { font-size: 12px; color: var(--ha-muted); }
.pf-v5-c-helper-text__item-text[aria-live] { color: var(--ha-danger); }
#kc-form, #kc-form-wrapper { display: block; }

/* ── fields ───────────────────────────────────────────────────────── */
/*
 * THE BOX IS THE SPAN, NOT THE INPUT. keycloak.v2 renders
 * `<span class="ha-input"><input …></span>` and puts the reveal button in a
 * SIBLING element, not inside the field. MEASURED against the rendered page —
 * styling the `<input>` directly left a browser-default control sitting inside
 * a styled wrapper, which is the sort of thing only looking at the output finds.
 */

.ha-form { display: flex; flex-direction: column; gap: 14px; }
.ha-group { display: flex; flex-direction: column; gap: 6px; }

.ha-label,
.ha-group-label label,
.pf-v5-c-form__label-text {
  font-size: 12px;
  color: var(--ha-muted);
}

/* The wrapper span IS the field. */
.ha-input {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  min-height: var(--field-h);
  padding: 0 11px;
  border: 1px solid var(--ha-line-strong);
  border-radius: var(--radius-sm);
  background: var(--ha-panel-2);
  color: var(--ha-fg);
}
/* The real control sits inside it and carries none of the chrome. */
.ha-input > input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: 14px;
  border: 0;
  padding: 0;
  background: none;
  color: inherit;
  outline: none;
}
.ha-input > input::placeholder { color: var(--ha-muted); }
/* The ring goes on the BOX, because the input inside has no border of its own.
   focus-within, so tabbing to the field shows it. */
.ha-input { transition: border-color .12s ease, box-shadow .12s ease; }
/* ONE ring, not a ring plus a recoloured border — at 2px offset the two read as
   a doubled outline, which is what the first pass looked like. */
.ha-input:focus-within {
  border-color: var(--ha-brass);
  box-shadow: 0 0 0 3px var(--ha-brass-tint);
}
/* Keycloak marks a refused field with pf-m-error and aria-invalid. */
.ha-input.pf-m-error,
.ha-input:has(> input[aria-invalid="true"]) { border-color: var(--ha-danger); }

/* An icon slot the engine renders beside a refused value. Hidden: the border
   and the message below already say it, and this slot expects an icon font the
   theme does not load. */
.pf-v5-c-form-control__utilities, .pf-v5-c-form-control__icon { display: none; }

/* The field and its reveal button share a row, and the field takes the rest of
   it. `pf-m-fill` is the engine's marker for "this is the one that grows". */
.ha-input-group,
.pf-v5-c-input-group {
  display: flex;
  align-items: stretch;
  gap: 6px;
  width: 100%;
}
.pf-v5-c-input-group__item { display: flex; align-items: stretch; }
.pf-v5-c-input-group__item.pf-m-fill { flex: 1 1 auto; min-width: 0; }
.pf-v5-c-input-group__item > .ha-input { width: 100%; }

.ha-reveal {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: var(--field-h);
  height: var(--field-h);
  padding: 0;
  border: 1px solid var(--ha-line-strong);
  border-radius: var(--radius-sm);
  background: var(--ha-panel-2);
  color: var(--ha-muted);
  cursor: pointer;
  transition: color .12s ease, border-color .12s ease;
}
.ha-reveal:hover { color: var(--ha-brass); border-color: var(--ha-brass); }
.ha-reveal:focus-visible { outline: 2px solid var(--ha-brass); outline-offset: 1px; }
/* Drawn in CSS. The stock theme ships an icon font for these two glyphs, and a
   font request that fails leaves a button with no label at all. */
.ha-eye::before { content: "\25CB"; font-size: 15px; line-height: 1; font-style: normal; }
.ha-eye-off::before { content: "\2298"; font-size: 15px; line-height: 1; font-style: normal; }

/* The message under a refused field. */
.ha-input-error,
.pf-v5-c-helper-text__item.pf-m-error,
.pf-v5-c-helper-text__item.pf-m-error .pf-v5-c-helper-text__item-text {
  font-size: 12px;
  color: var(--ha-danger);
}

/* ── options row: remember me, forgot password ────────────────────── */

.ha-options {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 13px;
}
.ha-options label { color: var(--ha-muted); display: inline-flex; align-items: center; gap: 6px; }
.ha-options input[type="checkbox"] { accent-color: var(--ha-brass); }

a { color: var(--ha-brass); text-decoration: none; }
a:hover { text-decoration: underline; }
a:focus-visible { outline: 2px solid var(--ha-brass); outline-offset: 2px; border-radius: 2px; }

/* ── buttons ──────────────────────────────────────────────────────── */

.ha-buttons { margin-top: 4px; }

.ha-btn {
  font: inherit;
  font-size: 14px;
  min-height: var(--field-h);
  padding: 0 14px;
  border: 1px solid var(--ha-line-strong);
  border-radius: var(--radius-sm);
  background: var(--ha-panel-2);
  color: var(--ha-fg);
  cursor: pointer;
}
.ha-btn:hover { border-color: var(--ha-brass); color: var(--ha-brass); }
.ha-btn:focus-visible { outline: 2px solid var(--ha-brass); outline-offset: 1px; }

.ha-btn-primary {
  background: var(--ha-brass);
  border-color: var(--ha-brass);
  color: #fff;
  font-weight: 600;
  letter-spacing: .01em;
}
.ha-btn-primary:hover { filter: brightness(1.08); color: #fff; border-color: var(--ha-brass); }
.ha-btn-block { display: block; width: 100%; }
.ha-btn-lg { padding: 10px 14px; }
.ha-btn-disabled { opacity: .55; cursor: not-allowed; }

/* ── alerts ───────────────────────────────────────────────────────── */

.pf-v5-c-alert,
.ha-alert {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 0 0 14px;
  padding: 9px 11px;
  border: 1px solid var(--ha-line);
  border-radius: var(--radius-sm);
  background: var(--ha-panel-2);
  color: var(--ha-fg);
  font-size: 13px;
}
.pf-v5-c-alert__title, .ha-alert-title { font-weight: 500; }
.pf-v5-c-alert.pf-m-danger  { border-color: var(--ha-danger); background: var(--ha-danger-tint); }
.pf-v5-c-alert.pf-m-warning { border-color: var(--ha-brass);  background: var(--ha-brass-tint); }
.pf-v5-c-alert.pf-m-success { border-color: var(--ha-signal); background: var(--ha-signal-tint); }
/* The icon slot the templates emit is left empty by this theme — the border and
   ground already carry the state, and an icon font that fails to load would put
   a broken glyph in front of every message. */
.pf-v5-c-alert__icon, .ha-alert .pf-c-alert__icon { display: none; }

.alert-error   { border-color: var(--ha-danger); background: var(--ha-danger-tint); }
.alert-warning { border-color: var(--ha-brass);  background: var(--ha-brass-tint); }
.alert-success { border-color: var(--ha-signal); background: var(--ha-signal-tint); }
.alert-info    { border-color: var(--ha-line-strong); }

/* ── identity providers ───────────────────────────────────────────── */

.ha-social { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--ha-line); }
.ha-social-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ha-social-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.ha-social-btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
.ha-social-name { font-size: 13px; }

/* ── one-time codes ───────────────────────────────────────────────── */

.ha-otp-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ha-otp-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px;
  border: 1px solid var(--ha-line); border-radius: var(--radius-sm);
  background: var(--ha-panel-2);
}
.ha-otp-title { font-size: 13px; }
/* A code is read off a screen and typed digit by digit; a proportional face
   makes 1 and l the same shape. */
.ha-otp-input, input[name="otp"], input[id="otp"] { font-family: var(--ha-mono); letter-spacing: .08em; }

/* ── locale picker ────────────────────────────────────────────────── */

.ha-locale { position: relative; display: flex; justify-content: flex-end; margin-bottom: 8px; font-size: 13px; }
.ha-locale-list {
  list-style: none; margin: 4px 0 0; padding: 4px;
  position: absolute; right: 0; top: 100%; z-index: 10;
  min-width: 150px;
  background: var(--ha-panel);
  border: 1px solid var(--ha-line); border-radius: var(--radius-sm);
  box-shadow: var(--ha-shadow);
}
.ha-locale-item { list-style: none; }
.ha-locale-link { display: block; padding: 6px 9px; border-radius: var(--radius-sm); color: var(--ha-fg); }
.ha-locale-link:hover { background: var(--ha-brass-tint); color: var(--ha-brass); text-decoration: none; }

/* ── the footer line under the card ───────────────────────────────── */

.ha-info, #kc-info {
  width: min(360px, 100%);
  text-align: center;
  font-size: 13px;
  color: var(--ha-muted);
}

/* Keycloak renders a try-another-way link and a back link into these. */
.ha-signup, .ha-setting { font-size: 13px; color: var(--ha-muted); }

/* ── motion ───────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
  .ha-card { animation: ha-rise .18s ease-out both; }
  @keyframes ha-rise { from { opacity: 0; transform: translateY(4px); } }
}
