/* authd login screen — the single sign-in surface (spec §4, §5).
 *
 * WHY THIS FILE EXISTS (do not inline this again):
 * The styles were originally an inline <style> block inside login.html. The
 * response carries `Content-Security-Policy: style-src 'self'`, which BLOCKS
 * inline styles — so every rule was silently discarded and the user saw
 * unstyled Times New Roman HTML. The design was written, deployed and thrown
 * away by a header, and no visual check caught it.
 *
 * Served as an external stylesheet from /auth/static/ so `style-src 'self'`
 * is satisfied and the CSP stays strict. Do NOT move this back inline.
 */

:root {
  /* SMS SPEEDWAY BRAND TOKENS — corrected 2026-09-16.
   *
   * SOURCE OF TRUTH: ai_knowledge/integrations/conversations_pwa/UX_UI_PRINCIPLES.md §5
   *   "The PWA's own chrome carries SMS Speedway's identity: navy #033F63, sky #37CCFB"
   * Corroborated against the real wordmark SVG (cls-1 = #37ccfb, cls-2 = #033f63)
   * and the live site.
   *
   * WHAT WAS WRONG: the previous palette used ONLY the navy. The company's
   * identity is the navy/sky PAIR, and the sky is the dominant brand colour —
   * dropping it left a generic corporate blue that carries no Speedway identity.
   * The sky accent is now a first-class token, not an afterthought.
   *
   * Do NOT substitute KMID's palette (purple #4212b3 / chartreuse #8bfd00) here:
   * that is the KMID product's identity. UX_UI_PRINCIPLES §5: "Never borrow
   * another product's identity."
   */
  --ink: #0a0a0a;
  --body: #2f2e2e;
  --muted: #a3a3a3;
  --brand: #033f63;        /* SMS Speedway navy */
  --brand-sky: #37ccfb;    /* SMS Speedway sky — the accent, previously omitted */
  --brand-ink: #ffffff;
  --brand-tint: #f4f7fa;
  --line: #e5e7eb;
  --danger: #b42318;
}

* { box-sizing: border-box; }

html {
  /* Paired with body's -webkit-fill-available below; without a height on the
   * root the child's percentage-of-available resolves against nothing. */
  height: -webkit-fill-available;
}

body {
  font-family: Inter, 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--body);
  background: var(--brand-tint);
  margin: 0;
  /* THREE DECLARATIONS, DELIBERATELY, LAST-SUPPORTED-WINS (2026-09-22).
   *
   * `footer { margin-top: auto }` pushes the footer to the bottom of this flex
   * column, so the footer's position is only ever as correct as this height.
   * On iOS Safari `100vh` is the LARGE viewport — it EXCLUDES the browser
   * chrome — so the body was taller than the visible area and the footer was
   * pushed below the fold, behind the toolbar. Measured on a real iPhone 12 /
   * iOS 14: the footer did not appear in the viewport at all, while Windows
   * Chrome showed it correctly.
   *
   * That footer carries "help: contact your administrator" — the ONLY help
   * route on the page. So on legacy Safari the refusal screen, whose copy tells
   * the person to ask their administrator, was a dead end.
   *
   *   100vh                    baseline, every browser
   *   -webkit-fill-available   iOS Safari: the ACTUAL visible height
   *   100dvh                   modern browsers: dynamic viewport, and it wins
   *                            here because anything supporting dvh also gets
   *                            it right without the WebKit keyword */
  min-height: 100vh;
  min-height: -webkit-fill-available;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  -webkit-font-smoothing: antialiased;
}

/* --- masthead: brand identity, so the page reads as ours, not as a blank form --- */
header {
  width: 100%;
  max-width: 560px;
  padding: 32px 16px 4px;
  display: flex;
  align-items: center;
  gap: 12px;
}

/* The real SMS Speedway wordmark. Height is fixed and width follows the 3.035:1
 * aspect ratio of the source SVG, so it never distorts. `display:block` avoids
 * the inline-baseline gap that adds stray height under an <img>. */
header .wordmark {
  display: block;
  height: 38px;
  width: auto;
  flex: 0 0 auto;
}

/* A sky rule under the masthead ties the header to the brand's dominant colour
 * without repainting the page. This is the accent the previous design omitted.
 *
 * WHY THIS IS A BORDER AND NOT A ::after PSEUDO-ELEMENT (2026-09-16).
 * The first attempt used `header::after { position:absolute; bottom:0; ... }`.
 * `header` is `display:flex`, so its ::after is a FLEX ITEM, and the absolutely
 * positioned box resolved to a zero-height sliver that painted nothing — the
 * visual gate measured `background-image: none` on the pseudo-element and the
 * accent was invisible in the served page while looking perfectly correct in the
 * CSS source. A border-bottom cannot interact with flex layout, so it renders
 * unconditionally. Verified by computed style, not by reading the file. */
header {
  /* A PAINTED BACKGROUND STRIP, not a border-image (2026-09-22).
   *
   * The previous rule was `border-bottom: 3px solid transparent` plus
   * `border-image: linear-gradient(...) 1`. On iOS 14 Safari that paints the
   * gradient around ALL FOUR EDGES, so the masthead rendered as a navy box with
   * a cyan top edge instead of a rule underneath it. Measured on a real
   * iPhone 12 / iOS 14 via BrowserStack, against Windows Chrome rendering the
   * same page correctly.
   *
   * The comment this replaces said "Verified by computed style, not by reading
   * the file." Computed style proves the border-image EXISTS; it cannot prove it
   * PAINTS CORRECTLY, and on the one browser family this estate goes out of its
   * way to support it did not. That is the whole lesson: the check measured the
   * wrong fact.
   *
   * A background strip has none of that ambiguity — it cannot leak onto other
   * edges because it is positioned, and (like the border it replaces) it does
   * not interact with this element's flex layout, which is what killed the
   * original ::after attempt. */
  background-image: linear-gradient(90deg, var(--brand) 0%, var(--brand-sky) 100%);
  background-repeat: no-repeat;
  background-size: 100% 3px;
  background-position: left bottom;
  padding-bottom: 7px;   /* was 4px; +3px so the rule does not sit under the text */
}

header .sub {
  color: var(--muted);
  font-size: 13px;
  margin-top: 1px;
}

main {
  width: 100%;
  max-width: 560px;
  padding: 12px 16px 48px;
}

.card {
  background: #fff;
  border-radius: 12px;
  padding: 28px;
  border: 1px solid var(--line);
  /* ORDER MATTERS: the `border` shorthand above resets every side, so the sky
   * accent must be declared AFTER it. Declared before, it was silently
   * overwritten and the card rendered with a plain grey top edge. */
  border-top: 3px solid var(--brand-sky);
  box-shadow: 0 1px 2px rgba(16, 24, 40, .06);
  margin-top: 16px;
}

.card h1 {
  font-size: 19px;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 4px;
}

.card .lede {
  font-size: 14px;
  color: var(--body);
  margin: 0 0 18px;
}

label {
  display: block;
  font-size: 14px;
  color: var(--ink);
  font-weight: 500;
  margin-bottom: 6px;
}

input[type=text] {
  /* iOS Safari keeps a NATIVE appearance on form controls and does not paint
   * box-shadow on them. Measured on a real iPhone 12 / iOS 14 (2026-09-22):
   * computed `box-shadow: none` on :focus, where Windows Chrome returned the
   * expected `rgb(3,63,99) 0 0 0 2px`. The focus ring therefore fell back to the
   * 1px border-colour change alone — TIDIER than the square outline it replaced,
   * but FAINTER, which is the wrong direction for a focus indicator.
   *
   * Resetting the appearance is what lets box-shadow paint. Keeping the explicit
   * background/border below matters because the reset also removes the control's
   * native chrome — without them the field would lose its own outline on iOS. */
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 16px;
  font-family: inherit;
  color: var(--ink);
  background: #fff;
}

input[type=text]:focus {
  /* box-shadow, not outline, for the VISIBLE ring (2026-09-22).
   *
   * `outline` only follows `border-radius` from Safari 16.4 / Chrome 94. On
   * iOS 14 it renders as a SQUARE ring around this 8px-rounded field — measured
   * on a real device. `box-shadow` follows the radius everywhere.
   *
   * The outline is KEPT, transparent. In forced-colors / high-contrast mode the
   * OS discards box-shadow and repaints a transparent outline, so removing it
   * outright would leave high-contrast users with no focus indicator at all —
   * trading a cosmetic defect on one browser for an accessibility defect on
   * another. */
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand);
  outline: 2px solid transparent;
  outline-offset: 1px;
}

button {
  width: 100%;
  margin-top: 14px;
  background: var(--brand);
  color: var(--brand-ink);
  border: 0;
  border-radius: 8px;
  padding: 12px 18px;
  font-size: 16px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
}

/* The primary action carries the brand PAIR: navy fill (contrast-safe for white
 * text) with the sky accent as a focus/hover edge. Using sky as the fill would
 * fail contrast against white text at ~1.9:1, so the accent is applied where it
 * is decorative rather than load-bearing — the same reasoning the Conversations
 * PWA applies to its sent bubbles. */
button {
  box-shadow: 0 0 0 0 var(--brand-sky);
  transition: box-shadow .15s ease, background .15s ease;
}

button:hover {
  background: #022c47;
  box-shadow: 0 0 0 3px rgba(55, 204, 251, .35);
}

button:focus-visible {
  outline: 2px solid var(--brand-sky);
  outline-offset: 2px;
}

button.secondary {
  background: #fff;
  color: var(--body);
  border: 1px solid var(--line);
}

button.secondary:hover { background: #f9fafb; }

.notice {
  background: #eff6ff;
  border: 1px solid #bfdbfe;
  color: #1e3a8a;
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 14px;
  margin-top: 12px;
}

.context {
  font-size: 14px;
  color: var(--body);
  margin-top: 14px;
}

.methods {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  background: #fff;
  /* THE INVISIBLE-CONTROL FIX (2026-09-19). This rule painted a white
   * background and declared NO colour, so the `button` element rule's
   * `color: var(--brand-ink)` — which is #ffffff, correct for the navy
   * primary — was left in force. A class beats an element selector, so the
   * class won the background and the element won the colour: every plain
   * `button.tile` rendered white-on-white BY CONSTRUCTION. Measured live on
   * the phone phrase gate: text rgb(255,255,255) on rgb(255,255,255) = 1.0:1,
   * and Brad hit it mid-ceremony — "The continue button is white text on
   * white button on white background so I couldn't see it." `button.secondary`
   * escaped only because it sets its own colour, which is why the adjacent
   * "Regenerate" tile measured a healthy 13.54:1 and the defect hid.
   *
   * A tile is a light control, so its text colour must be declared HERE,
   * beside the background it sits on. tests/test_auth_css_contrast.py computes
   * this pair from this file and refuses anything below WCAG AA. */
  color: var(--ink);
  cursor: pointer;
  font-size: 15px;
  width: 100%;
  font-family: inherit;
}

.tile:hover { background: #f9fafb; }

.qr { text-align: center; margin-top: 14px; }

.qr img {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
}

.qr .countdown {
  color: var(--muted);
  font-size: 13px;
  margin-top: 6px;
}

.qr a { color: var(--brand); font-size: 14px; }

.tile.locked { color: var(--muted); cursor: not-allowed; }

.tile .unlock { color: var(--brand); font-size: 13px; }

.status {
  color: var(--muted);
  font-size: 12px;
  margin-top: 18px;
  text-align: center;
}

.error {
  color: var(--danger);
  font-size: 14px;
  margin-top: 12px;
}

footer {
  color: var(--muted);
  font-size: 12px;
  margin-top: auto;
  padding: 16px;
  text-align: center;
}

/* --- small screens: comfortable touch targets, no cramped card --- */
@media (max-width: 480px) {
  header { padding: 24px 16px 4px; }
  .card { padding: 22px 18px; }
  button, input[type=text] { font-size: 16px; }  /* >=16px prevents iOS zoom-on-focus */
}
