/* The authentication entrance screens — sign in, sign out, the consent step and
   the interruption pages.

   Ported from the approved Claude Design surface (`ems/css/auth.css` in the
   Tokonatsu Ops project) and sanctioned by the design system itself:
   `ems-design.md` §"Login (signature surface)" calls this "the one expressive
   screen" and specifies the dusk-sky mesh, the amber-to-red card filament and
   the staggered entrance by name. The constitution's Accent-Not-Paint rule is
   not broken here — Principle III names that document the canonical rule
   source, and the carve-out lives inside it. See `specs/012-auth-entrance-design/spec.md` §0.1.

   ==== Why the tokens sit at :root, unlike project.css ====

   `project.css` scopes its `--toko-*` tokens to individual components on
   purpose, because it is loaded by the application shell alongside everything
   else. These pages are STANDALONE DOCUMENTS: `auth_base.html` does not extend
   `base.html` and loads this stylesheet and nothing else of ours. So there is
   nothing here for a document-level token to leak into, and putting them at the
   root is what stops the failure this repository has already met once — a
   shorthand containing an unresolvable `var()` is dropped WHOLE, silently, with
   no console warning and no lint error, so the element renders as though the
   rule had never been written.

   Every `var(--…)` below must resolve to a name declared in the block that
   follows. That is checkable, and `specs/012-auth-entrance-design/quickstart.md`
   carries the one-line check. */

/* ==== Open Sans, the one family (One-Family) ============================== */

/* The VARIABLE face. `ems-design.md` records that the static 400/600/700 faces
   silently render weight 500 — the EMS heading weight — as 400, so the axis is
   not a nicety. Vendored through the npm pipeline and served from this origin
   (VND-01); the relative path resolves after `collectstatic`, and
   `tests/test_static_pipeline.py` refuses it if it does not. */
@font-face {
  font-family: "Open Sans Variable";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("../vendor/open-sans/open-sans-latin-wght-normal.dcf31ebe1074.woff2")
    format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==== The box model this document owns ==================================== */

/* **This is not boilerplate; it is the reset the entrance document gave up.**

   These pages deliberately load no Bootstrap — that is what gives them one
   stylesheet and zero JavaScript — and Bootstrap is where the global
   `border-box` reset used to come from for free. Nothing replaced it, so
   `width: 100%` plus padding meant CONTENT width plus padding, and the card came
   out 24px wider than the viewport at every mobile size: measured at 320, 390,
   412 and 430, hanging 12px off each edge with the Discord button clipped.

   It hid because `.toko-auth` sets `overflow: hidden` — which is load-bearing,
   since the drifting glow uses `inset: -25%` — so the overflow was CLIPPED rather
   than scrolled, and every "does the page scroll sideways" assertion passed.

   Scoped by loading: only `auth_base.html` links this file, so this reaches the
   entrance surfaces and nothing else. The application shell keeps its own. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* ==== Tokens ============================================================== */

:root {
  /* Brand ramp — for gradients and decoration. None of these is a text colour;
     the text-safe darkened tones are below. */
  --toko-amber: #ffb337;
  --toko-amber-hover: #ffc257;
  --toko-red: #f90048;
  --toko-orange: #ff8922;
  --toko-deep-orange: #ff581e;

  /* Text-safe darkened tones. The raw brand reds and oranges fail WCAG AA on
     light surfaces — white on #f90048 is 4.1:1 — so anything carrying small
     text or a white label uses these instead. */
  --toko-red-cta: #d2003c;
  --toko-red-cta-rgb: 210, 0, 60;
  --toko-red-cta-hover: #b30033;
  --toko-deep-orange-text: #b8430e;

  /* Neutrals. #6b6b6b is ~5:1 on white and is the floor for muted text — do
     not go lighter. */
  --toko-ink-2: #444444;
  --toko-mid-grey: #6b6b6b;
  --toko-heading: #1f1f1f;

  /* Surfaces and lines. */
  --toko-amber-subtle: #fff3cd;
  --toko-amber-border: #ffd966;
  --toko-border: #e5e5e5;
  --toko-bg-2: #f2f2f2;

  /* Control Border. Distinct from --toko-border ON PURPOSE, and the one place
     this file departs from the imported stylesheet: a BARE FORM CONTROL is
     identified by its border, so WCAG 1.4.11 puts a 3:1 floor on it, and
     #e5e5e5 is about 1.3:1 against the white card. `ems-design.md`'s Do list
     names #8a8a8a for exactly this, and `SKILL.md` names that document the
     authoritative contrast-audited source. Cards, dividers, message pills and
     the secondary button are NOT bare controls and correctly keep the
     --toko-border hairline. Nothing measures this — `e2e/contrast.py` reads
     TEXT contrast only — so it has to be right here. */
  --toko-control-border: #8a8a8a;

  /* Refusal. A rejected credential is not a festival accent, so these are their
     own ramp rather than the red CTA: #8a0026 on #ffe1e9 measures 8.7:1, which
     keeps an error legible in the daylight this application is read in. Named
     because they carried meaning and had none — one error-state change used to
     mean editing five literals across three rules. */
  --toko-error-bg: #ffe1e9;
  --toko-error-ink: #8a0026;
  --toko-error-border: #ffc2d2;

  /* The password submit. Near-black rather than a brand colour ON PURPOSE: the
     amber primary above is how a volunteer signs in, and two filled controls
     competing for the same glance is what the design language calls
     accent-as-paint. This one recedes. */
  --toko-submit-bg: #2a2a2a;
  --toko-submit-bg-hover: #1a1a1a;

  /* Links. #7a5600 is 5.9:1 on white; raw amber is 2.1:1 and fails as text. */
  --bs-link-color: #7a5600;
  --bs-link-hover-color: #4a3400;

  /* Type. */
  --toko-font-body:
    "Open Sans Variable", "Open Sans", system-ui, -apple-system, "Segoe UI",
    sans-serif;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;

  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.14);
}

/* This stylesheet is loaded by `auth_base.html` and by nothing else, so a
   document-level rule here reaches the entrance screens only. */
body {
  margin: 0;
  font-family: var(--toko-font-body);
}

/* ==== The field =========================================================== */

.toko-auth {
  min-height: 100svh;
  display: grid;
  place-items: center;
  /* Scales with the viewport rather than sitting at one value: 16px on a 320px
     phone where every pixel of card is wanted, ~20px on a large phone, 40px once
     there is room to let the card float. The floor is what guarantees the
     gradient stays visible on all four sides at the narrowest width. */
  padding: clamp(1rem, 5vw, 2.5rem);
  position: relative;
  overflow: hidden;
  /* Light-by-design: stop OS dark mode from inverting the white card's inputs,
     autofill, and checkbox. */
  color-scheme: light;
  /* "Tokonatsu" = everlasting summer: a warm dusk-sky mesh. */
  background:
    radial-gradient(
      120% 90% at 12% 8%,
      rgba(255, 179, 55, 0.95) 0%,
      rgba(255, 179, 55, 0) 55%
    ),
    radial-gradient(
      120% 90% at 92% 18%,
      rgba(255, 137, 34, 0.95) 0%,
      rgba(255, 137, 34, 0) 60%
    ),
    radial-gradient(
      140% 120% at 85% 100%,
      rgba(249, 0, 72, 0.55) 0%,
      rgba(249, 0, 72, 0) 55%
    ),
    linear-gradient(160deg, var(--toko-deep-orange) 0%, #c8390f 100%);
}

/* Soft drifting glow + faint dot texture for depth. */
.toko-auth::before {
  content: "";
  position: absolute;
  inset: -25%;
  background: radial-gradient(
    closest-side,
    rgba(255, 240, 214, 0.55),
    rgba(255, 240, 214, 0) 70%
  );
  filter: blur(8px);
  animation: toko-drift 22s ease-in-out infinite alternate;
  pointer-events: none;
}

.toko-auth::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1.4px);
  background-size: 22px 22px;
  opacity: 0.5;
  mix-blend-mode: overlay;
  pointer-events: none;
}

@keyframes toko-drift {
  from {
    transform: translate3d(-4%, -3%, 0) scale(1);
  }

  to {
    transform: translate3d(5%, 4%, 0) scale(1.08);
  }
}

/* ==== The card ============================================================ */

.toko-auth-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 26rem;
  background: #fff;
  border-radius: var(--radius-lg);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.6) inset,
    0 24px 60px -12px rgba(80, 24, 0, 0.45),
    var(--shadow-lg);
  padding: 2.5rem 2.25rem 2rem;
  overflow: hidden;
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

/* Below 360px the generous padding costs more than it gives: at 320 it left about
   200px of content and wrapped the disclosure label. Stepping it down buys ~30px
   back exactly where it is scarcest — the scene this whole design is written for
   is a phone held in one hand. Placed immediately after the rule it overrides so
   the cascade reads top to bottom rather than by specificity. */
@media (max-width: 360px) {
  .toko-auth-card {
    padding: 2rem 1.25rem 1.75rem;
  }
}

/* Amber filament across the top edge of the card. */
.toko-auth-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: linear-gradient(
    90deg,
    var(--toko-amber),
    var(--toko-orange),
    var(--toko-red)
  );
}

/* ==== Brand row =========================================================== */

.toko-auth-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.06s both;
}

.toko-auth-brand .toko-brand-logo {
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  display: block;
}

.toko-auth-brand .name {
  font-weight: 700;
  font-size: 1.125rem;
  line-height: 1.1;
  color: var(--toko-heading);
}

/* The one kicker a card is allowed. Eyebrow-Earns-It permits a single contextual
   kicker and names an eyebrow per section as a defect.

   **Second deliberate deviation from the imported stylesheet, and it was found by
   measurement rather than by reading.** That file colours this Deep Orange
   (--toko-deep-orange, #ff581e), which is 3.15:1 on white and FAILS the 4.5:1 AA
   floor for normal text — reported by the browser contrast sweep as
   `('div', 'Event Operations', 3.15, 4.5)`. `ems-design.md` names the rule
   directly: "Eyebrows, icon text, focus rings on light = deep-orange-text
   #b8430e. Raw orange/deep-orange are gradient/accent tones, never body text."
   Deep Orange Text measures 5.3:1 here. Same class of defect as the control
   border above; unlike that one, this class IS measured, and was. */
.toko-auth-brand .kicker {
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--toko-deep-orange-text);
  font-weight: 600;
}

/* ==== Head ================================================================ */

.toko-auth-head {
  margin-bottom: 1.5rem;
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.12s both;
}

.toko-auth-head h1 {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 0 0 0.25rem;
  color: var(--toko-heading);
}

.toko-auth-head p {
  margin: 0;
  color: var(--toko-mid-grey);
  font-size: 0.9375rem;
}

/* Interruption-page status heading. The heading leads with a tinted icon chip —
   the identity-avatar treatment reused — so status reads as icon AND words,
   never colour alone, and the glyph never renders as bare heading-black. Flexed
   so wrapped heading text hangs clear of the chip on narrow screens instead of
   falling underneath. */
.toko-auth-head--status h1 {
  display: flex;
  /* Anchor the chip to the FIRST text line: on narrow screens a two-line
     heading must not float the chip between its lines. The negative offset
     optically re-centres the 2.25rem chip on the 1.8rem first line box
     (1.5rem x 1.2 line-height): (1.8 - 2.25) / 2 = -0.225rem. */
  align-items: flex-start;
  gap: 0.6rem;
}

.toko-auth-head--status h1 .ic {
  flex: 0 0 auto;
  margin-top: -0.225rem;
  width: 2.25rem;
  height: 2.25rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-md);
  background: var(--toko-amber-subtle);
  color: var(--toko-deep-orange-text);
  font-size: 1.2rem;
}

/* Quiet note line. Mid Grey is the contrast floor for muted text — do not go
   lighter.

   WIDENED from `.toko-auth-head .note` to `.toko-auth .note`: the sign-in card
   carries two of these OUTSIDE the head — one above the password disclosure and
   one inside it below the submit — and the imported stylesheet scoped the
   selector to the head only because the head was the only position when it was
   written. One treatment, positioned by the two modifiers below, rather than the
   same three declarations repeated per site. */
.toko-auth .note {
  margin: 0.5rem 0 0;
  font-size: 0.8125rem;
  color: var(--toko-mid-grey);
  text-wrap: pretty;
}

/* Above the password disclosure: the gap belongs below the text. */
.toko-auth .note--lead {
  margin: 0 0 0.5rem;
}

/* Inside the disclosure, below the submit: the gap belongs above it. */
.toko-auth .note--trailing {
  margin: 0.5rem 0 0;
}

/* On interruption pages the head paragraph IS the message, not a subtitle: it
   reads in ink for daylight legibility, leaving only the .note muted. */
.toko-auth--status .toko-auth-head p:not(.note) {
  color: var(--toko-heading);
}

/* ==== Providers and buttons =============================================== */

.toko-auth-providers {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.18s both;
}

.toko-auth-providers form {
  margin: 0;
}

.toko-auth-btn {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  /* Vertical padding plus line-height clears the 44px one-handed outdoor target
     the rest of this application uses. */
  min-height: 2.75rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-md);
  font-family: inherit;
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.2;
  border: 1px solid transparent;
  cursor: pointer;
  /* Anchors can wear this class (the sign-out "Back to dashboard"); keep them
     looking like buttons, not underlined links. */
  text-decoration: none;
  transition:
    transform 0.12s ease,
    box-shadow 0.12s ease,
    background-color 0.12s ease,
    border-color 0.12s ease;
}

.toko-auth-btn:hover {
  text-decoration: none;
}

.toko-auth-btn i {
  font-size: 1.15rem;
}

.toko-auth-btn:active {
  transform: translateY(1px);
}

/* Keyboard focus — a deliberate brand-warm ring on every button and the dark
   submit. Deep Orange Text, not raw amber: amber is ~1.8:1 against the white
   card, under WCAG 1.4.11's 3:1 non-text floor, and invisible ringing an amber
   button. The offset gap reads the ring against the surface BEHIND the control
   rather than against its fill. */
.toko-auth-btn:focus-visible,
.toko-auth-submit:focus-visible {
  outline: 3px solid var(--toko-deep-orange-text);
  outline-offset: 2px;
}

/* Ink on amber, never white and never amber text: amber is 2.1:1 on white, so
   it can carry black and nothing else. */
.toko-auth-btn--primary {
  background: var(--toko-amber);
  color: #1a1100;
  box-shadow: 0 8px 20px -8px rgba(255, 179, 55, 0.9);
}

.toko-auth-btn--primary:hover {
  background: var(--toko-amber-hover);
  box-shadow: 0 10px 24px -8px rgba(255, 179, 55, 1);
}

/* The Control Border, not the hairline — a third application of AED-23's rule and
   the one the spec filed on the wrong side. This button is white on a white card,
   so its BOUNDARY is the only thing that says it is a control at all, which is
   exactly what WCAG 1.4.11's 3:1 floor is about. On the no-access refusal it is the
   page's sole action, read one-handed in bright daylight. The spec grouped it with
   "cards and hairlines"; a card is not something you press. */
.toko-auth-btn--secondary {
  background: #fff;
  color: var(--toko-heading);
  border-color: var(--toko-control-border);
}

.toko-auth-btn--secondary:hover {
  background: var(--toko-amber-subtle);
  border-color: var(--toko-amber-border);
}

/* Leave action — the page's high-visibility CTA, in the same red ramp module
   submit buttons use, so the exit reads as the deliberate primary action. */
.toko-auth-btn--leave {
  background: var(--toko-red-cta);
  color: #fff;
  box-shadow: 0 8px 20px -8px rgba(var(--toko-red-cta-rgb), 0.7);
}

.toko-auth-btn--leave:hover {
  background: var(--toko-red-cta-hover);
  box-shadow: 0 10px 24px -8px rgba(var(--toko-red-cta-rgb), 0.85);
}

/* ==== Divider ============================================================= */

.toko-auth-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.5rem 0;
  color: var(--toko-mid-grey);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.24s both;
}

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

/* ==== The password fallback — native collapsible, no JavaScript =========== */

.toko-auth-password {
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.24s both;
}

/* `display: flex`, NOT `inline-flex`. Auto margins compute to zero on an
   inline-level box, so `margin: 0 auto` on an inline-flex summary is inert and the
   control renders left-aligned — a declaration that reads as intent and does
   nothing. Block-level plus `width: fit-content` is what actually centres it. */
.toko-auth-password > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin: 0 auto;
  width: fit-content;
  min-height: 2.75rem;
  padding: 0.5rem 0.85rem;
  border-radius: var(--radius-md);
  color: var(--bs-link-color);
  font-size: 0.875rem;
  font-weight: 600;
  user-select: none;
  transition:
    color 0.12s ease,
    background-color 0.12s ease;
}

.toko-auth-password > summary::-webkit-details-marker {
  display: none;
}

.toko-auth-password > summary:hover {
  color: var(--bs-link-hover-color);
  background: var(--toko-amber-subtle);
}

.toko-auth-password > summary:focus-visible {
  outline: 3px solid var(--toko-deep-orange-text);
  outline-offset: 2px;
}

.toko-auth-password > summary .chev {
  transition: transform 0.18s ease;
  font-size: 0.85rem;
}

.toko-auth-password[open] > summary .chev {
  transform: rotate(180deg);
}

/* ==== Fields ============================================================== */

.toko-auth-fields {
  margin-top: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
}

.toko-auth-field label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--toko-ink-2);
  margin-bottom: 0.3rem;
}

/* A BARE FORM CONTROL takes the Control Border, not the hairline — see the
   token's own comment. This is the one deliberate departure from the imported
   stylesheet, and no gate in this repository can see it. */
.toko-auth-field input[type="text"],
.toko-auth-field input[type="email"],
.toko-auth-field input[type="password"] {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--toko-control-border);
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  font-family: inherit;
  color: var(--toko-heading);
  background: #fff;
  transition:
    border-color 0.12s ease,
    box-shadow 0.12s ease;
}

.toko-auth-field input:focus-visible {
  outline: 3px solid var(--toko-deep-orange-text);
  outline-offset: 2px;
  border-color: var(--toko-deep-orange-text);
}

.toko-auth-field--check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
}

/* The LABEL is the target here, not the 18px box. A `for=`-associated label
   toggles its checkbox, so making it fill the row gives a volunteer a 44px
   one-handed target without drawing an absurdly large tick box. Measured by
   `test_every_control_is_a_comfortable_one_handed_target`, which unions the
   checkbox with its label for exactly this reason. */
.toko-auth-field--check label {
  margin: 0;
  display: flex;
  flex: 1;
  align-items: center;
  min-height: 2.75rem;
  font-weight: 400;
  color: var(--toko-mid-grey);
}

.toko-auth-field--check input {
  width: 1.15rem;
  height: 1.15rem;
  /* Dark amber, not raw: every engine draws a light tick on a dark accent,
     which keeps the mark legible cross-browser. */
  accent-color: var(--bs-link-color);
}

.toko-auth-field--check input:focus-visible {
  outline: 3px solid var(--toko-deep-orange-text);
  outline-offset: 2px;
}

.toko-auth-submit {
  width: 100%;
  min-height: 2.75rem;
  margin-top: 1rem;
  padding: 0.7rem 1rem;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: var(--toko-submit-bg);
  color: #fff;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.9375rem;
  cursor: pointer;
  transition:
    transform 0.12s ease,
    background-color 0.12s ease;
}

.toko-auth-submit:hover {
  background: var(--toko-submit-bg-hover);
}

.toko-auth-submit:active {
  transform: translateY(1px);
}

/* ==== Errors and messages ================================================= */

.toko-auth-error {
  background: var(--toko-error-bg);
  color: var(--toko-error-ink);
  border: 1px solid var(--toko-error-border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  font-size: 0.8125rem;
  margin-bottom: 0.875rem;
}

.toko-auth-field .toko-auth-error {
  margin: 0.4rem 0 0;
}

/* Django messages, styled by level. A sign-out confirmation is a neutral
   notice; only the error and warning levels take the red pill. */
.toko-auth-msg {
  background: var(--toko-bg-2);
  color: var(--toko-heading);
  border: 1px solid var(--toko-border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  font-size: 0.8125rem;
  margin-bottom: 0.875rem;
}

.toko-auth-msg--error {
  background: var(--toko-error-bg);
  color: var(--toko-error-ink);
  border-color: var(--toko-error-border);
}

/* ==== Sign out ============================================================ */

.toko-auth-identity {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 0.75rem;
  margin-bottom: 1.25rem;
  border: 1px solid var(--toko-border);
  border-radius: var(--radius-md);
  background: var(--toko-bg-2);
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.18s both;
}

.toko-auth-identity .avatar {
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--toko-amber-subtle);
  color: var(--toko-deep-orange-text);
  font-size: 1.2rem;
}

.toko-auth-identity .who {
  min-width: 0;
}

.toko-auth-identity .label {
  display: block;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--toko-mid-grey);
  line-height: 1.2;
}

.toko-auth-identity .name {
  display: block;
  font-weight: 600;
  font-size: 0.9375rem;
  color: var(--toko-heading);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.toko-auth-actions {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.24s both;
}

.toko-auth-actions form {
  margin: 0;
}

/* ==== Foot ================================================================ */

.toko-auth-foot {
  margin-top: 1.75rem;
  text-align: center;
  font-size: 0.75rem;
  color: var(--toko-mid-grey);
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.3s both;
}

/* ==== The message and interruption stagger ================================ */

/* A message is a real third block on ANY card, not only an interruption one, and
   the sign-in card is the page GUARANTEED to carry one — AED-13's post-sign-out
   confirmation lands there every time. Without this it appeared instantly at full
   opacity while the brand row and head rose around it, and AED-22's "the beat stays
   even when a message occupies a slot" held for two surfaces out of five. */
.toko-auth .toko-auth-msg {
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.18s both;
}

.toko-auth:has(.toko-auth-msg) .toko-auth-providers {
  animation-delay: 0.24s;
}

.toko-auth:has(.toko-auth-msg) .toko-auth-divider,
.toko-auth:has(.toko-auth-msg) .toko-auth-password {
  animation-delay: 0.3s;
}

.toko-auth:has(.toko-auth-msg) .toko-auth-foot {
  animation-delay: 0.36s;
}

/* Interruption pages usually have no third content block between head and
   actions; compact the entrance stagger to keep the even 60ms beat (brand .06 →
   head .12 → actions .18 → foot .24) instead of skipping a slot. A rendered
   Django message IS a third block: it takes the .18s slot and the rows after it
   shift back one beat, so the rhythm stays truthful either way.

   These sit AFTER the base rules they override, deliberately. They are more
   specific, so the cascade would honour them from anywhere — but a stylesheet
   where a (0,2,0) rule precedes the (0,1,0) rule it modifies is one a reader has
   to compute specificity to follow, and `biome`'s noDescendingSpecificity is
   right to refuse it. */
.toko-auth--status .toko-auth-actions {
  animation-delay: 0.18s;
}

.toko-auth--status .toko-auth-foot {
  animation-delay: 0.24s;
}

.toko-auth--status .toko-auth-msg {
  animation: toko-rise 0.6s cubic-bezier(0.2, 0.7, 0.2, 1) 0.18s both;
}

.toko-auth--status:has(.toko-auth-msg) .toko-auth-actions {
  animation-delay: 0.24s;
}

.toko-auth--status:has(.toko-auth-msg) .toko-auth-foot {
  animation-delay: 0.3s;
}

@keyframes toko-rise {
  from {
    opacity: 0;
    transform: translateY(12px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Every animation on these pages has an instant alternative, as Principle III
   requires. This is the whole list of ANIMATED elements; transitions are collapsed
   separately below, because resetting `animation` does not touch them.

   **Each selector is scoped to `.toko-auth` on purpose, and removing that scope
   is a silent bug.** A media query adds no specificity, so a bare
   `.toko-auth-msg` at (0,1,0) would LOSE to `.toko-auth--status .toko-auth-msg`
   at (0,2,0) above — and that rule sets `animation-name`, so an interruption page
   carrying a message would go on animating for somebody who asked it not to.
   Matching the specificity lets source order decide, and this block is last. */
@media (prefers-reduced-motion: reduce) {
  .toko-auth::before,
  .toko-auth .toko-auth-card,
  .toko-auth .toko-auth-brand,
  .toko-auth .toko-auth-head,
  .toko-auth .toko-auth-providers,
  .toko-auth .toko-auth-divider,
  .toko-auth .toko-auth-password,
  .toko-auth .toko-auth-identity,
  .toko-auth .toko-auth-msg,
  .toko-auth .toko-auth-actions,
  .toko-auth .toko-auth-foot {
    animation: none;
  }

  /* Transitions too, and COLLAPSED rather than removed — this repository's
     convention (`e2e/test_accessibility.py`) is that the thing still happens, in a
     single frame, so anything waiting on a transition to end still completes.
     Resetting `animation` above does not touch them, and the chevron rotate and the
     :active nudge are transitions.

     Each selector is written to OUT-SPECIFY the rule it overrides rather than
     reaching for `!important`, which reverses the cascade and which biome rightly
     refuses. `.toko-auth-field input[type=…]` is (0,2,1) and the chevron is (0,3,0),
     so these carry one more class than their targets. */
  .toko-auth .toko-auth-btn,
  .toko-auth .toko-auth-submit,
  .toko-auth .toko-auth-password > summary,
  .toko-auth .toko-auth-field input,
  .toko-auth .toko-auth-password > summary .chev {
    transition-duration: 0.001s;
  }
}
