/* login.css — the auth screens, ported token-for-token from `src/login.rs`.
 *
 * Every colour, size and gap here has a named counterpart in that file; the
 * comments give the constant so the two can be diffed by eye. The screens used
 * to be painted on the wasm canvas, which left no DOM for a password manager to
 * fill — that, and nothing about the design, is why they moved.
 *
 * Three things to know before editing:
 *
 * - Nothing is rounded. `style_auth_fields` sets `Rounding::ZERO` on every
 *   widget class, and the card and segmented track pass it explicitly. The
 *   exceptions are the docs link's hover chip at 4px and the paywall's plan
 *   card at 8px. The mockups under `design/sign-in/` show 6px/8px radii
 *   throughout and read "skew.bot" — they predate commits 27b651e and 9168838
 *   and are stale. The shipped Rust is the reference.
 *
 * - egui adds `item_spacing.y`, left at its default 3.0, between every stacked
 *   widget, *on top of* whatever `ui.add_space(N)` asked for. So a literal
 *   `add_space(18)` in login.rs is a 21px margin here, and two adjacent widgets
 *   with no add_space between them sit 3px apart. The `.mt-*` helpers at the
 *   bottom carry that arithmetic.
 *
 * - Bordered controls use an inset `box-shadow`, not `border`. egui centres its
 *   1px stroke on the rect edge and takes no width from the content, so a real
 *   CSS border would quietly shrink every 320px content box to 318.
 */

@font-face {
  /* The exact face egui draws with: epaint 0.27's bundled Ubuntu-Light.ttf,
     subsetted to Latin plus the punctuation these screens use. Licence in
     UFL.txt alongside, as the Ubuntu Font Licence requires. `block` rather
     than `swap` — a brief blank beats reflowing off a fallback face. */
  font-family: 'Ubuntu Light';
  src: url('./ubuntu-light.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: block;
}

:root {
  --accent:       #A855F7;  /* AUTH_ACCENT       — --color-fd-primary */
  --accent-muted: #3B1A5C;  /* AUTH_ACCENT_MUTED — primary fill, text selection */
  --border:       #1F1F1F;  /* AUTH_BORDER       — --color-fd-border */
  --fg:           #EBEBEB;  /* AUTH_FOREGROUND   — --color-fd-foreground */
  --muted:        #B3B3B3;  /* AUTH_MUTED        — labels, status */
  --muted-dim:    #929292;  /* AUTH_MUTED_DIM    — the "or" label */
  --card:         #0D0D0D;  /* AUTH_CARD_FILL    — --color-fd-card */
  --field:        #000000;  /* AUTH_FIELD_FILL */
  --segment-on:   #1A1A1A;  /* AUTH_SEGMENT_ACTIVE — --color-fd-accent */
  --error:        #F43F5E;  /* AUTH_ERROR        — --color-dealer-downside */

  /* egui-derived values with no named constant, read out of its dark theme.
     `--hint-text` is `weak_text_color()` = tint(gray(140), fade_out_to_color()),
     and `fade_out_to_color()` is `noninteractive.weak_bg_fill` = gray(27) —
     not the panel fill — so the blend lands on gray(83). */
  --input-text:   #B4B4B4;  /* widgets.inactive.text_color() = gray(180) */
  --hint-text:    #535353;  /* weak_text_color() */
  --caret:        #C0DEFF;  /* the text cursor stroke */
  --fade-to:      #1B1B1B;  /* fade_out_to_color() = gray(27), blended 50% */

  --card-w: 320px;          /* the card's content width */
  --card-pad: 28px;         /* AUTH_CARD_PAD */

  /* epaint lays a line out at (hhea ascent + |descent| + lineGap) / unitsPerEm.
     Read off the very Ubuntu-Light.ttf this page embeds: (932 + 189 + 28)/1000.
     Every text run sets its line-height from this, so a 13px label occupies
     14.937px here exactly as it does on the canvas. */
  --lh: 1.149;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: #000;         /* CentralPanel Frame::none().fill(Color32::BLACK) */
  color: var(--fg);
  font-family: 'Ubuntu Light', Ubuntu, system-ui, -apple-system, sans-serif;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  color-scheme: dark;
}

::selection { background: var(--accent-muted); }

/* ---------------------------------------------------------------------------
 * Stage and card
 * ------------------------------------------------------------------------ */

.stage {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 0 16px 40px;     /* auth_card's `.max(16.0)` minimum gutter */
  /* `ui.add_space(((avail.y - 560.0) * 0.35).max(24.0))`, plus the 3px
     item_spacing that follows it. */
  padding-top: max(27px, calc((100vh - 560px) * 0.35 + 3px));
}

/* render_forgot_password measures against 470 rather than 560. */
.stage[data-view="reset"] {
  padding-top: max(27px, calc((100vh - 470px) * 0.35 + 3px));
}

/* render_subscription_required opens with a bare add_space(10) beneath its own
   top bar, with no centring arithmetic at all. */
.stage[data-view="subscribe"] { padding-top: 13px; }

.card {
  width: calc(var(--card-w) + var(--card-pad) * 2);   /* 320 + 56 = 376 */
  padding: var(--card-pad);
  background: var(--card);
  box-shadow: inset 0 0 0 1px var(--border);
  border-radius: 0;
}

/* The paywall has no card frame at all — render_subscription_required puts its
   content straight on black at a 360px width. */

/* ---------------------------------------------------------------------------
 * Brand header — the 267x52 bitmap, drawn at 30px tall like render_auth_brand
 * ------------------------------------------------------------------------ */

.brand {
  display: block;
  width: 154px;             /* 30 * (267 / 52) = 154.04 */
  height: 30px;
  margin: 0 auto;
}

/* ---------------------------------------------------------------------------
 * Segmented control — auth_segmented_control
 * ------------------------------------------------------------------------ */

.segmented {
  display: flex;
  gap: 4px;                 /* AUTH_TRACK_PAD, as item_spacing.x */
  width: var(--card-w);
  padding: 4px;             /* AUTH_TRACK_PAD */
  background: #000;
  box-shadow: inset 0 0 0 1px var(--border);
}

.segment {
  flex: 0 0 154px;          /* (track_w - AUTH_TRACK_PAD) / 2 = (312 - 4) / 2 */
  height: 36px;             /* AUTH_SEGMENT_HEIGHT */
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 14px;          /* AUTH_LABEL_SIZE + 1 */
  line-height: calc(14px * var(--lh));
  cursor: pointer;
}

.segment[aria-selected="true"] {
  background: var(--segment-on);
  color: var(--fg);
}

/* ---------------------------------------------------------------------------
 * Labels and fields
 * ------------------------------------------------------------------------ */

.label {
  display: block;
  font-size: 13px;          /* AUTH_LABEL_SIZE */
  line-height: calc(13px * var(--lh));
  color: var(--muted);
}

/* The "password" label and the "forgot password?" link share a row, with the
   field below spanning both columns.
 *
 * The link is placed here rather than ordered here: it comes after the field in
 * the DOM so Tab runs email -> password -> forgot password -> sign in, the
 * order login.rs:1408-1412 goes out of its way to preserve. Grid moves it up a
 * row without touching the tab sequence, which is why this is not a flexbox
 * with a positive `tabindex` — positive tabindex values are visited before
 * every tabindex="0" on the page, so that version tabs to the password field
 * first and reaches the email field last. */
.pw-block {
  display: grid;
  /* The label sizes to its text and the link's column takes the slack, so the
     link right-aligns at its natural width. `1fr auto` looks equivalent and is
     not: `1fr` is greedy, which squeezes the link to its min-content width and
     wraps "forgot password?" onto two lines, making the row 15px taller than
     egui's. */
  grid-template-columns: auto 1fr;
  align-items: baseline;
}

.pw-block > .label { grid-area: 1 / 1; }
.pw-block > .link  { grid-area: 1 / 2; justify-self: end; white-space: nowrap; }
.pw-block > .field { grid-area: 2 / 1 / 3 / 3; }

.field {
  display: block;
  width: var(--card-w);
  margin-top: 3px;          /* item_spacing.y — login.rs adds no space here */
  /* Margin::symmetric(10.0, AUTH_FIELD_MARGIN_Y) around one 15px row.
     TextEdit allocates 320 x (15 * 1.149 + 26) = 320 x 43.235, so the height
     falls out of the same arithmetic rather than being asserted. */
  padding: 13px 10px;
  background: var(--field);
  border: 0;
  border-radius: 0;
  box-shadow: inset 0 0 0 1px var(--border);
  color: var(--input-text);
  caret-color: var(--caret);
  font: inherit;
  font-size: 15px;          /* AUTH_INPUT_SIZE */
  line-height: calc(15px * var(--lh));
}

/* style_auth_fields points both hovered and active bg_stroke at the accent.
   egui also grows the rect 1px on every side via `visuals.expansion`; that is
   left out deliberately — in CSS it costs either a reflow or a fake ring, for a
   difference nobody can see. */
.field:hover,
.field:focus { box-shadow: inset 0 0 0 1px var(--accent); outline: none; }

.field::placeholder { color: var(--hint-text); opacity: 1; }

.field:read-only { color: var(--muted-dim); }

/* Chrome paints its own autofill background over the field. Hold the design. */
.field:-webkit-autofill,
.field:-webkit-autofill:hover,
.field:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--input-text);
  -webkit-box-shadow: inset 0 0 0 1px var(--border), inset 0 0 0 1000px var(--field);
  caret-color: var(--caret);
}

/* ---------------------------------------------------------------------------
 * Buttons — auth_primary_button / auth_secondary_button
 * ------------------------------------------------------------------------ */

.btn {
  display: block;
  width: var(--card-w);
  border: 0;
  border-radius: 0;
  font: inherit;
  font-size: 15px;          /* AUTH_BUTTON_SIZE */
  line-height: calc(15px * var(--lh));
  color: var(--fg);
  cursor: pointer;
}

.btn-primary {
  height: 48px;             /* AUTH_PRIMARY_HEIGHT */
  background: var(--accent-muted);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.btn-secondary {
  height: 44px;             /* AUTH_SECONDARY_HEIGHT */
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--border);
}

/* egui fades a disabled widget 50% toward fade_out_to_color() = gray(27). */
.btn:disabled {
  cursor: default;
  color: color-mix(in srgb, var(--fg) 50%, var(--fade-to));
}

.btn-primary:disabled {
  background: color-mix(in srgb, var(--accent-muted) 50%, var(--fade-to));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 50%, var(--fade-to));
}

.btn-secondary:disabled {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 50%, var(--fade-to));
}

/* ---------------------------------------------------------------------------
 * Links — ui.link
 *
 * egui draws the hover underline in `visuals.hyperlink_color`, left at its dark
 * default #5AAAFF, so "forgot password?" currently underlines *blue* under
 * purple text. That is an egui default nobody chose; underline in currentColor.
 * ------------------------------------------------------------------------ */

.link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;          /* AUTH_LABEL_SIZE */
  line-height: calc(13px * var(--lh));
  color: var(--muted);
  cursor: pointer;
  text-decoration: none;
  text-decoration-color: currentColor;
}

.link:hover { text-decoration: underline; }
.link-accent { color: var(--accent); }

/* ---------------------------------------------------------------------------
 * "or" divider — auth_or_divider
 *
 * rule_len = (320 - width("or")) / 2 - GAP. A flex row with two `flex: 1` rules
 * and a 10px gap lands on the same number without hard-coding it.
 * ------------------------------------------------------------------------ */

.or {
  display: flex;
  align-items: center;
  gap: 10px;                /* GAP */
  height: 18px;
  width: var(--card-w);
}

.or::before,
.or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.or span {
  font-size: 12px;          /* AUTH_LABEL_SIZE - 1 */
  line-height: calc(12px * var(--lh));
  color: var(--muted-dim);
}

/* ---------------------------------------------------------------------------
 * Status line, separator, docs link
 * ------------------------------------------------------------------------ */

.status {
  margin: 0;
  font-size: 13px;          /* AUTH_LABEL_SIZE */
  line-height: calc(13px * var(--lh));
  color: var(--muted);
}

.status[data-failure="true"] { color: var(--error); }

/* ui.separator() allocates a 6px box and paints a 1px rule down its middle. */
.separator {
  height: 6px;
  border: 0;
  margin: 0;
  background: linear-gradient(var(--border), var(--border)) center / 100% 1px no-repeat;
}

.docs-row { display: flex; justify-content: center; }

.docs {
  display: inline-flex;
  align-items: center;
  gap: 7px;                 /* the gap in auth_docs_link */
  height: 28px;
  padding: 0 10px;          /* auth_docs_link's `total_w + 20.0` hit box */
  border: 1px solid transparent;
  border-radius: 4px;       /* Rounding::same(4.0) — the one rounded control */
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 14px;
  line-height: calc(14px * var(--lh));
  text-decoration: none;
  cursor: pointer;
}

.docs svg { width: 15px; height: 16px; flex: none; }

.docs:hover {
  color: var(--fg);
  background: #181818;
  border-color: #2E2E2E;
}

.docs:active {
  color: var(--fg);
  background: var(--accent-muted);
  border-color: var(--accent);
}

/* ---------------------------------------------------------------------------
 * Reset screen
 * ------------------------------------------------------------------------ */

.title {
  margin: 0;
  font-size: 18px;          /* AUTH_TITLE_SIZE */
  line-height: calc(18px * var(--lh));
  color: var(--fg);
}

/* The eyebrow over the waitlist and closed panels. It names the state before
   the explanation under it, so a first-time visitor reads why the card looks
   like this instead of inferring it from a paragraph. */
.capacity {
  margin: 0;
  font-size: 11px;
  line-height: calc(11px * var(--lh));
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-dim);
}

.helper {
  margin: 0;
  font-size: 13px;          /* AUTH_LABEL_SIZE */
  line-height: calc(13px * var(--lh));
  color: var(--muted);
}

/* ---------------------------------------------------------------------------
 * Paywall — render_subscription_required
 *
 * This screen was never migrated to the AUTH_* tokens; it still carries egui's
 * named colours, default button fills and an 8px radius from before the auth
 * restyle. The literals below are ported as they stand rather than quietly
 * modernised, so this stays a move and not a redesign.
 * ------------------------------------------------------------------------ */

.topbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  min-height: 34px;
  padding: 0 8px;
}

/* The offer, grouped by spacing rather than by a box.
   ----------------------------------------------------------------------------
   This was a port of an egui panel — 8px rounding, its own #0C0C0E fill and its
   own #36363E stroke — and it sat on a card that had been stripped of its
   border. That left the plan as the only outlined thing on the screen while the
   heading, the address and the sign-out button floated outside it.

   The card now carries the border, exactly as the sign-in card does. A second
   outline inside it would be a box in a box, over a fill one value away from the
   card's own, with a rounding the rest of the page does not use. So the plan
   keeps only its rhythm. */
.plan {
  padding: 0;
}

.plan-name  { margin: 0; font-size: 17px; line-height: calc(17px * var(--lh)); color: #FFF; }
.plan-blurb { margin: 0; font-size: 12px; line-height: calc(12px * var(--lh)); color: #90EE90; }
.plan-list  { margin: 0; padding: 0; list-style: none; }
.plan-list li { font-size: 12px; line-height: calc(12px * var(--lh)); color: #A0A0A0; }

/* The gate's answer, inside the plan card. Same 12px as the feature list it
   sits under, in the foreground colour rather than the list's gray, because it
   is the one line on this screen that is news. */
.plan-note  { margin: 0; font-size: 12px; line-height: calc(12px * var(--lh)); color: var(--fg); }

/* The gate's answer arrives from `login.js` as one string, and the waitlist
   case is two paragraphs — it has to set expectations about the order of the
   list and about the early access rate, which one sentence cannot carry.
   `pre-line` lets the blank line in that string be the paragraph break, so
   the note stays a single element with a single voice. */
.plan-note { white-space: pre-line; text-wrap: pretty; }

/* With the gate shut the plan still describes the product, but the price is no
   longer an offer — fade it and the list so the note above the button leads.
   Set from `applySubscribeAdmission`, which is the only thing that knows. */
.plan[data-gated="true"] .plan-blurb,
.plan[data-gated="true"] .plan-list { opacity: .55; }

.sub-heading { margin: 0; font-size: 18px; line-height: calc(18px * var(--lh)); color: #FFF; }
.sub-note    { margin: 0; font-size: 12px; line-height: calc(12px * var(--lh)); color: #A0A0A0; }

.sub-status  { margin: 0; font-size: 12px; line-height: calc(12px * var(--lh)); color: #A0A0A0; }
.sub-status[data-failure="true"] { color: #DC5A5A; }  /* from_rgb(220, 90, 90) */

/* The paywall's buttons are the card's buttons.
   ----------------------------------------------------------------------------
   `subscribe`, `join waitlist` and `sign out` each carried a private style: a
   #3C3C3C fill from egui's dark default, white or red text, a 2px rounding and
   a hard 360px width that matched the card only while the card had no border.
   Nothing else on the page looked like that, so the paywall read as a different
   product from the sign-in card two clicks earlier.

   They now use `.btn` with `.btn-primary` or `.btn-secondary` — the same pair
   the sign-in card uses, so the accent fill, the stroke, the width and the
   square corners all come from one place.

   `sign out` keeps only its colour. It is the one destructive action on the
   card, and the secondary treatment with a red label says so without inventing
   a third kind of button. */
.btn-signout {
  color: #FF7878;            /* Color32::from_rgb(255, 120, 120) */
}

/* `.btn:disabled` fades toward the foreground colour, which is not this one. */
.btn-signout:disabled {
  color: color-mix(in srgb, #FF7878 50%, var(--fade-to));
}

/* ---------------------------------------------------------------------------
 * Loading interstitial — render_centered_message
 * ------------------------------------------------------------------------ */

.loading {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: max(40px, calc((100vh - 40px) * 0.5));
  font-size: 16px;
  color: #A0A0A0;           /* Color32::GRAY */
}

/* ---------------------------------------------------------------------------
 * Vertical rhythm.
 *
 * Each value is `add_space(N) + item_spacing.y`, or a bare 3 where login.rs
 * stacked two widgets with nothing between them.
 * ------------------------------------------------------------------------ */

.mt-3  { margin-top: 3px;  }   /* adjacent widgets */
.mt-11 { margin-top: 11px; }   /* add_space(8)  */
.mt-13 { margin-top: 13px; }   /* add_space(10) */
.mt-15 { margin-top: 15px; }   /* add_space(12) */
.mt-17 { margin-top: 17px; }   /* add_space(14) */
.mt-19 { margin-top: 19px; }   /* add_space(16) */
.mt-21 { margin-top: 21px; }   /* add_space(18) */
.mt-23 { margin-top: 23px; }   /* add_space(20) */

[hidden] { display: none !important; }
