/* Login — standalone page, responsive, no dashboard chrome. Self-sufficient
   theme tokens (this page does NOT load variables.css/reset.css/animations.css
   — see docs/design-system.md §6/§9 for why), using the SAME canonical token
   names the app uses so atoms.css's .btn/.input classes resolve identically
   here as they do in-app. Dark-first polarity (bare :root = dark values,
   `@media (prefers-color-scheme: light)` overrides to light), mirroring both
   this page's own pre-existing OS-driven behaviour and note-share.css's
   pattern. Mirrors note-share.css structurally. */

:root {
  --bg: #1c1c1e;
  --card: #2c2c2e;
  --border: rgba(255,255,255,0.10);
  --text: #f5f5f7;
  --text2: #c3c3c8;
  --text3: #9a9aa1;

  --accent: #007AFF;           /* fixed brand blue — tests/ui/full_audit.mjs pins this */
  --accent-bg: #0062d6;
  --accent-bg-hover: #0073f5;
  --accent-text: #5fa8ff;      /* accent-as-foreground (AA on dark --bg/--card) */

  --green: #34C759;
  --green-text: #5be07f;
  --red: #FF6961;
  --red-text: #ff9b91;
  --error: var(--red);
  --success: var(--green);

  --input-bg: rgba(255,255,255,0.08);
  --hover-bg: rgba(255,255,255,0.10);
  --press-bg: rgba(255,255,255,0.16);
  --disabled-bg: rgba(255,255,255,0.04);
  --disabled-fg: rgba(255,255,255,0.32);
  --shadow-focus: 0 0 0 3px rgba(0,122,255,0.32);

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

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-7: 32px;

  --text-xs: 11px; --text-sm: 12px; --text-base: 14px; --text-md: 15px;
  --text-lg: 16px; --text-xl: 18px; --text-2xl: 20px; --text-3xl: 24px;

  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --tap-min: 36px;
  --tap-comfortable: 44px;

  --transition-fast: 0.12s cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);

  --icon-md: 20px;

  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left:   env(safe-area-inset-left, 0px);
  --safe-right:  env(safe-area-inset-right, 0px);
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f5f5f7;
    --card: #ffffff;
    --border: rgba(0,0,0,0.08);
    --text: #1d1d1f;
    --text2: #5b5b60;
    --text3: #6b6b70;

    --accent-bg-hover: #0050b3;
    --accent-text: #0062d6;

    --green-text: #1a7f37;
    --red: #FF3B30;
    --red-text: #d70015;

    --input-bg: rgba(0,0,0,0.04);
    --hover-bg: rgba(0,0,0,0.06);
    --press-bg: rgba(0,0,0,0.10);
    --disabled-bg: rgba(0,0,0,0.04);
    --disabled-fg: rgba(0,0,0,0.30);
    --shadow-focus: 0 0 0 3px rgba(0,122,255,0.18);
  }
}

/* ── Minimal local reset (not reset.css — its `body{display:flex;min-height:
   100dvh}` rule is app-shell layout that would fight this page's own
   flex-centered card layout) ─────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

/* ── Screen reader only utility (copied verbatim from animations.css — see
   docs/design-system.md §9 for why this page duplicates rather than links) */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ── Global keyboard focus ring — copied from animations.css's rule (this
   page doesn't load animations.css, so atoms.css's .btn/.input alone have
   no focus-visible styling of their own; without this, keyboard focus falls
   back to each browser's default UA outline instead of the vNext ring). */
:where(button, a, [role="button"], input):focus { outline: none; }
:where(button, a, [role="button"], input):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}
input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

html, body { height: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", "Segoe UI", Roboto, system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding:
    max(24px, var(--safe-top))
    max(24px, var(--safe-right))
    max(24px, var(--safe-bottom))
    max(24px, var(--safe-left));
  -webkit-font-smoothing: antialiased;
  position: relative;
  overflow: hidden;
}

/* Soft ambient gradient backdrop — distinctive, not loud */
body::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(80% 60% at 20% 20%, rgba(0,122,255,0.18), transparent 60%),
    radial-gradient(60% 50% at 80% 80%, rgba(91,91,214,0.16), transparent 60%),
    radial-gradient(50% 40% at 60% 30%, rgba(52,199,89,0.10), transparent 60%);
  pointer-events: none;
  filter: blur(40px);
  z-index: 0;
}
@media (prefers-color-scheme: light) {
  body::before {
    background:
      radial-gradient(80% 60% at 20% 20%, rgba(0,122,255,0.12), transparent 60%),
      radial-gradient(60% 50% at 80% 80%, rgba(91,91,214,0.10), transparent 60%);
  }
}

.card {
  position: relative; z-index: 1;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 44px 36px 32px;
  width: 100%;
  max-width: 380px;
  text-align: center;
  box-shadow: 0 24px 64px rgba(0,0,0,0.45), 0 2px 8px rgba(0,0,0,0.20);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  overflow: hidden;
}
/* A quiet top accent bar — the same brand green as the mark below it, not a
   new color — signals "this card is a security boundary" before a single
   word is read, the same instinct a bank or password manager's sign-in
   card leans on. */
.card::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, #2D6A4F, #40916C);
}

/* Reassurance line, not a caveat: pairs the passkey button with the one
   sentence that explains *why* it's the safer default, so the page reads as
   a security decision the user is informed about rather than a bare button. */
.security-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--text3);
  line-height: 1.5;
  text-align: left;
}
.security-note svg { flex: 0 0 auto; margin-top: 1px; color: var(--text3); }

.brand-mark {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 76px; height: 76px;
  background: linear-gradient(150deg, #2D6A4F, #1B4332 72%);
  border-radius: 22px;
  box-shadow: 0 14px 36px rgba(27,67,50,0.42),
              inset 0 1px 0 rgba(255,255,255,0.18),
              inset 0 -1px 0 rgba(0,0,0,0.22);
  margin-bottom: var(--space-4);
  font-size: 40px; line-height: 1;
  color: #fff;
  overflow: hidden;
}
.brand-mark::before {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.35), transparent 55%);
  pointer-events: none;
}
.brand-mark .raptor-mascot { width: 54px; height: auto; overflow: hidden;
  filter: drop-shadow(0 3px 5px rgba(0,0,0,0.28)); }

/* ── Ember, the Tickforge mascot (T. rex) ─────────────────────────────────
   Duplicated from web/styles/animations.css, itself the CSS half of
   web/js/atoms/mascot.js. This page is standalone and does not load the app's
   stylesheet graph, so it carries its own copy — the accepted pattern here
   (docs/design-system.md §9). Login renders the idle brand mark and the egg loader.
   Update every comment-flagged copy in the same change. */

/* ══ MASCOT ARTWORK — parts, rigging, states ══════════════ */
/* hidden, not visible: the tier crops ARE viewBox crops, and overflow:visible
   lets everything outside the box paint anyway — bust and mark then spill the
   whole animal. Every effect is authored inside the frame so this can clip. */
.raptor-mascot{display:block;overflow:hidden}
/* Pivots are fill-box PERCENTAGES, measured from each group's own bbox, so a
   pivot survives all three tier viewBox crops. A px origin under
   transform-box:view-box would shift by each crop's min-x/min-y. */
.raptor-mascot g,.raptor-mascot path,.raptor-mascot circle,.raptor-mascot ellipse,.raptor-mascot rect,.raptor-mascot text{transform-box:fill-box}
/* NEVER put a transform="rotate(a cx cy)" attribute on artwork inside .raptor-mascot —
   it is a presentation attribute for the CSS transform property,so fill-box
   re-bases cx/cy onto that element's own bbox and throws it off the canvas. */
.raptor-mascot .p-all,.raptor-mascot .p-body-g{transform-origin:51.4% 100%}
.raptor-mascot .p-tail{transform-origin:95.8% 38.2%}    /* the hip */
.raptor-mascot .p-head{transform-origin:17.1% 75.6%}  /* the neck base */
.raptor-mascot .p-crest{transform-origin:77.1% 57.2%}
.raptor-mascot .p-jaw{transform-origin:2.1% 17.6%}    /* the jaw hinge */
.raptor-mascot .p-brow{transform-origin:47.2% 77.2%}
.raptor-mascot .p-lid{transform-origin:49.7% 0%;transform:scaleY(0)}
.raptor-mascot .p-arm{transform-origin:0% 5.2%}       /* the shoulder */
.raptor-mascot .p-pupil{transform-origin:50% 50%}
.raptor-mascot .p-mouth{opacity:0}
/* the mouth cavity behind the jaw shows only while the jaw is swung open */
.raptor-mascot[data-mascot-state="success"] .p-mouth{opacity:1}
.raptor-mascot .acc,.raptor-mascot .fx{opacity:0;pointer-events:none}

/* detail suppression at mark tier — 16-40px */
.raptor-mascot[data-mascot-tier="mark"] .d-fine,.raptor-mascot[data-mascot-tier="mark"] .p-nostril{display:none}
.raptor-mascot[data-mascot-tier="mark"] .p-brow{transform:translateY(-.5px) scale(1.1)}

/* idle — the resting pose everything falls back to */
@keyframes em-breathe{0%,100%{transform:translateY(0) scaleY(1)}
  50%{transform:translateY(calc(-2px*var(--m-amp,1))) scaleY(calc(1 + .018*var(--m-amp,1)))}}
@keyframes em-tail{0%,72%,100%{transform:rotate(0)}
  82%{transform:rotate(calc(-7deg*var(--m-amp,1)))}91%{transform:rotate(calc(4deg*var(--m-amp,1)))}}
@keyframes em-blink{0%,93%,97%,100%{transform:scaleY(0)}95%{transform:scaleY(1)}}
@keyframes em-crest{0%,84%,100%{transform:rotate(0)}
  90%{transform:rotate(calc(-5deg*var(--m-amp,1)))}94%{transform:rotate(calc(3deg*var(--m-amp,1)))}}
.raptor-mascot .p-body-g{animation:em-breathe calc(4.2s/var(--m-speed,1)) ease-in-out infinite}
.raptor-mascot .p-tail{animation:em-tail calc(5.4s/var(--m-speed,1)) ease-in-out infinite}
.raptor-mascot .p-lid{animation:em-blink calc(6s/var(--m-speed,1)) infinite}
.raptor-mascot .p-crest{animation:em-crest calc(7.5s/var(--m-speed,1)) ease-in-out infinite}

/* ── egg / hatching — its own artwork ────────────────────── */
.egg-loader{display:block;overflow:visible}
.egg-loader g,.egg path,.egg polyline,.egg ellipse{transform-box:fill-box}
.egg-loader .egg-shell{transform-origin:50% 94.1%}
.egg-loader .egg-cap{transform-origin:20.6% 91.7%}
.egg-loader .egg-crest,.egg-loader .egg-seam,.egg-loader .egg-cap{opacity:0}
@keyframes egg-rock{0%,100%{transform:rotate(calc(-5deg*var(--m-amp,1)))}
  50%{transform:rotate(calc(5deg*var(--m-amp,1)))}}
@keyframes egg-seam-in{0%,44%{opacity:0}66%{opacity:.95}100%{opacity:.95}}
@keyframes egg-cap-off{0%,58%{opacity:0;transform:translate(0,0) rotate(0)}
  72%{opacity:1;transform:translate(-3px,-5px) rotate(-15deg)}
  100%{opacity:1;transform:translate(-6px,-3px) rotate(-24deg)}}
@keyframes egg-crest-up{0%,60%{opacity:0;transform:translateY(7px) scale(.7)}
  84%{opacity:1;transform:translateY(0) scale(1.06)}100%{opacity:1;transform:translateY(0) scale(1)}}
.egg-loader .egg-shell{animation:egg-rock calc(1.5s/var(--m-speed,1)) ease-in-out infinite}
.egg-loader[data-mascot-state="hatching"] .egg-seam{animation:egg-seam-in calc(2.1s/var(--m-speed,1)) ease-out both}
.egg-loader[data-mascot-state="hatching"] .egg-cap{animation:egg-cap-off calc(2.1s/var(--m-speed,1)) ease-out both}
.egg-loader[data-mascot-state="hatching"] .egg-crest{animation:egg-crest-up calc(2.1s/var(--m-speed,1)) ease-out both;
  transform-origin:73.1% 100%}
.egg-loader[data-mascot-state="hatching"] .egg-shell{animation:egg-rock calc(1.5s/var(--m-speed,1)) ease-in-out 1.4}


h1 {
  font-size: 26px;
  font-weight: var(--weight-bold);
  color: var(--text);
  letter-spacing: -0.02em;
  margin-bottom: var(--space-1);
}
.tagline {
  font-size: var(--text-sm);
  color: var(--text2);
  margin-bottom: var(--space-7);
  letter-spacing: 0.01em;
}

/* Primary/registration buttons compose atoms.css's .btn/.btn-primary/.btn-lg
   (≥44px, required by tests/ui/full_audit.mjs) and .btn-ghost. Google's own
   brand button stays a local, unstyled-by-atoms variant (Google's brand
   guidelines require its own fixed white/neutral treatment in both themes —
   same treatment --jira-brand gets elsewhere). */
.btn-google {
  background: #ffffff;
  color: #1f1f1f;
  border: 1px solid #dadce0;
  font-weight: var(--weight-medium);
}
.btn-google:hover:not(:disabled) {
  background: #f7f8f8;
  box-shadow: 0 1px 4px rgba(60,64,67,0.20);
}
.btn-google svg { width: 18px; height: 18px; flex: 0 0 auto; }

#view-invite .btn-ghost { margin-top: var(--space-3); }

.or-divider {
  display: flex; align-items: center; gap: var(--space-3);
  margin: 14px 2px; color: var(--text3); font-size: var(--text-xs);
}
.or-divider::before, .or-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--border);
}

.msg {
  margin-top: var(--space-4);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  line-height: 1.5;
  display: none;
  text-align: left;
}
.msg.error   { background: rgba(255,69,58,0.14); color: var(--red-text);    display: block; border: 1px solid rgba(255,69,58,0.20); }
.msg.success { background: rgba(52,199,89,0.14); color: var(--green-text);  display: block; border: 1px solid rgba(52,199,89,0.20); }
.msg.info    { background: rgba(0,122,255,0.12); color: var(--accent-text); display: block; border: 1px solid rgba(0,122,255,0.20); }

.hint {
  font-size: var(--text-xs);
  color: var(--text3);
  margin-top: var(--space-4);
  line-height: 1.55;
}
.hint code {
  background: var(--input-bg);
  padding: 1px 6px;
  border-radius: var(--radius-xs);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: var(--text-xs);
  color: var(--text);
}

.invite-link {
  display: inline-block;
  margin-top: var(--space-5);
  padding: 6px 10px;
  font-size: var(--text-sm);
  color: var(--text2);
  cursor: pointer;
  border-radius: 6px;
  text-decoration: none;
  transition: color var(--transition-fast), background var(--transition-fast);
}
.invite-link:hover { color: var(--accent); background: var(--input-bg); }

#view-loading { padding: 16px 0; }

#auth-overlay {
  display: none;
  position: fixed; inset: 0;
  background: var(--bg);
  z-index: 100;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  opacity: 0;
  transition: opacity 0.25s ease;
}
#auth-overlay.visible { display: flex; }
#auth-overlay.faded   { opacity: 1; }
.auth-overlay-text {
  font-size: var(--text-md); font-weight: var(--weight-medium);
  color: var(--text2); letter-spacing: 0.01em;
}

/* Token/invite inputs use atoms.css's .input, sized up via .input-lg
   (44px, matches the primary button height on the same view). */
.input { margin-bottom: var(--space-3); }
.input::placeholder { color: var(--text3); }


@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
