/* Nixhe — holding page
   Palette sampled directly from the tesseract mark. */

:root {
  --void:        #07040E;
  --void-lift:   #0B0716;
  --indigo:      #4940E5;
  --core:        #6549F7;
  --violet:      #6D29E5;
  --lavender:    #C9BEFF;
  --paper:       #F2EEFF;

  --ink:         var(--paper);
  --ink-soft:    #A79BD4;
  --ink-faint:   #635682;

  --shell:       min(560px, 88vw);
  --mark:        clamp(148px, 30vw, 236px);

  --ease:        cubic-bezier(.22, .68, 0, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100svh;
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  padding: clamp(1.5rem, 5vw, 3rem);
  background: var(--void);
  color: var(--ink);
  font-family: "Manrope", ui-sans-serif, system-ui, sans-serif;
  text-align: center;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* ── Atmosphere ─────────────────────────────────────────────── */

/* Two offset radial washes, breathing out of phase, so the ground
   under the mark never sits perfectly still. */
.aurora {
  position: fixed;
  inset: -20%;
  z-index: -2;
  background:
    radial-gradient(46% 38% at 50% 30%, color-mix(in oklab, var(--core) 42%, transparent) 0%, transparent 68%),
    radial-gradient(52% 44% at 32% 62%, color-mix(in oklab, var(--indigo) 30%, transparent) 0%, transparent 70%),
    radial-gradient(44% 40% at 72% 58%, color-mix(in oklab, var(--violet) 32%, transparent) 0%, transparent 70%);
  filter: blur(28px);
  opacity: .5;
  animation: drift 19s var(--ease) infinite alternate;
}

@keyframes drift {
  from { transform: translate3d(-1.5%, -1%, 0) scale(1);    opacity: .42; }
  to   { transform: translate3d(1.5%, 2%, 0)   scale(1.09); opacity: .6;  }
}

/* Fine noise kills the banding that big soft gradients cause on
   cheap panels, and gives the black some tooth. */
.grain {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: .16;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── Stage ──────────────────────────────────────────────────── */

.stage {
  width: var(--shell);
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* ── The mark ───────────────────────────────────────────────── */

/* Entrance and idle share this element: `both` holds the entrance's end
   state so the mark doesn't fall back to the hidden base opacity, and the
   idle hover takes over transform once it starts. */
.mark {
  margin: 0 0 clamp(2.25rem, 6vw, 3.25rem);
  width: var(--mark);
  animation:
    arrive-mark 1s var(--ease) .1s both,
    hover 8s ease-in-out 1.1s infinite;
}

.mark img {
  display: block;
  width: 100%;
  height: auto;
  /* The glow is the mark's own colour, so it reads as light the
     object is emitting rather than a drop shadow behind it. */
  filter:
    drop-shadow(0 0 26px color-mix(in oklab, var(--core) 55%, transparent))
    drop-shadow(0 0 72px color-mix(in oklab, var(--violet) 42%, transparent));
  animation: pulse 8s ease-in-out infinite;
}

@keyframes hover {
  0%, 100% { transform: translate3d(0, -6px, 0) rotate(-1.1deg); }
  50%      { transform: translate3d(0,  6px, 0) rotate(1.1deg);  }
}

@keyframes pulse {
  0%, 100% { filter: drop-shadow(0 0 22px color-mix(in oklab, var(--core) 45%, transparent))
                     drop-shadow(0 0 60px color-mix(in oklab, var(--violet) 32%, transparent)); }
  50%      { filter: drop-shadow(0 0 34px color-mix(in oklab, var(--core) 68%, transparent))
                     drop-shadow(0 0 96px color-mix(in oklab, var(--violet) 52%, transparent)); }
}

/* ── Type ───────────────────────────────────────────────────── */

.eyebrow {
  margin: 0 0 1.5rem;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .688rem;
  font-weight: 500;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  gap: .85em;
  text-indent: .34em; /* offset the trailing letter-space so it optically centres */
}

/* Rules that taper away from the label rather than stopping dead. */
.eyebrow::before,
.eyebrow::after {
  content: "";
  width: clamp(1.5rem, 7vw, 2.75rem);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--ink-faint));
}
.eyebrow::after { transform: scaleX(-1); }

.title {
  margin: 0 0 1.5rem;
  font-family: "Syne", ui-sans-serif, sans-serif;
  line-height: 1;
}

.title__greeting {
  display: block;
  font-size: clamp(1rem, 3.4vw, 1.25rem);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink-soft);
  margin-bottom: .5em;
}

/* "Nixhe" in Syne 800 measures 4.54x its font-size, so 17vw keeps the
   word inside the 88vw shell at every width without wrapping. */
.title__name {
  display: block;
  font-size: clamp(2.75rem, 17vw, 7.25rem);
  font-weight: 800;
  letter-spacing: -.022em;
  background: linear-gradient(104deg, var(--indigo) 4%, var(--core) 42%, var(--violet) 96%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Gradient text can't take a text-shadow, so the bloom is painted
     as a soft copy sitting underneath. */
  position: relative;
}

.title__name::after {
  content: "Nixhe";
  position: absolute;
  inset: 0;
  z-index: -1;
  color: var(--core);
  filter: blur(30px);
  opacity: .38;
}

.note {
  margin: 0;
  font-size: clamp(.938rem, 2.6vw, 1.063rem);
  font-weight: 400;
  line-height: 1.72;
  color: var(--ink-soft);
  text-wrap: balance;
}

.note__smile {
  color: var(--lavender);
  font-weight: 500;
}

.foot {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .688rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-top: 2.5rem;
}

/* ── Entrance ───────────────────────────────────────────────── */

/* One orchestrated arrival: the mark resolves first, then the copy
   settles under it in reading order. */
[data-reveal] {
  opacity: 0;
  animation: arrive 1s var(--ease) forwards;
}

[data-reveal="2"] { animation-delay: .58s; }
[data-reveal="3"] { animation-delay: .7s;  }
[data-reveal="4"] { animation-delay: .84s; }
[data-reveal="5"] { animation-delay: 1s;   }

@keyframes arrive {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

@keyframes arrive-mark {
  from { opacity: 0; transform: scale(.9) rotate(-7deg); filter: blur(9px); }
  to   { opacity: 1; transform: none;                    filter: blur(0);   }
}

/* ── Quality floor ──────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .aurora, .mark, .mark img { animation: none; }
  .aurora { opacity: .5; }
  [data-reveal] { opacity: 1; animation: none; }
}

:focus-visible {
  outline: 2px solid var(--lavender);
  outline-offset: 4px;
  border-radius: 4px;
}

/* Short landscape phones: reclaim the vertical budget from the mark. */
@media (max-height: 620px) and (orientation: landscape) {
  :root { --mark: 116px; }
  .mark { margin-bottom: 1.5rem; }
  .foot { padding-top: 1.5rem; }
}
