/* ===========================================================================
   OMNI LOGIN — the shared sign-in FORMAT for every Omni product and private
   label. Portable and self-contained: it depends on no other stylesheet, so a
   peer can drop this one file into any app and get the same sign-in shape.

   WHAT THIS FILE DECIDES:  layout, dimensions, spacing, type scale, where the
                            brand sits, how the theme flips.
   WHAT IT NEVER DECIDES:   which sign-in methods exist. A product that offers
                            only Microsoft renders only the Microsoft button; a
                            product with email+password renders the form too.
                            Nothing here shows, hides, or reorders a method —
                            that stays each app's own logic.

   THE SHAPE: a two-panel shell. Left is the brand — big mark, product wordmark,
   one line of what the product is, and a few plain-language proof points. Right
   is the card that actually signs you in. Under 900px the brand panel collapses
   into a compact header above the card, so a phone sees one clean column.

   COLOR: one token. Set --login-accent to the product's own main color and the
   whole screen follows — button, focus ring, wordmark highlight, and the two
   soft glows behind the shell. Aura is orange, SONAR is cyan, a peer's app might
   be purple: same screen, own color.

   BRAND: the mark belongs to whoever OWNS the deployment. Omni's own builds show
   the Omni Echo logo; a white-labeled build shows the client's, via one config
   value (--login-logo / --login-logo-dark) — never a forked template.

   PERF: no backdrop-filter anywhere, and no filter on any animated layer (an
   Omni-wide law after a full-screen runtime blur cost us frames on every build).
   The glows are static radial gradients, which cost nothing.

   USAGE
     <link rel="stylesheet" href="/omni-login.css">
     :root { --login-accent: #d97706; --login-accent-dark: #f59e0b;
             --login-logo: url('/assets/your-logo-on-light.png');
             --login-logo-dark: url('/assets/your-logo-on-dark.png'); }
   Markup skeleton is in docs/login_standard.md — copy it verbatim.
=========================================================================== */

:root {
  /* --- the one knob a product sets ------------------------------------- */
  --login-accent: #d97706;          /* main color on LIGHT backgrounds */
  --login-accent-dark: #f59e0b;     /* main color on DARK backgrounds  */
  --login-accent-ink: #ffffff;      /* text ON the accent (contrast!)  */

  /* --- brand marks (theme-aware; leave unset to fall back to a wordmark) */
  --login-logo: none;
  --login-logo-dark: none;
  --login-powered-logo: url('/assets/omni-echo-light-gold.png');
  --login-powered-logo-dark: url('/assets/omni-echo-dark.png');
  /* One size for whoever owns the deployment — ours on an Omni build, the
     client's on theirs. Ours used to be the smaller of the two. */
  --login-logo-height: 62px;
  --login-logo-width: 280px;

  /* --- format: identical across every product --------------------------- */
  --login-width: 372px;             /* the card */
  --login-shell: 960px;             /* brand panel + card together */
  /* The two columns SHARE one height, so the card's top and bottom edges always
     line up with the brand copy beside it. Whatever the two differ by becomes a
     gap above the proof list, so the copy is matched to the card instead: a
     product whose card carries a FORM earns the proof points (SONAR measures 474
     against 472), and a compact SSO-only card shows the headline and pitch alone
     — hide .login-points when there is no form. */
  /* Tight enough that a card carrying BOTH a provider button and a password form
     lands near the brand copy's natural height. The two columns are pinned to a
     shared top and bottom, so whatever height they differ by becomes a gap in the
     middle of the left column — the fix is to shrink the difference, not to widen
     the gap. */
  --login-pad: 28px 28px;
  /* A floor, not a fixed height: a compact SSO-only card is given enough room to
     sit beside two proof points, and a card carrying a form simply exceeds it. */
  --login-card-min: 330px;
  --login-radius: 20px;
  --login-field-radius: 11px;
  --login-font: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* --- light surface ---------------------------------------------------- */
  --login-bg: #f4f5f8;
  --login-bg-2: #eceef3;
  --login-surface: #ffffff;
  --login-border: #e2e5ea;
  --login-field: #f8f9fb;
  --login-text: #14161b;
  --login-muted: #6a7280;
  --login-err: #c0362c;
  --login-shadow: 0 24px 60px -20px rgba(16, 18, 23, .22), 0 2px 8px rgba(16, 18, 23, .05);
  --login-glow: .16;
}

/* Dark surface. Both signals are honored: an app that stamps data-theme on the
   root wins, otherwise the OS preference decides — so this file behaves the
   same whether or not the host app has a theme switcher. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --login-bg: #0c0e13;
    --login-bg-2: #12151c;
    --login-surface: #171b22;
    --login-border: #272d38;
    --login-field: #0e1116;
    --login-text: #e8eaed;
    --login-muted: #98a1ae;
    --login-err: #ff7a7a;
    --login-shadow: 0 30px 70px -24px rgba(0, 0, 0, .8), 0 2px 10px rgba(0, 0, 0, .35);
    --login-accent: var(--login-accent-dark);
    --login-glow: .26;
  }
}
:root[data-theme="dark"] {
  --login-bg: #0c0e13;
  --login-bg-2: #12151c;
  --login-surface: #171b22;
  --login-border: #272d38;
  --login-field: #0e1116;
  --login-text: #e8eaed;
  --login-muted: #98a1ae;
  --login-err: #ff7a7a;
  --login-shadow: 0 30px 70px -24px rgba(0, 0, 0, .8), 0 2px 10px rgba(0, 0, 0, .35);
  --login-accent: var(--login-accent-dark);
  --login-glow: .26;
}

/* --- the page ---------------------------------------------------------- */
/* Two static radial washes in the product's own color, plus a linear base.
   Static gradients — never an animated or filtered layer (the perf law). */
.login-page {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;              /* mobile browser chrome must not clip the card */
  display: flex;
  flex-direction: column;          /* shell, then the "powered by" footer */
  align-items: center;
  justify-content: center;
  gap: 34px;
  padding: 32px 20px;
  box-sizing: border-box;
  color: var(--login-text);
  font-family: var(--login-font);
  -webkit-font-smoothing: antialiased;
  background:
    radial-gradient(58% 48% at 12% 8%, color-mix(in srgb, var(--login-accent) calc(var(--login-glow) * 100%), transparent) 0%, transparent 62%),
    radial-gradient(52% 44% at 92% 96%, color-mix(in srgb, var(--login-accent) calc(var(--login-glow) * 66%), transparent) 0%, transparent 60%),
    linear-gradient(160deg, var(--login-bg) 0%, var(--login-bg-2) 100%);
  background-attachment: fixed;
}

/* --- the shell: brand panel + card -------------------------------------- */
/* align-items:stretch is what makes the two columns share ONE height — the card's
   top and bottom edges line up with the brand copy beside it instead of floating
   at some height of their own. Each column then centers its own content, so a
   short card (an SSO-only build with one button) still reads as deliberate. */
.login-shell {
  width: 100%;
  max-width: var(--login-shell);
  display: grid;
  grid-template-columns: 1fr minmax(320px, var(--login-width));
  align-items: stretch;
  gap: 56px;
}
/* One column on anything narrower than a small laptop. The brand panel stays —
   it just becomes a compact header above the card instead of a column beside it. */
@media (max-width: 900px) {
  /* Stacked: the fixed height is a desktop alignment device and would only add
     dead space above a phone's card. */
  .login-shell { grid-template-columns: minmax(0, var(--login-width)); justify-content: center; gap: 26px; }
  .login-aside { text-align: center; }
  .login-aside .login-brand { justify-content: center; }
  .login-aside .login-points { display: none; }   /* proof points are desktop breathing room */
  .login-aside .login-pitch { font-size: 14px; margin-inline: auto; }
  .login-card { justify-content: flex-start; }    /* stacked: no column height to fill */
}

/* --- brand panel -------------------------------------------------------- */
/* Top-aligned so the brand copy starts on the CARD'S top edge — the two columns
   already share a height (see .login-shell), and a shared top line is what the
   eye actually reads as "aligned". Centering it instead left the logo floating
   a hundred pixels below the card's corner. */
/* Both columns fill the shared height. The brand copy starts at the top and its
   proof list is pinned to the bottom, so the first line sits on the card's top
   edge and the last sits on its bottom edge. Keep a product's proof-point COUNT
   tuned to its card so the leftover in the middle stays small — two for a compact
   SSO-only card, three for a card carrying a form as well. */
.login-aside { min-width: 0; display: flex; flex-direction: column; justify-content: flex-start; }
/* text-wrap: balance/pretty is the widow fix — the browser re-flows the last
   lines so a sentence never ends on one orphaned word. `pretty` costs nothing on
   short runs of text and degrades to normal wrapping where unsupported. */
.login-headline {
  font-size: 33px;
  line-height: 1.15;
  font-weight: 800;
  letter-spacing: -.015em;
  /* The card's own first line of text sits one padding-height down from its top
     edge; matching that here keeps the headline and the card's wordmark on the
     same baseline instead of a few pixels apart. */
  margin: 22px 0 10px;
  text-wrap: balance;
}
.login-pitch {
  color: var(--login-muted);
  font-size: 16px;
  line-height: 1.65;
  margin: 0;
  max-width: 42ch;
  text-wrap: pretty;
}
/* margin-top:auto pins the list to the BOTTOM of the shared column height, so the
   last proof point's baseline lands on the card's bottom edge. Together with the
   top-aligned brand mark that gives the pair a true top-and-bottom alignment
   rather than one shared edge and one ragged one. padding-top keeps a floor under
   the gap on a short card, where auto would otherwise collapse to nothing. */
.login-points { list-style: none; margin: auto 0 0; padding: 24px 0 0; display: grid; gap: 14px; }
.login-points li {
  position: relative;
  padding-left: 27px;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--login-muted);
  max-width: 46ch;
  text-wrap: pretty;
}
.login-points li::before {
  content: '';
  position: absolute;
  left: 0; top: .34em;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--login-accent) 20%, transparent);
  border: 1px solid color-mix(in srgb, var(--login-accent) 55%, transparent);
}
.login-points li::after {
  content: '';
  position: absolute;
  left: 4.5px; top: .62em;
  width: 4px; height: 7px;
  border: solid var(--login-accent);
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(42deg);
}

/* --- brand lockup ------------------------------------------------------- */
/* The image is a background so one element serves both themes and an app with
   no logo asset still gets a correctly-sized wordmark instead of a broken img. */
/* No padding: the logo's own top edge IS the column's top edge, so it lines up
   with the card's top border rather than sitting a few pixels below it. */
.login-brand { display: flex; align-items: flex-start; gap: 12px; min-height: var(--login-logo-height); }
.login-brand .login-logo {
  display: block;
  height: var(--login-logo-height);
  width: var(--login-logo-width);
  max-width: 100%;
  background: var(--login-logo) no-repeat left center / contain;
}
:root[data-theme="dark"] .login-brand .login-logo { background-image: var(--login-logo-dark); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .login-brand .login-logo { background-image: var(--login-logo-dark); }
}
@media (max-width: 900px) { .login-brand .login-logo { background-position: center; } }
/* Wordmark: the product name. It lives at the top of the CARD, not beside the
   logo — the company mark already says "Omni Echo", and putting "OMNI AURA"
   right next to it read as the same word twice in one spot. Separating them
   gives each a job: the mark is who made it, the wordmark is which product you
   are signing in to. */
/* Pinned to the top-left of the card while everything else stays centred: the
   product name is a label on the box, not part of the sign-in block. Absolute so
   it cannot push that block off centre; the card reserves room for it below. */
.login-wordmark {
  position: absolute;
  top: 26px;
  left: 28px;
  right: 28px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .16em;
  color: var(--login-muted);
  white-space: nowrap;
  margin: 0;
}
.login-wordmark em { font-style: normal; color: var(--login-accent); }
/* A wordmark still sitting in the brand lockup (an app that has not moved it
   yet, or one with no logo asset at all) keeps the larger treatment. */
.login-brand .login-wordmark { font-size: 19px; letter-spacing: .12em; color: var(--login-text); margin: 0; }

/* --- the card ---------------------------------------------------------- */
/* max-width, not width: the sign-in screen is the first thing anyone sees, and
   a fixed width scrolls sideways on a narrow phone. */
.login-card {
  position: relative;
  width: 100%;
  max-width: var(--login-width);
  box-sizing: border-box;
  background: var(--login-surface);
  border: 1px solid var(--login-border);
  border-radius: var(--login-radius);
  box-shadow: var(--login-shadow);
  padding: var(--login-pad);
  padding-top: 58px;                 /* room for the pinned wordmark above */
  min-height: var(--login-card-min);
  box-sizing: border-box;
  overflow: hidden;
  /* Fills the shared column height with its content CENTERED — neither squished
     against the top edge nor stretched apart to reach the bottom one. */
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* A hairline of the product's color across the top of the card — the one piece
   of chrome that makes two products instantly distinguishable at a glance. */
.login-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--login-accent), color-mix(in srgb, var(--login-accent) 30%, transparent));
}
@media (max-width: 420px) { .login-card { padding: 28px 22px; } }

/* --- copy -------------------------------------------------------------- */
.login-title { font-size: 19.5px; line-height: 1.25; margin: 0 0 4px; font-weight: 700; letter-spacing: -.01em; }
/* The copy sits HIGH in the card and the methods keep their place; the gap between
   them is what was missing (user 2026-08-05: "no space between them"). */
.login-sub { color: var(--login-muted); font-size: 12.8px; line-height: 1.5; margin: 0 0 30px; }

/* --- messages ---------------------------------------------------------- */
/* Reserved height: an error appearing must not shift the button out from under
   a finger already on its way down to it. */
.login-error { color: var(--login-err); font-size: 12.5px; line-height: 1.5; margin: 0 0 12px; min-height: 1em; }
/* Empty = absent. Reserving the line made Aura sit a row lower than SONAR under
   the same subtitle; matching spacing across products is worth the small shift
   that appears when a real error does. */
.login-error:empty { min-height: 0; margin: 0; }   /* the gap comes from .login-sub, not from a blank line */
.login-note { color: var(--login-muted); font-size: 12.5px; line-height: 1.5; margin: 10px 0 0; }

/* --- buttons ----------------------------------------------------------- */
/* 44px minimum: the platform tap-target floor. */
.login-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
  min-height: 44px;
  padding: 11px 16px;
  border: 1px solid transparent;
  border-radius: 12px;
  font: 600 13.8px var(--login-font);
  cursor: pointer;
  text-decoration: none;
  transition: transform .1s ease, box-shadow .12s ease, background-color .12s ease;
}
.login-btn:hover { text-decoration: none; transform: translateY(-1px); }
.login-btn:active { transform: translateY(0); }
.login-btn:disabled { opacity: .6; cursor: default; transform: none; }
.login-btn.primary {
  background: var(--login-accent);
  color: var(--login-accent-ink);
  box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--login-accent) 70%, transparent);
}
.login-btn.primary:hover { box-shadow: 0 10px 24px -8px color-mix(in srgb, var(--login-accent) 80%, transparent); }
/* The identity-provider button stays NEUTRAL, never the brand color: Microsoft
   and Google both require their mark be legible and unrecolored, and an
   accent-filled provider button reads as "this app's button", not "sign in
   with them". */
.login-btn.provider { background: var(--login-surface); color: var(--login-text); border-color: var(--login-border); }
.login-btn.provider:hover { background: var(--login-field); border-color: color-mix(in srgb, var(--login-accent) 45%, var(--login-border)); }
.login-btn svg { flex: none; }
.login-btn + .login-btn { margin-top: 9px; }

/* --- divider between method groups ------------------------------------- */
.login-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--login-muted);
  font-size: 11.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin: 14px 0;
}
.login-divider::before, .login-divider::after { content: ''; flex: 1; height: 1px; background: var(--login-border); }

/* --- fields ------------------------------------------------------------ */
.login-form { margin: 0; }
.login-label { display: block; font-size: 11.5px; font-weight: 600; color: var(--login-muted); margin: 0 0 5px; }
.login-input {
  width: 100%;
  box-sizing: border-box;
  padding: 11px 13px;
  margin: 0 0 12px;
  border: 1px solid var(--login-border);
  border-radius: var(--login-field-radius);
  background: var(--login-field);
  color: var(--login-text);
  font: 500 13.5px var(--login-font);
  transition: border-color .12s ease, box-shadow .12s ease;
}
/* iOS Safari zooms the page when a focused field is under 16px and never zooms
   back out — the user is left looking at a magnified corner of the card. */
@media (max-width: 640px) { .login-input { font-size: 16px; } }
.login-input:focus {
  outline: none;
  border-color: var(--login-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--login-accent) 20%, transparent);
}
.login-form .login-btn { margin-top: 6px; }

/* --- tabs (sign in / create account), for apps that have them ----------- */
.login-tabs { display: flex; gap: 6px; margin: 0 0 16px; }
.login-tab {
  flex: 1;
  min-height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 7px 0;
  border: 1px solid var(--login-border);
  border-radius: 999px;
  font-size: 13px;
  color: var(--login-muted);
  text-decoration: none;
}
.login-tab.on { background: var(--login-accent); border-color: var(--login-accent); color: var(--login-accent-ink); font-weight: 600; }

/* --- quiet footer links ------------------------------------------------ */
.login-foot { display: flex; justify-content: space-between; gap: 12px; margin-top: 14px; }
.login-quiet { color: var(--login-muted); font-size: 12px; text-decoration: none; }
.login-quiet:hover { color: var(--login-text); text-decoration: underline; }

/* --- "powered by" lockup ------------------------------------------------ */
/* Shown on a white-labeled build only: the client's mark leads, and ours signs
   the work at the foot of the brand column. An Omni build hides it — we are
   already the mark at the top, and naming ourselves twice is noise. */
.login-powered {
  display: none;                      /* .login-branded on <html> reveals it */
  flex-direction: column;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--login-muted);
  opacity: .8;
}
:root.login-branded .login-powered { display: flex; }
.login-powered .login-powered-mark {
  display: block;
  height: 24px;
  width: 116px;
  background: var(--login-powered-logo) no-repeat center / contain;
}
:root[data-theme="dark"] .login-powered .login-powered-mark { background-image: var(--login-powered-logo-dark); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .login-powered .login-powered-mark { background-image: var(--login-powered-logo-dark); }
}


.login-hidden { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  .login-btn { transition: none; }
  .login-btn:hover, .login-btn:active { transform: none; }
}
