/* ── LoginPage styles (scoped under .login-page) ──
 *
 * Permanently ROASt-brand themed to mirror the marketing site
 * (roast-labs.com): a pure-white surface with a soft coral "glow",
 * neutral type, and the gold→coral→pink brand gradient on accents.
 * The login is the brand gateway and must read as one coherent surface
 * with the landing — so it deliberately does NOT inherit the active app
 * theme. Fonts + colours are pinned here, independent of <html> theme.
 */

.login-page {
  /* ROASt landing palette — hex-pinned, theme-independent */
  --login-bg:         #ffffff;          /* page surface — pure white */
  --login-card:       #ffffff;          /* the centred card */
  --login-field:      #fafafa;          /* subtle input fill */
  --login-border:     rgba(0,0,0,0.09); /* hairline */
  --login-border-2:   rgba(0,0,0,0.14); /* hover / input border */
  --login-text:       #0a0b0d;          /* near-black */
  --login-text-2:     #3a3f47;          /* secondary */
  --login-text-3:     #62666d;          /* body */
  --login-text-4:     #9ca0a8;          /* muted labels */
  --login-wordmark:   #1c1231;          /* brand navy (letterforms) */
  --login-accent:     #f37771;          /* coral mid */
  --login-accent-2:   #ef5386;          /* pink end */
  --login-accent-text:#d6356a;          /* readable coral-pink for links on white */
  --login-accent-tint:rgba(243,119,113,0.10);
  --login-accent-glow:rgba(239,83,134,0.26);
  --login-grad: linear-gradient(92.88deg, #faa963 9.16%, #f37771 50%, #ef5386 90.84%);

  position: fixed;
  inset: 0;
  z-index: 9999;
  overflow-y: auto;
  background: var(--login-bg);
  color: var(--login-text);
  font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ── Atmospheric glow — mirrors landing .hero-glow + .hero-blush ── */
.login-glow,
.login-blush,
.login-grain {
  position: fixed;
  pointer-events: none;
}

/* Faint coral/pink radial well behind the card */
.login-glow {
  left: 50%;
  top: 42%;
  width: 1100px;
  height: 720px;
  transform: translate(-50%, -50%);
  z-index: 0;
  background: radial-gradient(
    ellipse at center,
    rgba(243, 119, 113, 0.14) 0%,
    rgba(239, 83, 134, 0.07) 32%,
    transparent 70%
  );
  filter: blur(44px);
}

/* Warm gold→coral→pink blush rising from the bottom edge */
.login-blush {
  left: 50%;
  bottom: -340px;
  width: 1500px;
  height: 900px;
  transform: translateX(-50%);
  z-index: 0;
  background: radial-gradient(
    ellipse 55% 82% at 50% 90%,
    rgba(250, 169, 99, 0.20) 0%,
    rgba(243, 119, 113, 0.13) 28%,
    rgba(239, 83, 134, 0.06) 52%,
    transparent 80%
  );
  filter: blur(40px);
}

/* Barely-there grain — same fractal-noise overlay as the landing */
.login-grain {
  inset: 0;
  z-index: 2;
  opacity: 0.045;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='256' height='256'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-repeat: repeat;
  background-size: 256px 256px;
  mix-blend-mode: overlay;
}

/* ── ANIMATIONS ── */
@keyframes loginFadeUp {
  from { opacity: 0; transform: translateY(12px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}

.login-page .anim {
  opacity: 0;
  animation: loginFadeUp 0.55s cubic-bezier(0.22,1,0.36,1) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .login-page .anim { animation-duration: 0.01ms; }
  .login-grain { display: none; }
}

/* ── Centred column — scroll-safe vertical centring ──
 * min-height:100% fills the viewport when content is short (so the card
 * sits at true centre); the column grows past 100% when content is tall
 * and .login-page scrolls, so nothing is ever clipped. This is the fix
 * for the old grid that pinned the card above centre. */
.login-shell {
  position: relative;
  z-index: 1;
  min-height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 48px 20px;
}

/* ── The card ── */
.login-card {
  position: relative;
  z-index: 1;
  width: min(420px, 100%);
  background: var(--login-card);
  border: 1px solid var(--login-border);
  border-radius: 20px;
  padding: 38px 34px 32px;
  box-shadow:
    0 1px 2px rgba(10,11,13,0.04),
    0 10px 30px rgba(10,11,13,0.06),
    0 2px 10px rgba(243,119,113,0.05);
}
/* top-edge brand shine */
.login-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 28px;
  right: 28px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(243,119,113,0.4), transparent);
  pointer-events: none;
}

/* ── Brand lockup (icon + wordmark) ── */
.login-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-bottom: 14px;
}
.login-brand-icon {
  display: block;
  width: 36px;
  height: 36px;
}
.login-brand-logo {
  display: block;
  height: 26px;
  width: auto;
  color: var(--login-wordmark);
}

/* ── Tagline — brand signature beneath the lockup ── */
.login-tagline {
  text-align: center;
  font-size: 14px;
  font-weight: 500;
  color: var(--login-text-3);
  letter-spacing: -0.01em;
  margin-bottom: 24px;
}
.login-grad {
  background: var(--login-grad);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  font-weight: 600;
}

/* ── Per-view heading ── */
.login-form-heading {
  font-family: inherit;
  font-size: 22px;
  font-weight: 640;
  color: var(--login-text);
  letter-spacing: -0.02em;
  margin-bottom: 5px;
}
.login-form-sub {
  font-size: 13.5px;
  color: var(--login-text-3);
  line-height: 1.55;
  margin-bottom: 22px;
}

/* ── Pending-plan chip (landing pricing CTA → /signup?plan=…) ── */
.login-plan-chip {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--login-text-3);
  background: var(--login-accent-tint);
  border: 1px solid rgba(243,119,113,0.28);
  border-radius: 999px;
  padding: 7px 14px;
  margin-bottom: 12px;
  width: fit-content;
}
.login-plan-chip-tier {
  color: var(--login-text);
  font-weight: 650;
}
.login-plan-chip-sep { color: var(--login-text-4); }

/* ── Signup-only value-prop note ── */
.login-signup-note {
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--login-text-3);
  background: var(--login-accent-tint);
  border: 1px solid rgba(243,119,113,0.18);
  border-radius: 10px;
  padding: 11px 13px;
  margin-bottom: 18px;
}
.login-signup-note strong { color: var(--login-text); font-weight: 600; }

/* ── Form fields ── */
.login-page .field {
  margin-bottom: 14px;
}
.login-page .field label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--login-text-4);
  margin-bottom: 7px;
}
.login-page .field input {
  width: 100%;
  padding: 12px 14px;
  background: var(--login-field);
  border: 1px solid var(--login-border-2);
  border-radius: 9px;
  font-family: inherit;
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  color: var(--login-text);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.login-page .field input:focus {
  background: #fff;
  border-color: var(--login-accent);
  box-shadow: 0 0 0 3px var(--login-accent-tint);
}
.login-page .field input::placeholder {
  color: var(--login-text-4);
}

/* ── 2FA verify view (security Part B §B4) ── */
.login-page .field input.totp-input {
  text-align: center;
  font-size: 20px;
  letter-spacing: 0.28em;
  font-weight: 600;
}
.login-page .field input.totp-input::placeholder {
  letter-spacing: 0.28em;
  font-weight: 400;
}
.login-page .login-totp-attempts {
  font-size: 12px;
  color: var(--login-text-4);
  text-align: center;
  margin: -6px 0 14px;
}

/* ── Error / success ── */
.login-page .login-error,
.login-page .login-success {
  border-radius: 9px;
  padding: 10px 13px;
  font-size: 13px;
  line-height: 1.45;
  margin-bottom: 16px;
  animation: loginFadeUp 0.25s ease;
}
.login-page .login-error {
  background: rgba(220,38,38,0.07);
  border: 1px solid rgba(220,38,38,0.22);
  color: #c81e1e;
}
.login-page .login-success {
  background: rgba(22,163,74,0.07);
  border: 1px solid rgba(22,163,74,0.22);
  color: #15803d;
}

/* ── Google sign-in button ── */
.login-page .btn-google {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 11px;
  background: #fff;
  border: 1px solid var(--login-border-2);
  border-radius: 12px;          /* rounded-rect to match the wizard's primary button */
  font-family: inherit;
  font-size: 14px;
  font-weight: 510;
  color: var(--login-text);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.login-page .btn-google:hover {
  background: #fafafa;
  border-color: var(--login-text-4);
  box-shadow: 0 1px 6px rgba(10,11,13,0.05);
}

/* ── "or" divider ── */
.login-page .social-divider {
  display: flex;
  align-items: center;
  margin: 14px 0;
}
.login-page .social-divider::before,
.login-page .social-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--login-border);
}
.login-page .social-divider span {
  padding: 0 12px;
  font-size: 12px;
  color: var(--login-text-4);
}

/* ── Auth links ── */
.login-page .auth-links {
  display: flex;
  justify-content: flex-end;
  margin: 2px 0 14px;
}
.login-page .auth-link {
  background: none;
  border: none;
  padding: 0;
  color: var(--login-accent-text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 510;
  cursor: pointer;
  text-decoration: none;
  transition: color 0.15s;
}
.login-page .auth-link:hover {
  color: var(--login-accent-2);
  text-decoration: underline;
}

/* ── Auth switch (bottom of form) ── */
.login-page .auth-switch {
  text-align: center;
  font-size: 13px;
  color: var(--login-text-4);
  margin-top: 18px;
}

/* ── Request Access pill ── */
.login-page .btn-request-access {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 14px;
  border: 1.5px solid var(--login-accent);
  border-radius: 12px;          /* rounded-rect to match the wizard's primary button */
  background: transparent;
  color: var(--login-accent-text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s;
  margin-left: 6px;
}
.login-page .btn-request-access:hover {
  background: var(--login-accent-tint);
}

/* ── Verify screen ── */
.login-page .verify-screen {
  text-align: center;
  padding: 12px 0 4px;
}
.login-page .verify-icon {
  font-size: 44px;
  margin-bottom: 14px;
  line-height: 1;
}
.login-page .verify-screen p {
  font-size: 14px;
  color: var(--login-text-3);
  line-height: 1.6;
  margin: 0 0 8px;
}
.login-page .verify-screen p strong { color: var(--login-text); font-weight: 600; }
.login-page .verify-note {
  font-size: 13px !important;
  color: var(--login-text-4) !important;
  margin-bottom: 22px !important;
}

/* ── Primary button — brand gradient pill (brighten-on-hover, no lift) ── */
.login-page .btn-login {
  width: 100%;
  padding: 13px;
  background: var(--login-grad);
  background-clip: padding-box;
  color: #fff;
  border: none;
  border-radius: 12px;          /* rounded-rect to match the wizard's primary button */
  font-family: inherit;
  font-size: 14px;
  font-weight: 590;
  cursor: pointer;
  transition: filter 0.16s, box-shadow 0.16s;
  box-shadow: 0 6px 20px var(--login-accent-glow);
}
.login-page .btn-login:hover {
  filter: brightness(1.06);
  box-shadow: 0 8px 26px var(--login-accent-glow);
}
.login-page .btn-login:active {
  filter: brightness(0.96);
}
.login-page .btn-login:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  filter: none;
  box-shadow: none;
}

/* ── Secondary button (resend verification) ── */
.login-page .btn-secondary {
  background: transparent;
  color: var(--login-accent-text);
  border: 1.5px solid var(--login-accent);
  box-shadow: none;
}
.login-page .btn-secondary:hover {
  background: var(--login-accent-tint);
  box-shadow: none;
  filter: none;
}

/* ── Spinner ── */
.login-page .login-spinner {
  display: inline-block;
  width: 13px;
  height: 13px;
  border: 2px solid rgba(255,255,255,0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: motionSpin calc(var(--motion-draw)*0.9) linear infinite;
  vertical-align: middle;
  margin-right: 7px;
}

/* ── Footer (inside the shell, below the card) ── */
.login-footer {
  position: relative;
  z-index: 1;
  font-family: inherit;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--login-text-4);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}
.login-footer-legal {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.login-footer-link {
  color: var(--login-text-4);
  text-decoration: none;
  transition: color 0.15s ease;
}
.login-footer-link:hover {
  color: var(--login-text-3);
  text-decoration: underline;
}

/* ── RESPONSIVE ── */
@media (max-width: 480px) {
  .login-shell {
    padding: 32px 16px;
    gap: 16px;
  }
  .login-card {
    border-radius: 16px;
    padding: 30px 22px 26px;
  }
  .login-form-heading { font-size: 21px; }
}

/* ── Workspace loading screen ─────────────────────────────────────────────── */
/* Brand-locked (pinned hex, theme-independent) so it shares ONE branded world
   with LoginPage + the client-overview gateway — login → pick client → load →
   workspace never jumps visual style. NEVER reads the active app theme.       */
.workspace-loading-screen {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: #ffffff;
  font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.011em;
}

.workspace-loading-screen::before,
.workspace-loading-screen::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.workspace-loading-screen::before {
  width: 460px;
  height: 420px;
  top: -160px;
  right: -120px;
  background: radial-gradient(circle, rgba(243, 119, 113, 0.16), rgba(250, 169, 99, 0.06) 45%, transparent 70%);
}

.workspace-loading-screen::after {
  width: 440px;
  height: 420px;
  bottom: -200px;
  left: -140px;
  background: radial-gradient(circle, rgba(239, 83, 134, 0.09), transparent 70%);
}

.workspace-loading-shell {
  position: relative;
  z-index: 1;
  width: min(460px, calc(100vw - 32px));
  padding: 34px 30px 32px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 18px;
  background: #ffffff;
  box-shadow: 0 30px 70px -28px rgba(24, 20, 30, 0.28), 0 2px 8px rgba(0, 0, 0, 0.05);
  text-align: center;
}

.workspace-loading-lockup {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
}
.workspace-loading-icon {
  width: 36px;
  height: 36px;
  display: block;
}
.workspace-loading-wordmark {
  color: #0a0b0d;
  height: 28px;
  width: auto;
}

.workspace-loading-spinner {
  width: 32px;
  height: 32px;
  margin: 22px auto 0;
  position: relative;
  color: #f37771;
  background: radial-gradient(8px, currentColor 94%, #0000);
}
.workspace-loading-spinner::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(7.2px at bottom right, #0000 94%, currentColor) top    left,
    radial-gradient(7.2px at bottom left,  #0000 94%, currentColor) top    right,
    radial-gradient(7.2px at top    right, #0000 94%, currentColor) bottom left,
    radial-gradient(7.2px at top    left,  #0000 94%, currentColor) bottom right;
  background-size: 16px 16px;
  background-repeat: no-repeat;
  animation: workspaceLoaderPulse 1.5s infinite cubic-bezier(0.3, 1, 0, 1);
}
@keyframes workspaceLoaderPulse {
  33%  { inset: -8px; transform: rotate(0deg); }
  66%  { inset: -8px; transform: rotate(90deg); }
  100% { inset: 0;     transform: rotate(90deg); }
}

.workspace-loading-title {
  margin-bottom: 8px;
  color: #0a0b0d;
  font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.03em;
}

.workspace-loading-copy {
  max-width: 320px;
  margin: 0 auto;
  color: #62666d;
  font-size: 14px;
  line-height: 1.6;
}

@media (max-width: 640px) {
  .workspace-loading-shell {
    width: min(420px, calc(100vw - 24px));
    padding: 28px 22px 26px;
    border-radius: 12px;
  }

  .workspace-loading-title {
    font-size: 24px;
  }

  .workspace-loading-copy {
    font-size: 13px;
  }
}

/* ════════════════════════════════════════════════════════════════════
   Split layout — login brand panel (Flume wave) · 2026-06-12
   Desktop: form column on white (left), full-height landing-dark brand
   panel (right) running the Flume wave with the lockup bottom-left.
   ≤920px: the panel disappears and the page is exactly the pre-split
   single-column layout (brand row returns to the top of the card).
   Like everything in this file, the panel is brand-pinned hex — it
   never reads app theme tokens.
   ════════════════════════════════════════════════════════════════════ */

.login-page {
  /* The split boundary. MUST stay in lockstep with the grid columns below:
     46% of a full-viewport page == 46vw, floored at 480px by minmax. The
     page background's hard colour stop and the wave-copy clip lines all
     use this var, so the colour flip and the clip seam coincide exactly. */
  --login-split: max(480px, 46vw);
  display: grid;
  grid-template-columns: minmax(480px, 46%) 1fr;
  overflow: hidden;               /* each pane owns its scrolling */
  /* Solid white — the dark side is no longer painted by the page; it floats as
     its own panel (see .login-brandpane). */
  background: var(--login-bg);
}

.login-formpane {
  position: relative;
  overflow-y: auto;
  overflow-x: hidden;
  background: transparent;        /* page paints the white; wave runs beneath */
}

/* ── Full-page wave field ──
   Two identical full-viewport copies of the surface, one clock; each copy
   clipped to its side of the split. Ink dots on the white half, snow dots
   on the dark half — the geometry is the same frame-for-frame, so the
   wave rolls straight through the seam. */
.login-wavefield {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.login-wave--ink {
  /* Full field — the ink texture flows across the whole white page and right up
     to (and around) the floating dark panel, so there's no bare white "bezel"
     between the form-side wave and the panel. Over the dark panel the ink dots
     are dark-on-dark (invisible); the snow copy paints the visible white dots. */
  clip-path: none;
}
.login-wave--ink .login-wave-line {
  stroke: rgba(10, 11, 13, 0.24);
}

.login-wave--snow {
  /* Clip the snow copy to the FLOATING brand panel's rounded rect (grid col 2,
     inset 12px, 16px radius) instead of the old full-height seam half-plane.
     Keeps the one-clock / two-copy wave intact while containing the snow copy
     inside the panel. MUST stay in lockstep with .login-brandpane's margin +
     border-radius below. */
  clip-path: inset(12px 12px 12px calc(var(--login-split) + 12px) round 16px);
}
.login-wave--snow .login-wave-line {
  stroke: rgba(255, 255, 255, 0.16);
}

/* Atmosphere centres on the form column now, not the viewport. The clipping
   wrapper is load-bearing: glow/blush are bigger than the pane (the blush
   alone is 900px tall), and as absolute descendants of the scroller they
   would otherwise EXTEND its scrollable area — phantom scrolling on the
   form side (prod bug, 2026-06-12). inset:0 + overflow:hidden caps them
   at exactly the pane box. */
.login-atmos {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.login-formpane .login-glow,
.login-formpane .login-blush,
.login-formpane .login-grain {
  position: absolute;
}

/* On the split, the brand panel carries the lockup — the card drops its */
@media (min-width: 921px) {
  .login-card .login-brand { display: none; }
}

/* ── Brand panel — floating dark card ──
   Same floating treatment as the in-app nav sidebar (base.css .nav-sidebar) +
   the onboarding wizard rail: 12px inset, rounded, the same soft drop shadow.
   The dark FILL + shadow are painted by .login-page::before, which sits BEHIND
   the page-level wave field — so the snow wave reads as white dots ON the dark
   (the original "dark behind the wave" layering). The pane itself MUST stay
   transparent: an opaque fill here paints over the wave (the pane is last in
   the DOM) and hides it. This pane only clips + positions the dawn glow +
   lockup to the rounded rect. */
.login-brandpane {
  position: relative;
  overflow: hidden;
  margin: 12px;
  border-radius: 16px;
  background: transparent;
  /* The panel's resting drop shadow lives HERE (not on .login-darkfill): the
     darkfill is a clip-path'd full-viewport slab since the §34.5 v2 rework,
     and clip-path clips an element's own box-shadow away. Same rect, same
     read; it fades out with the pane when the panel expands. */
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.10), 0 1px 6px rgba(0, 0, 0, 0.06);
  animation: loginPaneIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* The floating dark fill, painted BEHIND the wave (it's the FIRST positioned
   child in DOM order, so the wavefield draws over it). A real element (was
   .login-page::before pre-arrival) because the arrival ritual (§34.5)
   animates it. §34.5 v2: a FULL-VIEWPORT slab whose visible window is cut by
   clip-path — at rest the brand panel's rect; on enter the clip opens to a
   floating full-page panel (inset 12 round 16); on landing it shrinks to the
   app's .content-window footprint. Animating the CLIP (the main-thread
   `tweenClipPath` from LoginPage — NEVER element.animate(): Chrome 152
   composites WAAPI clip-path animations and paints them at the wrong
   geometry, 2026-09-04) keeps the 16px corners crisp at every frame — a transform
   scale stretches them (the v1 full-bleed expand hid that with an offscreen
   bleed; a visible floating end-state can't). The rest clip MUST stay in
   lockstep with the pane's margin + the snow-wave clip above (grid col 2,
   inset 12px, 16px radius). */
.login-darkfill {
  position: absolute;
  inset: 0;
  clip-path: inset(12px 12px 12px calc(var(--login-split) + 12px) round 16px);
  background: #08090A;
  pointer-events: none;
}

@keyframes loginPaneIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.login-wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  /* The band's top/bottom fade: a CSS mask sized to the band's box (vars
     published by LoginWave — --wave-fade-top/-h, in px on .login-wavefield).
     This REPLACED an SVG <mask> on 2026-09-04: Safari rasterises SVG masks in
     software every frame and pinned the whole login page at 7fps (the panel
     expand + picker cascade jitter Tom saw); the CSS mask composites on the
     GPU — 60fps, identical picture. Keep the fade here, never in the SVG. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
  -webkit-mask-size: 100% var(--wave-fade-h, 100%);
  mask-size: 100% var(--wave-fade-h, 100%);
  -webkit-mask-position: 0 var(--wave-fade-top, 0);
  mask-position: 0 var(--wave-fade-top, 0);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.login-wave-line {
  fill: none;                     /* stroke colour set per copy (--ink / --snow) */
  stroke-width: 0.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1 2.5;        /* fine stipple — dots riding the surface */
  vector-effect: non-scaling-stroke;
}

/* Warm dawn rising from the horizon — the landing sunrise motif.
   Two stacked radials: a hot amber core kissing the bottom edge + a wide
   soft coral-pink falloff. Over pure black, low single-alpha warm tints
   read as muddy brown — the layered hot core is what makes it luminous. */
.login-brandpane-dawn {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 40% 28% at 50% 103%,
      rgba(250, 169, 99, 0.52) 0%,
      rgba(243, 119, 113, 0.30) 42%,
      transparent 74%),
    radial-gradient(ellipse 80% 62% at 50% 105%,
      rgba(243, 119, 113, 0.17) 0%,
      rgba(239, 83, 134, 0.07) 52%,
      transparent 80%);
}

/* Lockup — bottom-left, above the wave */
.login-brandpane-lockup {
  position: absolute;
  left: 52px;
  bottom: 46px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.login-brandpane-brandrow {
  display: flex;
  align-items: center;
  gap: 14px;
}

.login-brandpane-icon {
  width: 40px;
  height: 40px;
  display: block;
  flex-shrink: 0;
}

.login-brandpane-wordmark {
  width: 132px;
  height: auto;
  display: block;
  color: #F7F8F8;                 /* letterforms via currentColor; the t keeps its gradient */
}

.login-brandpane-tagline {
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: rgba(247, 248, 248, 0.88);
}

/* ── Narrow viewports: single column, no panel ──
   The split collapses: the dark half and its snow copy disappear and the
   ink wave quietly textures the whole white page behind the card. */
@media (max-width: 920px) {
  .login-page { --login-split: 100%; grid-template-columns: 1fr; }
  .login-darkfill { display: none; }   /* no floating dark panel in single-column */
  .login-brandpane { display: none; }
  .login-wave--snow { display: none; }
}

/* ════════════════════════════════════════════════════════════════════
   Arrival ritual — login → workspace ("Sunrise panel", DESIGN §34.5)
   Password login morphs this page into the client picker, then the dark
   panel expands (loading) and contracts into the nav rail, dissolving on
   landing. Brand-pinned like everything above. Approval record:
   login-arrival-lab.html (Concept A, locked 2026-08-30).
   Durations reference the §34.2 motion tokens; the two panel-scale moves
   get local vars (one place to retune).
   ════════════════════════════════════════════════════════════════════ */

.login-page {
  --larr-expand-t: 0.65s;   /* panel → full viewport */
  --larr-land-t: 0.6s;      /* full viewport → nav rail */
}

/* Entrance cascade for arrival content (same shape as loginFadeUp; separate
   name so the auth-form entrance and the arrival cascade stay independently
   tunable). Fires once per mount — the arrival surface is a genuine first
   paint, so §34.1 principle 4 is satisfied. */
@keyframes larrFadeUp {
  from { opacity: 0; transform: translateY(12px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
.login-page .larr-in {
  opacity: 0;
  animation: larrFadeUp 0.55s var(--ease-out, cubic-bezier(0.22,1,0.36,1)) forwards;
}

/* ── Beat 2: the panel wakes (.larr-arrived on .login-page) ── */
.login-brandpane-lockup {
  transform-origin: left bottom;
  transition: transform var(--larr-land-t) var(--ease-out, cubic-bezier(0.22,1,0.36,1));
}
.larr-arrived .login-brandpane-lockup { transform: scale(0.62); }
.login-brandpane-tagline { transition: opacity var(--motion-base, 0.25s) ease; }
.larr-arrived .login-brandpane-tagline { opacity: 0; }
/* boosted dawn layer — same gradients as .login-brandpane-dawn, brighter core */
.larr-dawnboost {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.1s ease;
  background:
    radial-gradient(ellipse 46% 34% at 50% 103%,
      rgba(250, 169, 99, 0.34) 0%,
      rgba(243, 119, 113, 0.20) 42%,
      transparent 74%),
    radial-gradient(ellipse 86% 68% at 50% 105%,
      rgba(243, 119, 113, 0.11) 0%,
      rgba(239, 83, 134, 0.05) 52%,
      transparent 80%);
}
.larr-arrived .larr-dawnboost { opacity: 1; }

/* ── Briefing (left pane, replaces the card) ── */
.larr-briefing {
  position: relative;
  z-index: 1;
  width: min(430px, 100%);
  text-align: left;
}
.larr-b-eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--login-text-4); margin-bottom: 10px;
}
.larr-b-greeting {
  font-size: 32px; font-weight: 700; letter-spacing: -0.03em;
  color: var(--login-text); line-height: 1.1; margin-bottom: 8px;
}
.larr-b-sub { font-size: 14px; color: var(--login-text-3); margin-bottom: 26px; }
/* min-height reserves the full three-row briefing's space up front: the
   shell centres this column, so rows landing after their fetches would
   otherwise re-centre the block and visibly shift the greeting + earlier
   rows (Tom, 2026-08-30). Rows fade into the reserved area instead. */
.larr-b-rows { display: flex; flex-direction: column; gap: 12px; margin-bottom: 28px; min-height: 134px; }
.larr-b-row { display: flex; align-items: flex-start; gap: 12px; }
.larr-b-ico {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px;
  background: var(--login-accent-tint); border: 1px solid rgba(243,119,113,0.22);
  display: grid; place-items: center; color: var(--login-accent-text);
}
.larr-b-ico svg { width: 15px; height: 15px; display: block; }
.larr-b-line { font-size: 13.5px; color: var(--login-text-2); line-height: 1.45; padding-top: 1px; }
.larr-b-line strong { color: var(--login-text); font-weight: 600; }
.larr-b-detail { display: block; font-size: 12px; color: var(--login-text-4); margin-top: 2px; }
.larr-b-cue {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 520; color: var(--login-text-4);
}
.larr-b-cue svg { width: 14px; height: 14px; }
.larr-b-loading { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--login-text-3); }
.larr-b-loading .login-spinner {
  border-color: rgba(243,119,113,0.3); border-top-color: var(--login-accent); margin-right: 0;
}

/* ── Picker (inside the dark panel) ── */
.larr-picker {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex; flex-direction: column; justify-content: center;
  padding: 56px 48px 120px;
}
.larr-p-eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(247,248,248,0.45); margin-bottom: 10px;
}
.larr-p-title {
  font-size: 23px; font-weight: 640; letter-spacing: -0.02em;
  color: #F7F8F8; margin-bottom: 20px;
}
.larr-p-rows { display: flex; flex-direction: column; gap: 9px; max-width: 520px; }
.larr-p-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: rgba(255,255,255,0.045);
  border: 1px solid rgba(255,255,255,0.11);
  border-radius: 12px; padding: 12px 14px;
  font-family: inherit; text-align: left; cursor: pointer;
  transition: background var(--motion-fast, 0.15s), border-color var(--motion-fast, 0.15s),
              opacity 0.3s, transform 0.3s;
}
.larr-p-row:hover { background: rgba(255,255,255,0.085); border-color: rgba(255,255,255,0.2); }
.larr-p-row.chosen { border-color: rgba(243,119,113,0.65); background: rgba(243,119,113,0.10); }
.larr-p-row.recede { opacity: 0.18; transform: translateY(4px); pointer-events: none; }
.larr-p-avatar {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center;
  background: linear-gradient(135deg, #faa963, #f37771 50%, #ef5386);
  color: #fff; font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
}
.larr-p-info { min-width: 0; flex: 1 1 auto; }
.larr-p-name {
  display: block; font-size: 13.5px; font-weight: 600; color: #F7F8F8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.larr-p-meta { display: block; font-size: 11px; color: rgba(247,248,248,0.5); margin-top: 1px; }
.larr-p-logos {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  flex: 0 0 auto; width: 56px;
}
.larr-p-logos svg { width: 14px; height: 14px; display: block; }
.larr-p-flag {
  flex: 0 0 auto; min-width: 62px; display: inline-flex; align-items: center; justify-content: center;
  padding: 3px 8px; border-radius: 999px;
  font-size: 10px; font-weight: 700; white-space: nowrap;
}
.larr-p-flag--green { background: rgba(48,164,108,0.22); color: #7fe0ab; }
.larr-p-flag--amber { background: rgba(245,166,35,0.2); color: #ffd489; }
.larr-p-flag--red   { background: rgba(226,75,74,0.24); color: #ff9d99; }
.larr-p-health {
  flex: 0 0 auto; min-width: 26px; text-align: center;
  padding: 3px 7px; border-radius: 8px; font-size: 11px; font-weight: 700;
}
.larr-p-health--a, .larr-p-health--b { background: rgba(48,164,108,0.22); color: #7fe0ab; }
.larr-p-health--c { background: rgba(245,166,35,0.2); color: #ffd489; }
.larr-p-health--d, .larr-p-health--f { background: rgba(226,75,74,0.24); color: #ff9d99; }
.larr-p-foot { font-size: 11px; color: rgba(247,248,248,0.38); margin-top: 16px; }
/* stats stream in when /api/clients/summary lands */
.larr-p-late { opacity: 0; transition: opacity 0.4s ease; }
.larr-stats-in .larr-p-late { opacity: 1; }

/* ── Fork choice (inside the dark panel — first login, no workspace yet) ──
   The D11 demo-vs-connect fork presented picker-style (fork-arrival-lab
   concept 1, Tom-locked 2026-08-30). Geometry mirrors .larr-p-row scaled up
   to card weight; explicit grid placements (an item with a definite row
   would otherwise place before the auto-flowed title). */
.larr-fork {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex; flex-direction: column; justify-content: center;
  padding: 56px 48px 120px;
}
.larr-f-eyebrow {
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(247,248,248,0.45); margin-bottom: 14px;
}
.larr-f-cards { display: flex; flex-direction: column; gap: 12px; max-width: 470px; }
.larr-f-card {
  display: grid; grid-template-columns: 46px 1fr auto; gap: 4px 15px; align-items: center;
  width: 100%; text-align: left; cursor: pointer; font-family: inherit;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.13);
  border-radius: 14px; padding: 18px 20px;
  transition: background var(--motion-fast, 0.15s), border-color var(--motion-fast, 0.15s),
              opacity 0.3s, transform 0.3s;
}
.larr-f-card:hover { background: rgba(255,255,255,0.09); border-color: rgba(255,255,255,0.24); }
.larr-f-card--connect { border-color: rgba(243,119,113,0.45); }
.larr-f-card--connect:hover { border-color: rgba(243,119,113,0.75); background: rgba(243,119,113,0.08); }
.larr-f-card.chosen { border-color: rgba(243,119,113,0.85); background: rgba(243,119,113,0.12); }
.larr-f-card.recede { opacity: 0.16; transform: translateY(4px); pointer-events: none; }
.larr-f-ico {
  grid-column: 1; grid-row: 1 / 3;
  width: 46px; height: 46px; border-radius: 12px;
  display: grid; place-items: center;
  background: rgba(255,255,255,0.08); color: rgba(247,248,248,0.85);
}
.larr-f-ico svg { width: 22px; height: 22px; display: block; }
.larr-f-ico--brand {
  background: linear-gradient(135deg, #faa963, #f37771 50%, #ef5386);
  color: #fff;
}
.larr-f-title {
  grid-column: 2; grid-row: 1; align-self: end;
  font-size: 15.5px; font-weight: 650; letter-spacing: -0.015em; color: #F7F8F8;
}
.larr-f-sub {
  grid-column: 2; grid-row: 2;
  font-size: 12.5px; line-height: 1.45; color: rgba(247,248,248,0.55);
}
.larr-f-arrow { grid-column: 3; grid-row: 1 / 3; color: rgba(247,248,248,0.4); }
.larr-f-arrow svg { width: 16px; height: 16px; display: block; }
.larr-f-trust {
  margin-top: 20px; max-width: 470px;
  font-size: 12px; line-height: 1.5; color: rgba(247,248,248,0.42);
}

/* ── Wizdock phase (.larr-wizdock) — the fork's "create" path: the dark
   panel docks onto the wizard's own #08090A left rail (same fill, geometry
   only; main-thread clip tween from LoginPage.enterFork). Carries the static state:
   left side + brandpane stay hidden, the darkload fades, the snow clip
   holds the expanded rect (white dots outside the shrinking slab sit on
   white — invisible), and the INK wave copy is removed so no dark dots can
   sit on the revealed white stage while the surge still plays on the slab
   (the deliberate overlap — a strictly-sequenced dock is a dead slab). */
.larr-wizdock .login-wave--snow { clip-path: inset(12px round 16px); }
.larr-wizdock .login-wave--ink { display: none; }
.larr-wizdock .login-brandpane { animation: none; opacity: 0; }
.larr-wizdock .login-formpane { opacity: 0; }
.larr-wizdock .larr-darkload { opacity: 0; }

/* ── Beat 4: the panel expands to a floating full-page panel (.larr-expand) ──
   §34.5 v2: end state is inset 12px round 16 — the white page reads as a
   thin light frame around the dark. The darkfill's motion is the
   main-thread clip-path tween from LoginPage (no layout work — the §34.1 principle-6
   lesson was layout transitions starving under hydration commits; a clip
   animation between matching inset() shapes stays off the layout path and
   keeps the corners crisp at every frame). This class carries only the
   state that ISN'T the slab's motion. The snow clip snaps open to the SAME
   end rect with no transition: snow dots are white — invisible outside the
   dark — so the expanding slab is what reveals them. */
.larr-expand .login-wave--snow { clip-path: inset(12px round 16px); }
/* login.css gives .login-brandpane a forwards-filling loginPaneIn (opacity)
   — cancel the fill so the fade can win (CLAUDE.md forwards-fill rule). */
.larr-expand .login-brandpane { animation: none; transition: opacity 0.3s ease; opacity: 0; }
.larr-expand .login-formpane { transition: opacity 0.35s ease; opacity: 0; }

/* loading state over the expanded dark — clipped to the floating panel's
   rect so the dawn gradient can't wash warm tints onto the 12px light frame */
.larr-darkload {
  position: absolute; inset: 0; z-index: 4;
  clip-path: inset(12px round 16px);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; pointer-events: none;
  opacity: 0; transition: opacity 0.4s ease;
}
/* the loading state waits for the dark to CLOSE over the screen: the
   expansion runs 0.15s (recede beat) + --larr-expand-t, so the bloom starts
   just as the last corner lands (Tom timing note, 2026-08-30) */
.larr-expand .larr-darkload { opacity: 1; transition-delay: calc(0.1s + var(--larr-expand-t)); }
/* the dawn survives into the loading beat */
.larr-darkload::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 40% 28% at 50% 103%, rgba(250,169,99,0.52) 0%, rgba(243,119,113,0.30) 42%, transparent 74%),
    radial-gradient(ellipse 80% 62% at 50% 105%, rgba(243,119,113,0.17) 0%, rgba(239,83,134,0.07) 52%, transparent 80%);
}
.larr-dl-lock { display: flex; align-items: center; gap: 10px; margin-bottom: 26px; }
.larr-dl-lock img { width: 34px; height: 33px; display: block; }
.larr-dl-lock svg { height: 20px; width: auto; color: #F7F8F8; }
.larr-dl-spinner {
  width: 30px; height: 30px; margin: 0 0 22px; position: relative; color: #f37771;
  background: radial-gradient(7.5px, currentColor 94%, #0000);
}
.larr-dl-spinner::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(6.8px at bottom right, #0000 94%, currentColor) top left,
    radial-gradient(6.8px at bottom left,  #0000 94%, currentColor) top right,
    radial-gradient(6.8px at top    right, #0000 94%, currentColor) bottom left,
    radial-gradient(6.8px at top    left,  #0000 94%, currentColor) bottom right;
  background-size: 15px 15px; background-repeat: no-repeat;
  animation: covLoaderPulse 1.5s infinite cubic-bezier(0.3, 1, 0, 1);
}
.larr-dl-title { font-size: 21px; font-weight: 700; letter-spacing: -0.03em; color: #F7F8F8; margin-bottom: 8px; }
.larr-dl-title strong {
  font-weight: 700;
  background: linear-gradient(135deg, #faa963, #f37771 50%, #ef5386);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.larr-dl-copy { font-size: 13.5px; color: rgba(247,248,248,0.55); max-width: 340px; line-height: 1.6; }

/* ── Beat 5: the workspace assembles (.larr-landing, §34.5 v2.1 —
   "Surge & release", strict sequence locked in wave-exit-lab.html) ──
   This class carries only the STATIC landing state; the whole timed
   choreography is delay-sequenced from LoginPage (WAAPI for colour/opacity,
   the main-thread tween for the clip):
     wave surge-dissolve (the wave's own clock — LoginWave `exiting` prop;
     do NOT add a CSS opacity fade on the wave copies here, it would kill
     the surge) → colour morph (darkfill → measured content-window bg, page
     veil → measured chrome bg) → shrink onto the .content-window footprint
     (live shell vars) with the veil fading chrome → transparent → reveal.
   The darkfill deliberately keeps NO landing z-index bump: it stays under
   the wavefield so the surge plays out over the dark; by the time the
   colour morph could expose the ink copy, the wave has fully departed. */
/* hold the snow clip at the expanded panel rect while the surge departs —
   without this the .larr-expand snap reverts and white dots pop back to
   the resting half-pane rect */
.larr-landing .login-wave--snow { clip-path: inset(12px round 16px); }
.larr-landing .login-brandpane { animation: none; opacity: 0; }
.larr-landing .login-formpane { opacity: 0; }
.larr-landing .larr-darkload { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .login-page .larr-in { animation-duration: 0.01ms; }
  .login-brandpane-lockup, .login-brandpane-tagline, .larr-dawnboost,
  .larr-darkload { transition: none; }
}

/* ── Workspace switch theatre (§34.5 switch variant, .wsx) ──
   The arrival recipe in reverse for in-session client switches
   (WorkspaceSwitchTheatre.tsx). The chrome never leaves: the overlay root
   is TRANSPARENT (no veil — the real nav/header show behind the floating
   panel's 12px frame) and only the darkfill + snow wave + darkload render.
   All darkfill motion is inline from the component (WAAPI colour/opacity,
   main-thread clip tween); these rules carry
   the static state. */
.login-page.wsx {
  background: transparent;
  overflow: hidden;
}
/* ink dots belong to the login's white page — over app chrome they'd read
   as dirt; the snow copy (clipped to the floating panel) is the whole show */
.wsx .login-wave--ink { display: none; }
.wsx .login-wave--snow { clip-path: inset(12px round 16px); }
/* loading lockup blooms mid-entry, fades at landing (base .larr-darkload
   transition carries both directions) */
.wsx.wsx-load .larr-darkload { opacity: 1; }

/* fadeout exit — no-real-client users head to the demo-vs-connect fork,
   which has no nav to dissolve into; the whole overlay lifts instead. */
.login-page.larr-fadeout {
  transition: opacity 0.35s ease;
  opacity: 0;
  pointer-events: none;
}

/* boot variant — the surface mounts over the workspace-loading state already
   in the arrival phase (no form to morph from: Google-SSO returns + fresh
   browser sessions), so the whole page fades in as one. */
@keyframes larrBootIn { from { opacity: 0; } to { opacity: 1; } }
.login-page.larr-boot { animation: larrBootIn 0.45s ease both; }
@media (prefers-reduced-motion: reduce) {
  .login-page.larr-boot { animation-duration: 0.01ms; }
}

/* ── Motion S9 sweep: reduced-motion guard for the brand-pane entrance ── */
@media (prefers-reduced-motion: reduce) {
  .login-brandpane { animation-duration: 0.01ms; }
}
