/* ==========================================================================
   preloader.css — Entrance screen: intro (avatar + START) → loading ring
   Do NOT add nav or hero styles here — those belong in nav.css and hero.css.
   ========================================================================== */

.preloader {
  position: fixed;
  inset: 0;
  background:
    radial-gradient(circle at 50% 42%, rgba(255, 255, 255, 0.02), transparent 22%),
    radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.08), transparent 58%),
    linear-gradient(180deg, #121212 0%, #0b0b0b 100%);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: transform;
  overflow: hidden;
}

.preloader::before {
  content: '';
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(circle at center, transparent 0 34%, rgba(0, 0, 0, 0.2) 64%, rgba(0, 0, 0, 0.5) 100%);
  pointer-events: none;
}

.preloader-center {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
  transform: translateY(-8px);
  /* Hidden until fonts are ready, so the START label + avatar never paint in the
     system fallback font and then swap once Syne/Geist load — that swap (and the
     tiny metric shift it causes) is the flash on hard refresh. JS adds
     .fonts-ready once document.fonts.ready resolves (or the 800ms race caps out).
     The safety keyframe reveals it after 1.2s no matter what, so a script/CDN
     failure can never leave the entrance blank. */
  opacity: 0;
  animation: preloaderRevealSafety 0.01s linear 1.2s forwards;
}
@keyframes preloaderRevealSafety { to { opacity: 1; } }
.preloader.fonts-ready .preloader-center {
  opacity: 1;
  animation: none;
  transition: opacity 0.3s ease;
}

/* ── stage-wrap: disc + ring share the same center point ── */
.stage-wrap {
  position: relative;
  width: min(26vw, 144px);
  aspect-ratio: 1;
}

.logo-ring-wrap {
  width: 100%;
  height: 100%;
  position: relative;
  isolation: isolate;
}

.logo-ring-wrap::after {
  content: "";
  position: absolute;
  inset: 22px -12px -28px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 0, 0, 0.28) 0%, rgba(0, 0, 0, 0) 72%);
  filter: blur(10px);
  z-index: -1;
}

.logo-disc {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 56%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(circle at 50% 34%,
    #dfd2bf 0%,
    var(--color-loader-accent) 58%,
    #c8b59a 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    0 26px 54px rgba(0, 0, 0, 0.34);
  z-index: 0;
}

/* ── intro-group: avatar + START (idle). Lifts out when START is pressed. ── */
.intro-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
  transition: opacity 0.52s ease, transform 0.62s cubic-bezier(0.5, 0, 0.2, 1);
}
.preloader[data-phase="boot"] .intro-group {
  opacity: 0;
  transform: translateY(-12px) scale(0.96);
  pointer-events: none;
}

/* ── boot-group: status words + dot ripple, revealed after START ──
   Absolutely centered over the same point the intro-group occupied, so the
   intro lifts out and the boot text fades in on the exact same axis. */
.boot-group {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 34px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s ease;
}
.preloader[data-phase="boot"] .boot-group {
  opacity: 1;
}

/* status words — masked, slide up one by one */
/* NOTE: every selector below is scoped to .boot-group on purpose. The class
   names (.word, .word-mask, .status, .caret, .dot, .dot-bar) are generic and
   collide with site classes — .word in particular is the hero/headline word span
   (initHeroAnimation targets [data-professional] .word). An unscoped `.word {
   opacity: 0 }` here hid the hero reveal text site-wide. Keep these scoped. */
.boot-group .status {
  display: flex;
  gap: 0.42em;
  align-items: flex-end;
  font-family: var(--font-mono);
  font-size: clamp(15px, 2vw, 19px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-text);
}
.boot-group .word-mask {
  overflow: hidden;
  display: inline-block;
  padding-bottom: 2px;
}
.boot-group .word {
  display: inline-block;
  transform: translateY(110%);
  opacity: 0;
}
.preloader[data-phase="boot"] .boot-group .word {
  animation: bootWordUp 0.62s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: var(--wd, 0ms);
}
.boot-group .word.accent {
  color: var(--color-accent);
}
@keyframes bootWordUp {
  to { transform: translateY(0); opacity: 1; }
}

/* caret blinks once the last word lands */
.boot-group .caret {
  display: inline-block;
  width: 0.5em;
  height: 1.05em;
  background: var(--color-accent);
  margin-left: 0.15em;
  transform: translateY(-8px);   /* lift past the words' 2px mask padding so it sits at text level */
  opacity: 0;
}
.preloader[data-phase="boot"] .boot-group .caret {
  animation: bootCaretIn 0.2s ease forwards 1.1s, bootBlink 1s steps(1) infinite 1.3s;
}
@keyframes bootCaretIn { to { opacity: 1; } }
@keyframes bootBlink { 50% { opacity: 0; } }

/* dot ripple bar — glow travels left→right and loops (dots built in main.js) */
.boot-group .dot-bar {
  display: flex;
  gap: 11px;
  align-items: center;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.preloader[data-phase="boot"] .boot-group .dot-bar {
  opacity: 1;
}
.boot-group .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-muted);
  transform: scale(0.85);
}
.preloader[data-phase="boot"] .boot-group .dot {
  animation: bootDotPulse 1.5s ease-in-out infinite;
  animation-delay: var(--d, 0ms);
}
@keyframes bootDotPulse {
  0%, 100% { transform: scale(0.85); background: var(--color-muted); box-shadow: none; }
  18% {
    transform: scale(1.7);
    background: var(--color-loader-accent);
    box-shadow: 0 0 14px 3px rgba(var(--color-loader-accent-rgb), 0.55);
  }
  40% { transform: scale(0.85); background: var(--color-muted); box-shadow: none; }
}

/* Avatar wrap — sized to the SVG's 922:1152 aspect ratio, fits inside ring */
.avatar-wrap {
  position: absolute;
  width: 105%;
  height: auto;
  aspect-ratio: 922 / 1152;
  top: 58%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
}

/* Face SVG sits on the warm disc without inversion to preserve the inked look */
.avatar-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: none;
  pointer-events: none;
  user-select: none;
  display: block;
  z-index: 1;
}

/* Eye-tracking overlay — same viewBox as face SVG, sits directly on top */
.avatar-eyes-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
}

.avatar-eyes-svg .eye-mask {
  fill: #fbfbf8;
}

.avatar-eyes-svg .eye-l,
.avatar-eyes-svg .eye-r {
  fill: #121212;
}

/* ── START button ── */
.start-btn {
  position: relative;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.44em;
  text-transform: uppercase;
  color: var(--color-loader-accent);
  font-weight: 700;
  background: var(--color-backdrop);
  border: 2px solid rgba(var(--color-loader-accent-rgb), 0.42);
  padding: 14px 40px 13px 44px;
  border-radius: 999px;
  cursor: pointer;
  /* Kill the mobile tap flash: the default -webkit-tap-highlight-color paints a
     rectangle that ignores border-radius (the square box seen for a moment on tap).
     The global reset in main.css is scoped to the mode-toggle button only. The
     keyboard focus ring lives in :focus-visible below and is untouched. */
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.22);
  transition:
    transform 0.25s ease,
    box-shadow 0.55s ease,
    border-color 0.55s ease,
    background-color 0.55s ease,
    opacity 0.2s ease,
    color 0.55s ease,
    filter 0.55s ease;
  transition-delay: 0s, 0s, 0s, 0s, 0s, 0s, 0s;
}

.start-btn-label {
  font-weight: 700;
}

.start-btn:hover {
  color: #141414;
  border-color: var(--color-loader-accent);
  background: var(--color-loader-accent);
  transform: translateY(-1px);
  box-shadow: 0 14px 26px rgba(0, 0, 0, 0.28);
  filter: brightness(1.03);
  transition-delay: 0.05s, 0.05s, 0.05s, 0.05s, 0s, 0.05s, 0.05s;
  outline: none;
}

.start-btn:focus-visible {
  box-shadow:
    0 0 0 3px rgba(var(--color-loader-accent-rgb), 0.16),
    0 10px 20px rgba(0, 0, 0, 0.22),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
  outline: none;
}

/* Screen reader live region — visually hidden */
.sr-loading {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (max-width: 640px) {
  .preloader-center {
    gap: 22px;
    transform: translateY(-2px);
  }

  .stage-wrap {
    width: min(35vw, 144px);
  }

  .start-btn {
    font-size: 10px;
    letter-spacing: 0.36em;
    padding: 12px 30px 11px 34px;
  }
}

/* Reduced-motion: skip fade transitions and freeze the boot sequence (words/caret/
   dots shown static, no looping motion). The JS path also cuts straight to the site
   for these users, so this is belt-and-braces. */
@media (prefers-reduced-motion: reduce) {
  .start-btn {
    transition: none;
  }
  .intro-group,
  .boot-group,
  .boot-group .dot-bar {
    transition: none;
  }
  .preloader[data-phase="boot"] .boot-group .word,
  .preloader[data-phase="boot"] .boot-group .caret,
  .preloader[data-phase="boot"] .boot-group .dot {
    animation: none;
  }
  .boot-group .word {
    transform: none;
    opacity: 1;
  }
}

/* ── Light theme overrides ─────────────────────────────────────────────────── */

:root.theme-light .preloader {
  background:
    radial-gradient(circle at 50% 42%, rgba(30, 94, 255, 0.04), transparent 22%),
    radial-gradient(circle at 50% 50%, rgba(10, 31, 122, 0.05), transparent 58%),
    linear-gradient(180deg, #F8FAFC 0%, #EEF4FF 100%);
}

:root.theme-light .preloader::before {
  background: radial-gradient(circle at center, transparent 0 34%, rgba(10, 31, 122, 0.03) 64%, rgba(10, 31, 122, 0.06) 100%);
}

:root.theme-light .logo-ring-wrap::after {
  background: radial-gradient(circle, rgba(30, 94, 255, 0.12) 0%, rgba(30, 94, 255, 0) 72%);
}

:root.theme-light .logo-disc {
  background: radial-gradient(circle at 50% 34%,
    #4D8CFF 0%,
    #1E5EFF 58%,
    #0A1F7A 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    0 26px 54px rgba(10, 31, 122, 0.25);
}

:root.theme-light .start-btn:hover {
  color: #F8FAFC;
  background: #1E5EFF;
  border-color: #1E5EFF;
}

