/* ==========================================================================
   Formula MXM: site styles
   Shared by index.html and register.html, so the browser downloads this
   once and reuses it on the second page.

   Palette and type roles come from the product's own design tokens
   (src/constants/colors.ts and typography.ts in the app repo). That system
   is deliberately dark only, "a near-black base with a single energetic
   accent", so this site commits to one theme rather than inventing a light
   variant. Every colour is painted explicitly, so the page holds up
   whatever theme the visitor's browser prefers.

   Contents
     1. Fonts
     2. Tokens
     3. Reset and base
     4. Background: grid, glow, cubes
     5. Layout: page, header, footer
     6. Type
     7. Buttons
     8. Home: streak grid
     9. Register: card, form, thank you
    10. Responsive
    11. Reduced motion
   ========================================================================== */

/* 1. Fonts ---------------------------------------------------------------- */

@font-face {
  font-family: 'Inter Var';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter Tight Var';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter-tight.woff2') format('woff2');
}

/* 2. Tokens --------------------------------------------------------------- */

:root {
  /* ground */
  --bg: #0a0a0c;
  --surface: #141417;
  --surface-alt: #1d1d22;
  --border: #2a2a31;

  /* the one accent */
  --accent: #d9ff47;
  --accent-pressed: #bfe33a;
  --on-accent: #0a0a0c;
  --accent-subtle: rgba(217, 255, 71, 0.12);
  --accent-line: rgba(217, 255, 71, 0.22);
  --accent-glow: rgba(217, 255, 71, 0.28);

  /* semantic */
  --danger: #f87171;
  --danger-subtle: rgba(248, 113, 113, 0.12);

  /* text */
  --text: #f5f5f7;
  --text-muted: #a1a1aa;
  --text-faint: #6b6b75;

  /* type */
  --font-body: 'Inter Var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    Helvetica, Arial, sans-serif;
  --font-display: 'Inter Tight Var', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, Helvetica, Arial, sans-serif;

  /* motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* shape */
  --radius-card: 20px;
  --radius-control: 10px;

  color-scheme: dark;
}

/* 3. Reset and base ------------------------------------------------------- */

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

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  min-height: 100vh;
  overflow-x: hidden;
  background-color: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg {
  max-width: 100%;
}

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

/* 4. Background: grid, glow, cubes ---------------------------------------- */

/* A faint engineering grid, almost entirely veiled by the scrim below it.
   It reads as texture rather than pattern. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-color: var(--bg);
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 34px 34px;
  background-position: center;
}

.backdrop::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--bg);
  opacity: 0.965;
}

/* The glow is split in two: the wrapper carries cursor parallax, the inner
   element carries the breathing animation. Keeping them apart means the two
   transforms never overwrite each other. */
.glow-wrap {
  position: fixed;
  top: var(--glow-top, 38%);
  left: 50%;
  z-index: 0;
  width: min(60vw, 720px);
  height: min(60vw, 720px);
  pointer-events: none;
  transform: translate(-50%, -50%) translate(var(--glow-x, 0px), var(--glow-y, 0px));
  will-change: transform;
}

.glow {
  width: 100%;
  height: 100%;
  filter: blur(10px);
  background: radial-gradient(circle, var(--accent-glow) 0%, rgba(217, 255, 71, 0) 68%);
  opacity: 0;
  animation:
    glow-in 1.4s ease-out 0.15s forwards,
    glow-breathe 9s ease-in-out 1.4s infinite;
}

@keyframes glow-in {
  to {
    opacity: 1;
  }
}

@keyframes glow-breathe {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.85;
  }
  50% {
    transform: scale(1.08);
    opacity: 1;
  }
}

/* Wireframe blocks: the streak cell given a third dimension. Injected by
   site.js; sized, timed and placed here. */
.cube-orbit {
  position: fixed;
  z-index: 0;
  width: var(--size);
  height: var(--size);
  perspective: 600px;
  pointer-events: none;
  animation: cube-bob var(--bob) ease-in-out infinite;
}

/* Wide screens: the text column is narrow and centred, so the cubes sit in
   the generous margins on either side. */
.cube-1 {
  --size: 26px;
  --spin: 19s;
  --bob: 8s;
  top: 16%;
  left: 10%;
}

.cube-2 {
  --size: 16px;
  --spin: 14s;
  --bob: 6.5s;
  top: 70%;
  left: 6%;
}

.cube-3 {
  --size: 20px;
  --spin: 22s;
  --bob: 9s;
  top: 22%;
  right: 9%;
}

.cube-4 {
  --size: 14px;
  --spin: 16s;
  --bob: 5.5s;
  top: 76%;
  right: 13%;
}

.cube-spin {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  animation: cube-spin var(--spin) linear infinite;
}

.cube {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

.cube-face {
  position: absolute;
  inset: 0;
  border: 1px solid var(--accent-line);
  border-radius: 2px;
  background-color: var(--accent-subtle);
}

.cube-face-front {
  transform: translateZ(calc(var(--size) / 2));
}
.cube-face-back {
  transform: rotateY(180deg) translateZ(calc(var(--size) / 2));
}
.cube-face-right {
  transform: rotateY(90deg) translateZ(calc(var(--size) / 2));
}
.cube-face-left {
  transform: rotateY(-90deg) translateZ(calc(var(--size) / 2));
}
.cube-face-top {
  transform: rotateX(90deg) translateZ(calc(var(--size) / 2));
}
.cube-face-bottom {
  transform: rotateX(-90deg) translateZ(calc(var(--size) / 2));
}

@keyframes cube-spin {
  to {
    transform: rotateX(360deg) rotateY(360deg);
  }
}

@keyframes cube-bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-16px);
  }
}

/* 5. Layout --------------------------------------------------------------- */

.page {
  position: relative;
  z-index: 1;
  display: flex;
  min-height: 100vh;
  flex-direction: column;
  padding: clamp(20px, 4vw, 44px) clamp(20px, 6vw, 64px);
}

.page-main {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px 0;
}

.site-header {
  display: flex;
  align-items: center;
  opacity: 0;
  animation: rise 0.7s var(--ease-out) 0.05s forwards;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}

.brand-mark {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 2px;
  background-color: var(--accent);
}

.brand-name {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  transition: color 0.2s ease;
}

a.brand:hover .brand-name {
  color: var(--text);
}

.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  font-size: 12.5px;
  color: var(--text-faint);
  opacity: 0;
  animation: rise 0.7s var(--ease-out) 1.2s forwards;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 6. Type ----------------------------------------------------------------- */

.eyebrow {
  margin: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.headline {
  margin: 18px 0 0;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 1.6rem + 4.2vw, 4.6rem);
  font-weight: 800;
  line-height: 1.03;
  letter-spacing: -0.025em;
  text-wrap: balance;
  color: var(--text);
}

.headline em {
  font-style: normal;
  color: var(--accent);
}

.lede {
  margin: 20px 0 0;
  max-width: 46ch;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--text-muted);
}

.microcopy {
  margin: 14px 0 0;
  font-size: 12.5px;
  color: var(--text-faint);
  text-align: center;
}

/* 7. Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 24px;
  border: none;
  border-radius: var(--radius-control);
  background-color: var(--accent);
  color: var(--on-accent);
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
  transition:
    background-color 0.2s ease,
    transform 0.15s ease,
    box-shadow 0.2s ease;
}

.btn:hover {
  background-color: var(--accent-pressed);
  transform: translateY(-1px);
  box-shadow: 0 8px 24px -8px var(--accent-glow);
}

.btn:active {
  transform: translateY(0) scale(0.98);
}

.btn:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
  box-shadow: none;
}

.btn svg {
  flex: none;
}

.btn-block {
  width: 100%;
  margin-top: 6px;
}

.btn-quiet {
  display: inline-block;
  margin-top: 22px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 13.5px;
  font-weight: 500;
  text-decoration: none;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

.btn-quiet:hover {
  color: var(--text);
  border-color: var(--text-muted);
}

/* 8. Home: streak grid ---------------------------------------------------- */

.hero {
  display: flex;
  width: 100%;
  max-width: 640px;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.hero .eyebrow {
  opacity: 0;
  animation: rise 0.7s var(--ease-out) 0.28s forwards;
}

.hero .headline {
  opacity: 0;
  animation: rise 0.8s var(--ease-out) 0.42s forwards;
}

.hero .lede {
  opacity: 0;
  animation: rise 0.7s var(--ease-out) 0.56s forwards;
}

.streak {
  width: 100%;
  margin-top: 44px;
  opacity: 0;
  animation: rise 0.7s var(--ease-out) 0.7s forwards;
}

.streak-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}

.streak-label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.streak-count {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.streak-count b {
  color: var(--accent);
  font-weight: 700;
}

.streak-grid {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr);
  gap: 4px;
  justify-content: center;
}

.cell {
  width: 11px;
  height: 11px;
  border-radius: 2.5px;
  background-color: var(--border);
  opacity: 0;
  transform: scale(0.4);
  transition:
    opacity 0.4s ease,
    transform 0.4s var(--ease-spring),
    background-color 0.3s ease;
  transition-delay: var(--delay, 0ms);
}

.streak-grid.is-revealed .cell {
  opacity: 1;
  transform: scale(1);
}

.cell[data-state='done'] {
  background-color: var(--accent);
}

.cell[data-state='rest'] {
  background-color: var(--surface-alt);
}

.cell.is-today {
  animation: cell-pulse 2.2s ease-in-out 1.9s infinite;
}

@keyframes cell-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 var(--accent-glow);
  }
  50% {
    box-shadow: 0 0 0 4px var(--accent-glow);
  }
}

.cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 40px;
  opacity: 0;
  animation: rise 0.7s var(--ease-out) 1.05s forwards;
}

.cta .microcopy {
  margin: 0;
}

/* 9. Register: card, form, thank you -------------------------------------- */

.flip-scene {
  width: 100%;
  max-width: 460px;
  perspective: 1800px;
  opacity: 0;
  animation: rise 0.8s var(--ease-out) 0.2s forwards;
}

/* Both faces share one grid cell, so the scene is always as tall as the
   taller face and neither can ever be clipped. */
.flip-inner {
  display: grid;
  width: 100%;
  transform-style: preserve-3d;
  transition: transform 0.9s cubic-bezier(0.4, 0.2, 0.2, 1);
}

.flip-inner.is-flipped {
  transform: rotateY(180deg);
}

.flip-face {
  grid-area: 1 / 1;
  width: 100%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.flip-face-back {
  display: flex;
  align-items: center;
  transform: rotateY(180deg);
}

.card {
  width: 100%;
  padding: clamp(26px, 4vw, 38px);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background-color: var(--surface);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.65);
}

/* Tilts toward the cursor. transform is written by register.js. */
.card-tilt {
  transform-style: preserve-3d;
  transition:
    transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1),
    box-shadow 0.4s ease;
  will-change: transform;
}

.card-title {
  margin: 10px 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 1.3rem + 1.6vw, 2.2rem);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-align: center;
  text-wrap: balance;
  color: var(--text);
}

.card-sub {
  max-width: 34ch;
  margin: 10px auto 0;
  font-size: 0.95rem;
  line-height: 1.55;
  text-align: center;
  color: var(--text-muted);
}

.form {
  margin-top: 26px;
}

.field-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px;
}

.field {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
  text-align: left;
}

.field label {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
}

.field input {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background-color: var(--surface-alt);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  appearance: none;
  transition:
    border-color 0.2s ease,
    box-shadow 0.2s ease;
}

.field input::placeholder {
  color: var(--text-faint);
}

.field input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-subtle);
}

.field-error {
  display: none;
  font-size: 12px;
  color: var(--danger);
}

.field.is-invalid input {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-subtle);
}

.field.is-invalid .field-error {
  display: block;
}

.form-message {
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
  color: var(--danger);
}

.thanks {
  width: 100%;
  padding: clamp(30px, 5vw, 46px) clamp(24px, 4vw, 38px);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background-color: var(--surface);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.65);
  text-align: center;
  perspective: 600px;
}

.thanks-badge {
  display: flex;
  width: 76px;
  height: 76px;
  align-items: center;
  justify-content: center;
  margin: 0 auto 22px;
  border-radius: 50%;
  background-color: var(--accent);
  transform-origin: bottom center;
  opacity: 0;
}

.is-flipped .thanks-badge {
  animation: badge-in 0.65s var(--ease-spring) 0.55s forwards;
}

@keyframes badge-in {
  from {
    opacity: 0;
    transform: rotateX(-90deg) scale(0.7);
  }
  to {
    opacity: 1;
    transform: rotateX(0deg) scale(1);
  }
}

.thanks-badge svg {
  width: 34px;
  height: 34px;
}

.thanks-badge path {
  fill: none;
  stroke: var(--on-accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 30;
  stroke-dashoffset: 30;
}

.is-flipped .thanks-badge path {
  animation: draw-check 0.4s ease 1.2s forwards;
}

@keyframes draw-check {
  to {
    stroke-dashoffset: 0;
  }
}

.thanks-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 1.9rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-wrap: balance;
  color: var(--text);
  opacity: 0;
}

.thanks-body {
  max-width: 36ch;
  margin: 14px auto 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text-muted);
  opacity: 0;
}

.thanks-note {
  max-width: 36ch;
  margin: 12px auto 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-faint);
  opacity: 0;
}

.is-flipped .thanks-title {
  animation: rise 0.6s var(--ease-out) 0.75s forwards;
}

.is-flipped .thanks-body {
  animation: rise 0.6s var(--ease-out) 0.86s forwards;
}

.is-flipped .thanks-note {
  animation: rise 0.6s var(--ease-out) 0.95s forwards;
}

.thanks-title:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}

/* Shown only when JavaScript is unavailable. */
.noscript-note {
  max-width: 34ch;
  margin: 20px auto 0;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background-color: var(--surface-alt);
  font-size: 13px;
  line-height: 1.55;
  text-align: center;
  color: var(--text-muted);
}

/* 10. Responsive ---------------------------------------------------------- */

/* Narrow screens: text fills the width, so the side margins the cubes lived
   in are gone. Two are retired and the survivors move to the top and bottom
   edges, clear of the text column. */
@media (max-width: 720px) {
  .cube-2,
  .cube-4 {
    display: none;
  }

  .cube-1 {
    --size: 20px;
    top: 6%;
    left: auto;
    right: 7%;
  }

  .cube-3 {
    --size: 16px;
    top: 89%;
    right: 9%;
  }
}

@media (max-width: 560px) {
  .cell {
    width: 8px;
    height: 8px;
    border-radius: 2px;
  }

  .streak-grid {
    gap: 3px;
  }

  .field-row {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .site-footer {
    font-size: 11.5px;
  }

  .site-footer span:last-child {
    display: none;
  }
}

/* 11. Reduced motion ------------------------------------------------------ */

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

  .glow {
    animation: none;
    opacity: 0.9;
  }

  .cube-orbit,
  .cube-spin {
    animation: none;
  }

  .cube {
    transform: rotateX(18deg) rotateY(28deg);
  }

  /* Without motion the reveal animations never run, so paint the final
     state directly rather than leaving these elements invisible. */
  .site-header,
  .site-footer,
  .hero .eyebrow,
  .hero .headline,
  .hero .lede,
  .streak,
  .cta,
  .flip-scene,
  .thanks-badge,
  .thanks-title,
  .thanks-body,
  .thanks-note {
    opacity: 1;
    transform: none;
  }

  .thanks-badge path {
    stroke-dashoffset: 0;
  }

  .streak-grid .cell {
    opacity: 1;
    transform: scale(1);
  }
}
