/*
 * Phylax sign-in styling.
 *
 * Rodauth emits Bootstrap-flavoured class names (form-group, form-control,
 * btn btn-primary) but ships no CSS, which is why the pages render as raw
 * HTML. Rather than pull in a whole framework for four form controls, this
 * styles exactly the markup Rodauth produces.
 *
 * This is the one screen every user of every connected application sees, and
 * often the only part of the estate they ever look at. It should read as
 * deliberate and trustworthy: a login page that looks broken teaches people
 * not to trust the thing asking for their password.
 *
 * Per-client instances will re-skin this via the custom properties below.
 * Keep colour and type decisions in :root so a client theme is a short
 * override rather than a fork.
 */

:root {
  --ink: #16202b;
  --ink-soft: #5a6672;
  --paper: #eef1f4;
  --card: #ffffff;
  --line: #d5dbe1;
  --accent: #2f5d8a;
  --accent-ink: #ffffff;
  --danger: #a8322a;
  --focus: #2f5d8a;
  /* The callout (TW #2925): amber, not the accent and not the danger red. */
  --callout-ink: #3d2800;
  --callout-bg: #fff3d1;
  --callout-border: #b86e00;
  --radius: 4px;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e4e9ed;
    --ink-soft: #94a2ae;
    --paper: #131a21;
    --card: #1b242d;
    --line: #2b3742;
    --accent: #6ea8dc;
    --accent-ink: #0f1620;
    --danger: #e0736a;
    --focus: #6ea8dc;
    --callout-ink: #fde7b8;
    --callout-bg: #3b2b0c;
    --callout-border: #f0a530;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  /* Column, explicitly. Rodauth renders the form and its footer links as
     sibling top-level elements, so the default row direction strings them
     across the page instead of stacking them. */
  flex-direction: column;
  align-items: center;
  padding: clamp(1.5rem, 8vh, 5rem) 1.25rem 3rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* The card. Rodauth renders a bare form, so the form itself is the card and
   any following content (footer links) sits beneath it in the same column. */
body > * {
  width: 100%;
  max-width: 25rem;
}

form.rodauth {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.75rem 1.5rem 1.5rem;
  margin: 0 0 1.5rem;
}

.form-group { margin-bottom: 1.1rem; }
.form-group:last-child { margin-bottom: 0; }

.form-label {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}

.form-control {
  display: block;
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  font-size: 0.97rem;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.form-control:focus {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-color: var(--focus);
}

.btn {
  display: inline-block;
  width: 100%;
  padding: 0.65rem 1rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.btn-primary:hover { filter: brightness(1.08); }

/* A link drawn as a button (TW #2690). A button centres its words and does not
   underline them; a link does neither unless told. Said once, here, for every
   page: it used to be said page by page, and the page that was forgotten
   showed its words at the left, underlined. */
a.btn-primary, a.btn-secondary { text-align: center; text-decoration: none; }

.btn:focus-visible,
.btn-link:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* Footer links ("Forgot Password?" and friends). Presented as quiet options,
   not as calls to action competing with the sign-in button. */
.rodauth-login-form-footer-links-heading,
h2 {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
  margin: 0 0 0.6rem;
}

.rodauth-links,
ul.rodauth-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.rodauth-links a {
  color: var(--accent);
  text-decoration: none;
  font-size: 0.92rem;
}

.rodauth-links a:hover { text-decoration: underline; }

.rodauth-links a:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Flash messages: Rodauth reports both errors and notices through these. */
/* .login-refused and .login-locked: the sign-in's one refusal and the locked
   page's sentence (TW #2674). */
.flash-error, .alert-danger, .field_error, .login-refused, .login-locked {
  color: var(--danger);
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

.flash-notice, .alert-notice, .alert-success {
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

/* Masthead supplied by the layout. */
.phylax-masthead {
  margin: 0 0 1.25rem;
}

.phylax-masthead .service {
  font-size: 1.15rem;
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.01em;
}

.phylax-masthead .tagline {
  margin: 0.15rem 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.phylax-footnote {
  margin: 1.75rem 0 0;
  font-size: 0.76rem;
  color: var(--ink-soft);
}

/*
 * The launcher (TW #1983): the authenticated landing, and the screen a client
 * is shown to demonstrate that several apps are one system. Same tokens as
 * the sign-in card — one product, not a second look — and everything is
 * token-driven, so the existing dark-scheme block covers it with no extra
 * rules and a per-client re-skin carries the launcher for free.
 *
 * Type scale (rem), hold to it: 0.72 eyebrow/meta/note · 0.78 chips ·
 * 0.85 standing · 0.97 tile label · 1.5 name.
 * Spacing rhythm (rem): 0.25 · 0.5 · 0.75 · 1 · 1.5 · 2. No eyeballed values.
 */

/* ── Identity header: whose access this is, readable across a room ───────── */

.launcher-id {
  margin: 0 0 1.5rem;
  padding: 0 0 1rem;
  border-bottom: 1px solid var(--line);
}

.launcher-id-eyebrow {
  margin: 0 0 0.25rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
}

.launcher-id-name {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--ink);
}

.launcher-id-standing {
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.launcher-id-sep { margin: 0 0.25rem; }

.launcher-id-roles { color: var(--ink); font-weight: 500; }

/* ── Section label, matching the sign-in card's footer-heading treatment ── */

.launcher-heading {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
  margin: 0 0 0.75rem;
}

/* ── Tiles: mark · label+meta · role chip. The anchor IS the card. ───────── */

.launcher-tiles {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.launcher-tile-link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  color: var(--ink);
  text-decoration: none;
  transition: border-color 120ms ease;
}

.launcher-tile-link:hover { border-color: var(--accent); }

.launcher-tile-link:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* The mark: a monogram square that gives each tile a face; the portal kind
   is accent-tinted so a non-WordPress app is visibly a different animal. */
.launcher-tile-mark {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  font-size: 0.97rem;
  font-weight: 700;
  color: var(--ink-soft);
}

.launcher-tile--rails_app .launcher-tile-mark,
.launcher-tile--admin_app .launcher-tile-mark {
  color: var(--accent);
  border-color: var(--accent);
}

.launcher-tile-body { flex: 1; min-width: 0; }

.launcher-tile-label {
  display: block;
  font-size: 0.97rem;
  font-weight: 600;
  line-height: 1.3;
}

.launcher-tile-meta {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.launcher-tile-kind {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0 0.5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* The role chip: differentiated access IS the demo, so the permission gets
   real weight — administrator filled with the accent, other roles outlined. */
.launcher-tile-role {
  flex: none;
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  background: transparent;
}

.launcher-tile-role--administrator {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* ── Empty state: same card language — a designed answer ────────────────── */

.launcher-empty {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin: 0 0 1.5rem;
}

.launcher-empty h1 {
  font-size: 0.97rem;
  font-weight: 600;
  margin: 0 0 0.5rem;
}

.launcher-empty p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* ── Sign out: unmistakably a control, quieter than the tiles ────────────── */

.launcher-signout {
  margin-top: 0.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.btn-signout {
  width: auto;
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
  background: var(--card);
  color: var(--ink);
  border-color: var(--line);
}

.btn-signout:hover { border-color: var(--accent); }

.launcher-signout-note {
  margin: 0.5rem 0 0;
  font-size: 0.72rem;
  color: var(--ink-soft);
}

/* ── Guided tour (TW #2000): one fixed card, launcher only ───────────────── */

.launcher-tour {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  width: min(21rem, calc(100vw - 3rem));
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  padding: 1rem 1rem 0.75rem;
  z-index: 50;
}

.launcher-tour-count {
  margin: 0 0 0.25rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
}

.launcher-tour-title {
  margin: 0 0 0.25rem;
  font-size: 0.97rem;
  font-weight: 600;
  color: var(--ink);
}

.launcher-tour-body {
  margin: 0 0 0.75rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.launcher-tour-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.launcher-tour-next {
  width: auto;
  padding: 0.5rem 1.1rem;
  font-size: 0.85rem;
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

.launcher-tour-dismiss {
  background: none;
  border: none;
  padding: 0.25rem;
  font: inherit;
  font-size: 0.72rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.launcher-tour-dismiss:hover { color: var(--ink); text-decoration: underline; }

/* "Say what to NOTICE": each away-sending step quietly rings the thing it is
   talking about — no arrows, no motion. */
[data-tour-step="2"] .launcher-tile-role { box-shadow: 0 0 0 2px var(--focus); }
[data-tour-step="3"] .launcher-tile--wordpress .launcher-tile-link { border-color: var(--accent); }
[data-tour-step="4"] .btn-signout { box-shadow: 0 0 0 2px var(--focus); }

/* ---- Passkeys (TW #2600) ------------------------------------------------ */

.rodauth_hidden { display: none; }

.phylax-login { max-width: 26rem; margin: 0 auto; }

.passkey-first { text-align: center; margin-bottom: 0.5rem; }
.btn-passkey { width: 100%; }
.passkey-status { min-height: 1.25rem; margin: 0.5rem 0 0; font-size: 0.85rem; color: var(--ink-soft); }
.passkey-status.is-error { color: var(--ink); }

.login-divider {
  display: flex; align-items: center; gap: 0.75rem;
  margin: 1rem 0; font-size: 0.8rem; color: var(--ink-soft);
}
.login-divider::before, .login-divider::after { content: ""; flex: 1; border-top: 1px solid var(--ink-soft); opacity: 0.35; }

/* Administrator sites in a session that did not use the passkey (TW #2911). */
.launcher-needs-passkey {
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  font-size: 0.9rem;
  margin: 0 0 1rem;
}
.launcher-needs-passkey a { color: var(--accent); font-weight: 600; }

/* "You're an administrator on ..." (TW #2925): the sentence the person must
   notice, on the page asked after a sign-in, the wizard's panel and the
   Launcher's line. Amber and bold (Steve, round 2), not the danger red:
   nothing is wrong. Contrast, text on box: 12.6:1 light, 11.3:1 dark; the
   left border against the box 3.6:1 light, 6.6:1 dark. */
.passkey-callout {
  display: block;
  margin: 0 0 0.6rem;
  padding: 0.55rem 0.8rem;
  font-weight: 700;
  color: var(--callout-ink);
  background: var(--callout-bg);
  border-left: 4px solid var(--callout-border);
  border-radius: var(--radius);
  text-align: left;
}
.launcher-tile-needs-passkey {
  flex: none;
  padding: 0.25rem 0.6rem;
  border: 1px dashed var(--line);
  border-radius: 999px;
  font-size: 0.72rem;
  color: var(--ink-soft);
}

/* The page asked once before the Launcher: the line for a phone under the
   button, and the way to the wizard above the way on without it (TW #2917). */
.passkey-ask-phone { margin: 0.5rem 0 0; font-size: 0.85rem; color: var(--ink-soft); text-align: center; }
.passkey-ask-set-up { margin: 1.25rem 0 0; text-align: center; font-size: 0.95rem; }
.passkey-ask-set-up a { color: var(--accent); font-weight: 600; }

.launcher-passkeys { margin: 1rem 0 0; font-size: 0.85rem; color: var(--ink-soft); }
.launcher-passkeys-link { color: var(--accent); font-weight: 600; }

.phylax-passkeys { max-width: 32rem; margin: 0 auto; }
.passkeys-heading { font-size: 1.35rem; margin: 0 0 0.5rem; }
.passkeys-lede, .passkeys-empty { color: var(--ink-soft); font-size: 0.92rem; }
.passkeys-list { list-style: none; padding: 0; margin: 1rem 0; }
.passkey {
  display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; justify-content: space-between;
  padding: 0.75rem 0; border-top: 1px solid var(--ink-soft);
}
.passkey:last-child { border-bottom: 1px solid var(--ink-soft); }
.passkey-name { margin: 0; font-weight: 600; }
.passkey-meta { margin: 0.15rem 0 0; font-size: 0.8rem; color: var(--ink-soft); }
.passkey-remove summary { list-style: none; cursor: pointer; display: inline-block; }
.passkey-remove summary::-webkit-details-marker { display: none; }
.passkey-remove[open] summary { border-color: var(--accent); }
.passkey-remove-form { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-top: 0.5rem; }
.passkey-remove-form .form-label { flex-basis: 100%; margin: 0; font-size: 0.85rem; color: var(--ink-soft); }
.form-control-sm { padding: 0.3rem 0.5rem; font-size: 0.85rem; max-width: 11rem; }
.btn-remove { background: none; border: 1px solid var(--ink-soft); color: var(--ink); padding: 0.3rem 0.7rem; }
.btn-remove:hover { border-color: var(--accent); }
.passkeys-actions { display: flex; gap: 1rem; align-items: center; margin-top: 1.25rem; }
.passkeys-back { color: var(--ink-soft); font-size: 0.9rem; }

/* ---- Branding (TW #2605): the mark and the launcher title ------------- */

.phylax-masthead { display: flex; align-items: center; gap: 0.75rem; }
.brand-mark { width: 44px; height: 44px; border-radius: 50%; flex: none; object-fit: contain; }
.launcher-title { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.01em; margin: 0 0 0.75rem; }

/* ---- Contextual help (TW #2610): where am I, and what's a passkey ------ */

.orient { margin: 0 0 1rem; font-size: 0.92rem; color: var(--ink-soft); }
.orient strong { color: var(--ink); }
details.help { margin: 0.75rem 0 0; font-size: 0.88rem; text-align: left; }
details.help summary { cursor: pointer; color: var(--accent); list-style: none; display: inline-block; }
details.help summary::-webkit-details-marker { display: none; }
details.help summary::before { content: "?"; display: inline-block; width: 1.1rem; height: 1.1rem; margin-right: 0.4rem;
  border: 1px solid var(--accent); border-radius: 50%; font-size: 0.7rem; line-height: 1.1rem; text-align: center; }
details.help[open] summary { margin-bottom: 0.4rem; }
.help-body p { margin: 0 0 0.5rem; color: var(--ink-soft); }
/* How to get one (TW #2641): set off from what a passkey is by a rule, and
   opened by its own bold lead-in in place of a heading. */
.help-howto { margin-top: 0.75rem; padding-top: 0.6rem; border-top: 1px solid var(--line); }
.help-howto strong { color: var(--ink); }

/* ---- Login wizard (TW #2615): passkey first, credentials on request ------ */

.btn-secondary { background: var(--card); color: var(--ink); border-color: var(--line); }
.btn-secondary:hover { border-color: var(--accent); }
details.credentials { margin: 1rem 0 0; }
details.credentials > summary { list-style: none; text-align: center; }
details.credentials > summary::-webkit-details-marker { display: none; }
details.credentials[open] > summary { margin-bottom: 1rem; }
.login-other { margin: 0.75rem 0 0; text-align: center; font-size: 0.9rem; }
.login-other a, .login-other .btn-link { color: var(--ink-soft); }
.login-other a:hover, .login-other .btn-link:hover { color: var(--accent); }
/* The quiet way out that must stay a POST (TW #2690): a button, because a link
   would be a GET, drawn as the link beside it. Without this the browser draws
   it itself: a grey box in the system's own type. */
.btn-link {
  background: none; border: 0; padding: 0;
  font: inherit; color: inherit;
  text-decoration: underline; cursor: pointer;
}

/* ---- Passkey enrolment wizard (TW #2616, #2646): explain and name, create, done ---- */

/* The screens are shown and hidden with the hidden attribute; nothing below
   may bring a hidden one back by giving it a display of its own. */
.passkey-wizard [hidden] { display: none !important; }

.wizard-steps {
  list-style: none; counter-reset: wizard-step;
  display: flex; gap: 0.5rem; padding: 0; margin: 0 0 1.5rem;
  font-size: 0.78rem; color: var(--ink-soft);
}
.wizard-steps li { flex: 1; counter-increment: wizard-step; padding-top: 0.4rem; border-top: 2px solid var(--line); }
.wizard-steps li::before { content: counter(wizard-step) ". "; }
.wizard-steps li.is-done { border-top-color: var(--accent); }
.wizard-steps li.is-current { border-top-color: var(--accent); color: var(--ink); font-weight: 600; }

.wizard-next { margin: 1.25rem 0 0; }
.wizard-status { min-height: 1.4rem; font-size: 0.9rem; }
.wizard-error { color: var(--danger); font-size: 0.92rem; margin: 0 0 0.75rem; }
.wizard-hint { margin: 0.35rem 0 0; font-size: 0.8rem; color: var(--ink-soft); }

.wizard-form { margin: 0; }
.wizard-fields, .wizard-panel {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.5rem 1.5rem 1.25rem; margin: 0.75rem 0 0;
}
.wizard-panel { margin: 0 0 1.25rem; }
.wizard-panel p { margin: 0 0 0.75rem; font-size: 0.92rem; }
.wizard-panel p:last-child { margin-bottom: 0; }

.wizard-leave { margin: 1.25rem 0 0; text-align: center; font-size: 0.9rem; }
.wizard-leave a { color: var(--ink-soft); }
.wizard-leave a:hover { color: var(--accent); }
.passkey-wizard .passkey-name { font-weight: 600; color: var(--ink); }
