/* ══════════════════════════════════════════════════════════════════════════
   The sign-in page, and the setup page's panel.

   ── measured off the CRM, not designed beside it ──────────────────────────

   This file used to invent its own version of the CRM's sign-in: a hero blue
   of #2E90E4 where the logo blue is #1a7fd4, a glow in the wrong place and the
   wrong colour, a wordmark asking for a weight the face does not have
   so the browser was faking a bold and the logo came out smeared), a 420px
   form column against the CRM's 470px, an h2 two pixels smaller, and a border
   down the join that the CRM does not have. Every one of those is invisible on
   its own. Together they are two products.

   So the numbers below were read off https://crm.ultracns.app with the
   computed styles rather than matched by eye. Where the two pages differ they
   differ on purpose, and say so.

   Read them WHOLE, too: the first pass at this dropped the panel's glow
   entirely, because the string had been truncated mid-value and "radial-" was
   sliced off the front of it. A background read as half a shorthand is a
   background you have not read.

   ultra-shell.css already carries identical tokens and the identical two faces
   (Space Grotesk, DM Sans), embedded. Nothing here names a colour that is not the
   dark panel's own.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* The panel is dark in BOTH themes: it is a brand surface, not a reading
     surface, which is the decision the CRM's sign-in makes too. So its colours
     are named here rather than taken from tokens that flip — but they are the
     CRM's colours, to the digit. */
  /* The UltraCNS sign-in kit's two faces. These pages carry the house
     sign-in look rather than the console's, so the door is the same door in
     every Ultra product; the shell's DM Sans and Space Grotesk resume on the
     other side of it.

     Both are PACKAGED now, in ultra-shell/fonts/ beside the package's own
     five. They were fetched from fonts.googleapis.com on every load, which
     told Google each time somebody opened the door to a privileged-access
     product -- and made the one screen whose job is to look like the product
     depend on a network a vessel may not have. The package's rule was always
     "nothing is fetched at runtime"; these two pages were outside
     <ultra-shell> and outside the rule with it. */
  --f-ui:       'Barlow', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --f-display:  'Bebas Neue', 'Barlow', ui-sans-serif, sans-serif;
  --brand:      #1a7fd4;
  --accent:     #1569B8;

  --hero-deep:  #060F1E;               /* = --navy, the far end of the gradient */
  --hero-near:  #0A1729;               /* the near end */
  --hero-ink:   #FFFFFF;
  --hero-ink-2: #9AA3B4;               /* the paragraph */
  --hero-ink-3: rgba(255,255,255,.38); /* the footer strip */
  --hero-ink-4: rgba(255,255,255,.55); /* under the wordmark */
  --hero-node:  #4E6884;               /* the constellation's quiet nodes */

  /* ── the constellation, fitted rather than chosen ──────────────────────
     Read by brand.js on every sizing pass.

     These were 26000 / 300 / .30. The gradient underneath was already
     pixel-identical to the CRM's — 35 samples across the panel, every one
     within 2/255 — and the field on top was still adding 2.2x the light over
     3.5x the area, with lit pixels a median 150px apart against the CRM's
     510px. A network ACROSS the panel where the CRM's fades out of it, which
     is what "the dark blue is everywhere" meant.

     tools/field-fit.py measures both fields in one browser at one viewport
     and searches. What it found is counter-intuitive and would not have been
     guessed: FEWER nodes and LONGER links at LOWER alpha. Many short faint
     lines read as texture over everything; a few long ones read as a network
     with space around it.

         CRM     ink 0.027   cover 0.14%   gap 510px
         these   ink 0.027   cover 0.14%   gap 370px

     Re-fit with `python tools/field-fit.py --search` if either page moves. */
  --field-density: 42000;   /* px² of panel per node */
  --field-reach:   360;     /* longest link, px */
  --field-line:    .22;     /* per-line alpha at zero gap */
  --field-dot:     .40;     /* the quiet nodes */
  --field-dot-lit: .75;     /* the brighter ones */

  /* ── the scale, as measured ─────────────────────────────────────────────
     Named by role rather than by number, and not folded together where two
     roles happen to agree today: each of these was read off the CRM on its
     own and is defended on its own in the comment beside its rule, so a
     later divergence should read as a decision and not as drift.

     The door keeps its OWN scale rather than the shell's, and that is the
     point of the page: signin.html and setup.html sit outside <ultra-shell>
     so that the door is the same door in every Ultra product. These tokens
     are the CRM's numbers, held in one place so they stop being retyped. */
  --door-body:            15px;    /* the page, and what a control inherits */
  --door-wordmark:        41px;
  --door-wordmark-narrow: 24px;    /* in the form column, below 900px */
  --door-wordsub:         9px;
  --door-eyebrow:         12px;
  --door-headline:        clamp(30px, 4.6vw, 56px);
  --door-lede:            14px;    /* the hero paragraph */
  --door-strip:           9px;     /* the dotted meta strip */
  --door-h2:              21px;
  --door-sub:             13px;    /* the line under the heading */
  --door-label:           11.5px;
  --door-field:           13.5px;
  --door-vessel:          13.5px;  /* the vessel buttons */
  --door-code:            19px;    /* the one-time code, as drawn */
  --door-role:            10.5px;
  --door-hint:            12.5px;
  --door-refusal:         12.5px;
  --door-remember:        12.5px;
  --door-build:           11.5px;
  --door-btn:             13px;
  --door-rule:            12px;    /* the OR between the two routes */
  --door-key:             13px;    /* the setup page's TOTP secret */

  /* Barlow ships as static weights, so these are faces rather than points on
     a variable axis -- except 650, which no Barlow file carries. The browser
     synthesises it from 700 and always did; Google was never sending one
     either. It is written as 650 because that is what the CRM asks for. */
  --door-w-lede:   300;
  --door-w-normal: 400;
  --door-w-medium: 500;
  --door-w-label:  600;
  --door-w-h2:     650;

  --door-track-mark:    .02em;   /* wordmark, headline, build line */
  --door-track-sub:     .14em;
  --door-track-eyebrow: .26em;
  --door-track-strip:   .3em;
  --door-track-h2:      -.025em;
  --door-track-code:    .34em;
  --door-track-role:    .08em;
  --door-track-wide:    .06em;   /* the OR rule, and the TOTP key */
  --door-track-none:    normal;
  --door-track-flat:    0;       /* see .form .lbl: two spellings, one intent */

  --door-lh-tight:    1;
  --door-lh-headline: 1.02;
  --door-lh-vessel:   1.3;
  --door-lh-note:     1.45;
  --door-lh-block:    1.5;
  --door-lh-body:     1.55;
  --door-lh-key:      1.6;
  --door-lh-lede:     1.65;
}

/* ── the split ────────────────────────────────────────────────────────────
   A fixed 470px column, as on the CRM. It was minmax(360px, 420px), which is
   a sign-in form that changes width between the two products for no reason a
   person could name. */
.split {
  display: grid;
  grid-template-columns: 1fr 470px;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ── the brand half ─────────────────────────────────────────────────────── */
/* These two pages sit OUTSIDE <ultra-shell> on purpose -- there is no
   navigation to wrap around somebody who is not signed in yet -- and the
   package puts its typeface on .ultra-shell, not on body. So nothing set a
   font here at all: body and every form control fell back to the browser
   default and rendered in TIMES NEW ROMAN, while the headline and the field
   labels, which name their faces explicitly, came out in Space Grotesk and DM
   Sans. Three typefaces on the first screen of the product.

   Inputs and buttons do not inherit font from body on their own -- that is a
   UA stylesheet rule, not an inheritance one -- so they are told to. */
body {
  /* margin:0 is the third thing these pages needed for the same reason as the
     typeface and box-sizing: they sit OUTSIDE <ultra-shell> deliberately, and
     the package's base rules never reach them. Nothing here reset the user
     agent's 8px, so the whole page sat 8px in -- a band of paper above and
     beside a panel that is meant to run to the edge of the glass, which is
     what Jag kept marking on the screenshots.
     It was also making a scrollbar: .split is min-height:100vh, and 100vh plus
     16px of margin is taller than the window every time. That scrollbar is why
     the panel measured 499px against the sibling's 530 -- a layout difference
     that was really this margin wearing a different hat. */
  margin: 0;
  font-family: var(--f-ui);
  font-size: var(--door-body);
  line-height: var(--door-lh-body);
  color: var(--ink-800);
}
input, select, textarea, button { font: inherit; }

/* border-box, for the same reason as the font: the package sets it on
   .ultra-shell * and these two pages sit outside that. The visible symptom was
   the Continue button ending 28px short of the field above it -- both are
   width:100%, but the input was content-box, so its 13px of padding and 1px of
   border were added ON TOP of the 336px it shared with the button. Two
   controls in one column, told the same width, drawn different lengths. */
*, *::before, *::after { box-sizing: border-box; }

.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 44px;
  /* A brand-blue glow in the top-right — where the panel is empty, rather than
     behind the headline — over the gradient. The CRM's, to the digit, and in
     both themes: it is part of the panel, not a dark-mode flourish. */
  /* Literal rgba, not color-mix against a token. The kit is explicit about
     this and this file has already paid for it once: the glow used to mix
     from var(--brand), that token was later deleted, and an invalid
     color-mix takes the whole declaration with it -- the layer vanished with
     no error and left a flat panel. */
  background:
    radial-gradient(120% 90% at 78% 18%, rgba(26,127,212,.22), rgba(6,15,30,0) 62%),
    linear-gradient(168deg, #0A1729, #060F1E);
  color: #D6DAE4;
  isolation: isolate;
}

/* Decorative: painted, never read. The opacity is on the canvas rather than in
   the drawing, so the whole field sits back as one thing. */
#constellation {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: .5;
  z-index: -1;
}

/* ── the wordmark ─────────────────────────────────────────────────────────
   The old display face had ONE weight. Asking for 700 made the browser synthesise a
   bold, which is why the two logos did not match even where the sizes agreed:
   one of them was a smeared copy of the other. 400, 30px, 0.02em, and "CNS"
   in --brand rather than a blue two shades off it. */
/* The gap between the wordmark and "Ultra Cyber Networks" is set HERE and
   nowhere else. It was 6px of flex gap plus a 3px margin-top on .wordsub --
   two controls on one distance, 9px apart in total, and tightening either one
   only ever closed part of it. One lever now: 3px. */
/* The gap you set is not the gap you see. With line-height:1 a 41px line box
   still reserves descender room, and a wordmark in caps has no descenders --
   8px of this distance was empty font metric, which is why turning the gap
   down could never reach it. The slack is cancelled on .wordmark, and then the
   gap is honest: 6px set, 7px on screen. One lever, as before. */
.mark { display: flex; flex-direction: column; gap: 6px;
  line-height: var(--door-lh-tight); }

.wordmark {
  font-family: var(--f-display);
  font-weight: var(--door-w-normal);
  font-size: var(--door-wordmark);
  line-height: var(--door-lh-tight);
  letter-spacing: var(--door-track-mark);
  color: #fff;
  margin-bottom: -8px;   /* the descender slack, measured from the face */
}
.wordmark span { color: var(--brand); }

.wordsub {
  /* --alpha-white-12 is a HAIRLINE token -- it draws the 12%-white borders in
     the shell -- and it had been set as this text's colour, which put "Ultra
     Cyber Networks" at 1.41:1 on the panel. Present in the markup, invisible
     on the screen, which reads as a logo that lost its name. --hero-ink-4 is
     the token this line was written for ("under the wordmark", 55% white):
     6.11:1, and it sits under the logo rather than competing with it.

     10px with a hair less tracking because .34em at 9px had the words closer
     to the letters inside them than to each other. */
  font-family: var(--f-ui);
  font-weight: var(--door-w-label);
  font-size: var(--door-wordsub);
  line-height: var(--door-lh-tight);
  /* .14em, not .28em. Tracking is added per character, so twenty characters of
     "Ultra Cyber Networks" turned .28em into 56px of air and the line came out
     178px wide under a 151px logo -- wider than the wordmark it belongs to,
     which reads as stretched rather than as a lockup. At .14em the two are the
     same width to within a few pixels. */
  letter-spacing: var(--door-track-sub);
  text-transform: uppercase;
  color: rgba(255,255,255,.55);
}

.eyebrow {
  /* 12px, not 9px. It labels the headline under it and was small enough to
     read as a caption on the panel rather than as a heading for anything.
     Tracking eased with the size -- .34em at 12px is a third again as much air
     as it was at 9px, and the words come apart.

     --blue-400 rather than --blue-500: on the hero navy the 500 is 4.26:1,
     which is under AA for text this size, and the point of making it bigger
     was that it be read. The 400 is 6.03:1 and still the brand blue. */
  font-family: var(--f-ui);
  font-weight: var(--door-w-label);
  font-size: var(--door-eyebrow);
  line-height: var(--door-lh-block);
  letter-spacing: var(--door-track-eyebrow);
  text-transform: uppercase;
  /* #3d9be8, not the #1a7fd4 of the mark. Desk lifts the eyebrow a step off
     the brand blue so it reads on the navy, and on this ground the lighter one
     is 6.4:1 against the 4.3:1 of the darker. */
  color: #3d9be8;
  margin-bottom: 12px;
}

/* ── the claim ────────────────────────────────────────────────────────────
   One sentence per line, always.

   It was <br> inside a balanced h1 whose container was capped at 30ch, so
   "PROVE WHO CAME ABOARD." arrived folded across two lines at ordinary widths
   and text-wrap:balance was actively working against the breaks that had been
   asked for. Each sentence is now its own block and will not wrap; the type
   scales with the column instead, so a narrower window makes the words
   smaller rather than breaking them. */
.hero h1 {
  margin: 0;
  /* Measured off desk.ultracns.app rather than taken from the kit: it draws
     46px at a 1000px viewport and 56px at 1512, which is 4.6vw with a cap.
     The kit's 30px is the CRM's, and the two siblings do not agree -- the one
     Jag is looking at wins. */
  font-family: var(--f-display);
  font-weight: var(--door-w-normal);
  font-size: var(--door-headline);
  line-height: var(--door-lh-headline);
  letter-spacing: var(--door-track-mark);
  color: #fff;
}
.hero h1 span { display: block; white-space: nowrap; }

.hero p {
  margin: 15px 0 0;
  max-width: 46ch;
  font-family: var(--f-ui);
  font-weight: var(--door-w-lede);
  font-size: var(--door-lede);
  line-height: var(--door-lh-lede);
  color: var(--hero-ink-2);      /* #9AA3B4, which is what desk paints it */
}

/* The dotted meta strip. It carries the build, which is a real thing to know
   when somebody reports the console did something odd — so it is filled from
   the page rather than typed in. */
.strip {
  font-family: var(--f-ui);
  font-weight: var(--door-w-normal);
  font-size: var(--door-strip);
  line-height: var(--door-lh-block);
  letter-spacing: var(--door-track-strip);
  text-transform: uppercase;
  color: rgba(255,255,255,.55);
}

/* ── the form half ──────────────────────────────────────────────────────── */
.panel {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 34px 22px;
  background: var(--white);
  /* No border down the join. The CRM has none; the gradient's edge is the
     join, and a rule there turns one page into two panels. */
}

.form {
  width: 100%;
  max-width: 336px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.pane { display: none; }
.pane.on { display: flex; flex-direction: column; gap: 16px; }

.form h2 {
  margin: 0;
  font-family: var(--f-ui);
  font-weight: var(--door-w-h2);
  font-size: var(--door-h2);
  line-height: var(--door-lh-block);
  letter-spacing: var(--door-track-h2);
  color: var(--ink-800);
}

/* The heading and the line under it are one thing, so they share a flex child
   rather than being two children of a 16px gap. */
.head { display: block; }
.form .sub {
  margin: 5px 0 0;
  font-family: var(--f-ui);
  font-weight: var(--door-w-normal);
  font-size: var(--door-sub);
  line-height: var(--door-lh-block);
  color: var(--ink-500);
}

.form .fld { display: flex; flex-direction: column; gap: 5px; }

/* Sentence case, on this page only.
   The house .lbl is uppercase and letterspaced, which is right on a dense
   screen of many small fields and wrong on a door with two: "EMAIL ADDRESS"
   over an empty box reads as a form to be processed rather than a question.
   The CRM's sign-in makes the same exception at the same 11.5px, and the two
   doors should ask in the same voice. */
.form .lbl {
  font-family: var(--f-ui);
  font-weight: var(--door-w-label);
  font-size: var(--door-label);
  line-height: var(--door-lh-note);
  letter-spacing: var(--door-track-none);
  text-transform: none;
  color: var(--ink-500);
}

/* .lg on the buttons in the markup, not a height override here: the CRM's
   sign-in uses .btn.pri.lg — 38px and 14px — and the house sheet already has
   that size. This page had the default 32px button, which is the size used in
   a dense table of rows and reads as a secondary action on a door. */
.form .btn.wide { width: 100%; justify-content: center; }

/* ── the vessel choice ────────────────────────────────────────────────────
   Buttons rather than a <select>: there are two or three of them, the choice
   is consequential, and a dropdown hides the fact that a choice exists.

   In Barlow, like the rest of this page, and not the shell's DM Sans it was
   written in. There is no CRM value to copy: the CRM's sign-in has no vessel
   chooser, no refusal line and no build line, because they are all
   SecureAccess's own. So the rule is the one the header of this file already
   states -- on this side of the door, the door's face. Only the face moved;
   the sizes and tracking are as they were measured. */
.vessels { display: flex; flex-direction: column; gap: 7px; }

.vessel {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  padding: 10px 12px;
  text-align: left;
  border: 1px solid var(--alpha-ink-14);
  border-radius: var(--ultra-r-chip);
  background: var(--white);
  color: var(--ink-800);
  font-family: var(--f-ui);
  font-weight: var(--door-w-medium);
  font-size: var(--door-vessel);
  line-height: var(--door-lh-vessel);
  cursor: pointer;
}
.vessel:hover { border-color: var(--blue-500); }
.vessel.on {
  border-color: var(--blue-500);
  background: var(--blue-100);
  color: var(--blue-700);
}
.vessel .role {
  margin-left: auto;
  font-family: var(--f-ui);
  font-weight: var(--door-w-medium);
  font-size: var(--door-role);
  line-height: var(--door-lh-tight);
  letter-spacing: var(--door-track-role);
  text-transform: uppercase;
  color: var(--ink-400);
}
.vessel.on .role { color: var(--blue-700); }

/* ── the refusal ──────────────────────────────────────────────────────────
   One sentence, one place, the same words for every cause. A note rather than
   a red shout, because the ordinary reason somebody sees it is a typo and the
   unusual reason is not one the page should dramatise. */
.refusal {
  font-family: var(--f-ui);
  font-weight: var(--door-w-normal);
  font-size: var(--door-refusal);
  line-height: var(--door-lh-note);
  color: var(--status-critical);
  min-height: 1.45em;
}
/* display:none, not min-height:0. As a zero-height flex child it still took
   the pane's 16px gap, which made this form 12px taller than the CRM's and
   moved the whole thing up by six — every element below out by the same. A row
   with nothing in it should not be a row. */
.refusal:empty { display: none; }

/* The build line, pinned to the bottom of the pane exactly as the CRM pins
   its version line: absolute, full width, centred, 12px off the floor. It was
   a right-aligned monospace line inside the form, which moved with the form —
   so it sat in a different place on each of the three steps. */
.build {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  text-align: center;
  font-family: var(--f-ui);
  font-weight: var(--door-w-normal);
  font-size: var(--door-build);
  line-height: var(--door-lh-block);
  letter-spacing: var(--door-track-mark);
  font-variant-numeric: tabular-nums;
  color: var(--ink-400);
  pointer-events: none;
}

/* The mark belongs to the dark panel above the breakpoint.
   This rule sits BEFORE the media query on purpose: it was after it, where
   two rules of equal specificity meant the later one won and the mark stayed
   hidden at every width — the narrow rule below was dead the moment it was
   written. */
.panel .mark { display: none; }

/* ── narrow ───────────────────────────────────────────────────────────────
   At 900px the CRM drops its brand panel and gives the form the window. The
   same here, at the same number, so the two products change shape at the same
   width rather than at two widths a client will notice and cannot explain. */
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .hero { display: none; }

  /* min-height: 0 was on .split here, and it was a bug only visible on a
     phone: with the hero gone the grid collapsed to the form's own height, so
     the white pane stopped two thirds down the screen with bare --ground
     beneath it, and the build line — pinned to the pane's bottom — landed
     directly under the button. The pane keeps the window.

     Column, not row: .panel is a centring flex row, and the mark added below
     would otherwise sit BESIDE the form rather than above it. */
  .panel {
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    padding: 30px 22px 48px;
  }
  .panel .mark,
  .panel .form { width: 100%; max-width: 380px; }

  /* The wordmark comes back, above the form.
     This is the one place the two pages differ on purpose: the CRM hides its
     whole brand panel at this width, so its sign-in carries no mark at all. A
     door with no name on it is a defect rather than a style — and the SAME
     wordmark in the SAME face is not something a person reads as a different
     product. */
  .panel .mark { display: flex; margin-bottom: 26px; }
  .panel .wordmark { font-size: var(--door-wordmark-narrow); color: var(--ink-800); }
  .panel .wordsub { color: var(--ink-400); }
}

@media (prefers-reduced-motion: reduce) {
  /* The constellation still draws — it just never moves. Handled in brand.js;
     this is here so the intent is visible from the stylesheet too. */
}


/* "Don't ask on this browser" -- one quiet line between the code and the
   button, because the person it serves is mid-sign-in with a code on their
   phone screen. */
.remember { display: flex; gap: 8px; align-items: center;
  font-size: var(--door-remember); color: var(--ink-500); margin: 2px 0 14px;
  cursor: pointer; }
.remember input { accent-color: var(--blue-500); margin: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   THE FORM

   Written here because these two pages sit outside <ultra-shell> and the
   package has no opinion about an <input> -- a dashboard shell does not need
   one.

   This section OVERRIDES the form rules above it rather than adding to them:
   .form .lbl and .form .inp are restated here, at equal specificity and later
   in the file, so these are the ones that draw. The duplication is not
   deliberate. The third of them, an .inp.code block near the vessel choice,
   was dead in every declaration and has been deleted -- it also carried the
   only written statement of what that field is for, nine hundred lines from
   the rule that draws it, which is how the field came to be doing the
   opposite of what its comment promised. What is left here is the .lbl, whose
   two versions disagree only in spelling (`normal` against `0`), and .inp. Every value is a package token, and the controls are the same size and
   shape as the ones inside the console, so signing in and then using the
   product is one continuous thing.
   ══════════════════════════════════════════════════════════════════════════ */

/* The kit's geometry: a 30px field with 3px corners, and the label sitting
   tight to it at a 3px gap rather than floating 6px off. font: inherit first,
   because a control does not take type from the page on its own. */
.form .fld { display: flex; flex-direction: column; gap: 3px; margin-bottom: 14px; }
.form .lbl { font-size: var(--door-label); font-weight: var(--door-w-label);
  color: var(--ink-500); letter-spacing: var(--door-track-flat);
  text-transform: none; }
.form .inp {
  width: 100%; height: 30px; padding: 0 9px; font: inherit;
  font-size: var(--door-field);
  color: var(--ink-800); background: var(--white);
  border: 1px solid #D4D9E2; border-radius: 3px;
}
.form .inp:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--alpha-blue-35); }
.form .inp::placeholder { color: var(--ink-400); }
.form .hint { font-size: var(--door-hint); color: var(--ink-500); }

/* The one-time code. Wide tracking and the identifier face, because it is
   read off a phone a digit at a time and compared, not scanned.

   The face is var(--ultra-font-data), and was var(--ultra-mono) -- a token
   that is not defined anywhere and never was. An invalid var() leaves the
   property unset, so font-family fell back to inheritance and this field drew
   in the page's proportional face: the comment above was right and the rule
   agreed with it, and the name silently did not. --ultra-font-data is the
   package's own, and what the console's data cells read. */
.form .inp.code {
  font-family: var(--ultra-font-data); font-size: var(--door-code);
  letter-spacing: var(--door-track-code); text-align: center;
}

/* Full width, because there is one thing to do on this page. The package's
   button is otherwise unchanged -- same height, same radius, same blue. */
.ultra-btn.wide {
  width: 100%; text-align: center;
  height: 29px; padding: 0 11px; border-radius: 3px;
  font-size: var(--door-btn); font-weight: var(--door-w-medium);
  line-height: var(--door-lh-tight);
  margin-top: 6px;
}
.ultra-btn--primary.wide {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.ultra-btn--primary.wide:hover { filter: brightness(1.08); }

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


/* The identity-provider route, under the password form.

   A rule with a word in it rather than a second primary button: two buttons of
   equal weight is a question, and almost everybody at a customer that has
   turned this on wants the top one. */
.orsso { margin-top: 20px; }
.or {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 16px;
  color: var(--ink-400);
  font-size: var(--door-rule); letter-spacing: var(--door-track-wide);
  text-transform: uppercase;
}
.or::before, .or::after {
  content: ""; flex: 1; height: 1px; background: var(--alpha-ink-14);
}
