/*
 * Backword marketing site — visual tokens.
 *
 * Tile colors mirror branding/styles.css (which in turn mirrors
 * theme/paperTheme.ts game tokens). Keep these three files in sync if
 * the app's tile palette ever changes.
 */

:root {
  /* Light theme */
  --light-page-bg: #ffffff;
  --light-text-primary: #000000;
  --light-tile-empty-border: #d3d6da;
  --light-tile-tbd-border: #878a8c;
  --light-tile-tbd-bg: #ffffff;
  --light-tile-tbd-text: #000000;
  --light-tile-correct-bg: #4B807C;
  --light-tile-present-bg: #6A4087;
  --light-tile-absent-bg: #787c7e;
  --light-tile-state-text: #ffffff;

  /* Dark theme */
  --dark-page-bg: #121213;
  --dark-text-primary: #f8f8f8;
  --dark-tile-empty-border: #3a3a3c;
  --dark-tile-tbd-border: #565758;
  --dark-tile-tbd-bg: #121213;
  --dark-tile-tbd-text: #f8f8f8;
  --dark-tile-correct-bg: #3B6A67;
  --dark-tile-present-bg: #5B2C79;
  --dark-tile-absent-bg: #3a3a3c;
  --dark-tile-state-text: #f8f8f8;
}

/* Theme classes resolve a single set of --tile-* variables that the tile
 * rules consume. Apply .theme-light or .theme-dark to <body> (or a smaller
 * subtree) to switch palettes. */
.theme-light {
  --page-bg: var(--light-page-bg);
  --text-primary: var(--light-text-primary);
  --tile-empty-border: var(--light-tile-empty-border);
  --tile-tbd-border: var(--light-tile-tbd-border);
  --tile-tbd-bg: var(--light-tile-tbd-bg);
  --tile-tbd-text: var(--light-tile-tbd-text);
  --tile-correct-bg: var(--light-tile-correct-bg);
  --tile-present-bg: var(--light-tile-present-bg);
  --tile-absent-bg: var(--light-tile-absent-bg);
  --tile-state-text: var(--light-tile-state-text);
}

.theme-dark {
  --page-bg: var(--dark-page-bg);
  --text-primary: var(--dark-text-primary);
  --tile-empty-border: var(--dark-tile-empty-border);
  --tile-tbd-border: var(--dark-tile-tbd-border);
  --tile-tbd-bg: var(--dark-tile-tbd-bg);
  --tile-tbd-text: var(--dark-tile-tbd-text);
  --tile-correct-bg: var(--dark-tile-correct-bg);
  --tile-present-bg: var(--dark-tile-present-bg);
  --tile-absent-bg: var(--dark-tile-absent-bg);
  --tile-state-text: var(--dark-tile-state-text);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  height: 100%;
}

body {
  font-family: 'Libre Franklin', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--page-bg);
  color: var(--text-primary);
  overflow: hidden;
}

/* Splash layout — full viewport, centered content. Phase 2 + 3 will add
 * the boot-stage and resting children. */
.splash {
  position: relative;
  width: 100vw;
  height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.boot-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Resting layout — small logo + App Store badge. Both children of .splash
 * are absolutely positioned (boot-stage AND resting) so they overlay; the
 * resting layer fades in once .boot-stage carries the .boot-complete
 * class, which boot-animation.js adds either when the 5250ms animation
 * finishes or immediately on tap-to-skip. */
.resting {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: clamp(60px, 12vh, 140px);
  gap: 32px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 600ms ease-in 200ms;
}

.boot-stage.boot-complete ~ .resting {
  opacity: 1;
  pointer-events: auto;
}

/* Visually-hidden but readable by screen readers — provides the
 * accessible name for the page since the mini-logo tiles are decorative. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
  white-space: nowrap;
}

/* Wordmark + tagline stack — kept tight so they read as a single unit,
 * with the parent .resting's 32px gap separating them from the icon. */
.resting-titles {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

/* "Backword" wordmark — Roboto Slab 800 ExtraBold, matches the in-game
 * GameHeader and the marketing post generator's title treatment. */
.resting-wordmark {
  font-family: 'Roboto Slab', serif;
  font-weight: 800;
  font-size: clamp(48px, 10vw, 84px);
  line-height: 1;
  color: #ffffff;
  letter-spacing: -0.01em;
  margin: 0;
}

/* "A Daily Word Puzzle" tagline — same Roboto Slab family, lighter weight
 * and smaller size to sit visually below the wordmark. */
.resting-tagline {
  font-family: 'Roboto Slab', serif;
  font-weight: 500;
  font-size: clamp(16px, 3vw, 22px);
  line-height: 1.2;
  color: #ffffff;
  margin: 0;
}

/* App icon shown below the wordmark. Sized to read as a "show off" of
 * the icon without dominating the splash; scales with viewport. */
.resting-icon {
  display: block;
  width: clamp(140px, 28vw, 220px);
  height: auto;
}

/* Mini BACKWORD logo — reuses the .tile primitive at a smaller --tile-size.
 * 28-40px scales with viewport (clamp); matches the layout used in
 * branding/index.html's first logo draft (BACK row + WORD row, offset by
 * grey absent spacers). */
.mini-logo {
  --tile-size: clamp(28px, 6vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.mini-logo-row {
  display: flex;
  gap: 4px;
}

/* App Store badge — Apple's official "Download on the App Store" SVG.
 * Per Apple's marketing guidelines the artwork itself must not be modified
 * (no recolor, no shadow, no stretch); the wrapper link only handles
 * sizing + a subtle interaction state. Clear space requirement (≥ 1/10
 * the badge height on all sides) is covered by the .resting gap. */
.app-store-badge {
  display: inline-block;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 150ms ease-out;
}

.app-store-badge:hover,
.app-store-badge:focus-visible {
  opacity: 0.85;
}

.app-store-badge img {
  display: block;
  height: clamp(48px, 9vw, 64px);
  width: auto;
}

/* Privacy policy page — long-form legal text. Force light regardless of
 * OS theme (the body class is theme-light); centered max-width column
 * for readable line length. body.policy-page lifts the splash-only
 * overflow:hidden so the page scrolls naturally on any device height. */
body.policy-page {
  overflow: auto;
}

.policy {
  max-width: 720px;
  margin: 0 auto;
  padding: 64px 24px 96px;
  font-size: 16px;
  line-height: 1.65;
  color: var(--text-primary);
}

.policy h1 {
  font-size: 28px;
  font-weight: 700;
  margin-bottom: 16px;
}

.policy h2 {
  font-size: 20px;
  font-weight: 700;
  margin-top: 40px;
  margin-bottom: 12px;
}

.policy p {
  margin-bottom: 16px;
}

.policy ul {
  margin: 0 0 16px 24px;
  padding: 0;
}

.policy li {
  margin-bottom: 8px;
}

.policy hr {
  border: 0;
  border-top: 1px solid #d3d6da;
  margin: 24px 0;
}

.policy a {
  color: #4B807C;
  text-decoration: underline;
}

.policy a:hover,
.policy a:focus-visible {
  color: #355d59;
}

.policy-meta {
  color: #555;
  font-size: 14px;
}

.policy-meta p {
  margin-bottom: 4px;
}

.policy address {
  font-style: normal;
  margin-top: 8px;
}

/* Contact page — dark-themed form. body.contact-page lifts the splash-only
 * overflow:hidden so the page scrolls naturally on short viewports and when
 * the iOS soft keyboard pushes the layout. */
body.contact-page {
  overflow: auto;
}

.contact {
  max-width: 560px;
  margin: 0 auto;
  padding: 64px 24px 96px;
}

.contact-header {
  margin-bottom: 32px;
}

.contact-header h1 {
  font-size: 28px;
  font-weight: 700;
  margin-bottom: 8px;
}

.contact-subtitle {
  font-size: 16px;
  line-height: 1.5;
  color: #b8b8b8;
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.form-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-row label {
  font-size: 14px;
  font-weight: 700;
}

.form-row .required {
  color: var(--tile-correct-bg);
}

.form-row input,
.form-row textarea {
  font-family: inherit;
  font-size: 16px;
  color: var(--text-primary);
  background: #1f1f21;
  border: 1px solid var(--tile-tbd-border);
  border-radius: 6px;
  padding: 10px 12px;
  outline: none;
  transition: border-color 150ms ease-out;
}

.form-row input:focus,
.form-row textarea:focus {
  border-color: var(--tile-correct-bg);
}

.form-row textarea {
  resize: vertical;
  min-height: 120px;
}

/* Shared filled-button styling. Used by the contact form's submit <button>
 * and by the thank-you page's "Visit Homepage" anchor — anchors-as-buttons
 * are fine for navigation actions; the visual styling cues "do this." */
.contact-button {
  display: inline-block;
  align-self: flex-start;
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  color: var(--tile-state-text);
  background: var(--tile-correct-bg);
  border: none;
  border-radius: 6px;
  padding: 12px 28px;
  cursor: pointer;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: background 150ms ease-out;
}

.contact-button:hover,
.contact-button:focus-visible {
  background: #355d59;
}

/* Tile primitive — shared between boot-stage tiles and any resting logo
 * built from tiles. Sized via CSS variables so the boot grid can scale
 * independently from a small resting logo. */
.tile {
  width: var(--tile-size, 64px);
  height: var(--tile-size, 64px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Libre Franklin', sans-serif;
  font-weight: 700;
  font-size: calc(var(--tile-size, 64px) * 0.45);
  line-height: 1;
  text-transform: uppercase;
  border: 2px solid transparent;
  border-radius: 0;
  user-select: none;
}

.tile.empty {
  border-color: var(--tile-empty-border);
  background: transparent;
  color: transparent;
}

.tile.tbd {
  border-color: var(--tile-tbd-border);
  background: var(--tile-tbd-bg);
  color: var(--tile-tbd-text);
}

.tile.correct {
  background: var(--tile-correct-bg);
  color: var(--tile-state-text);
}

.tile.present {
  background: var(--tile-present-bg);
  color: var(--tile-state-text);
}

.tile.absent {
  background: var(--tile-absent-bg);
  color: var(--tile-state-text);
}

/* Boot animation — 4x5 grid of two-faced tiles. Web port of
 * components/game/BootFlippingBackground.tsx. Animation constants mirror
 * components/game/flipAnimation.ts:
 *   REVEAL_HALF_MS         500ms   (per 90° rotation)
 *   REVEAL_DURATION_MS    1000ms   (per full flip = two ease-in quarters)
 *   STAGGER_MS              75ms   (between tiles in the shuffled order)
 *   HOLD_MS                400ms   (between forward and reverse phases)
 *   Total wall-clock     ~5250ms
 *
 * Per-tile delays + the reverse phase start are written to each tile as
 * CSS custom properties by boot-animation.js. Easing is applied per-keyframe
 * so each 90° segment has its own ease-in curve — matching the RN port's
 * two-quarter withTiming chain. */

.boot-grid {
  --tile-size: clamp(48px, 12vw, 80px);
  display: grid;
  grid-template-columns: repeat(5, var(--tile-size));
  grid-template-rows: repeat(4, var(--tile-size));
  gap: 8px;
}

.boot-tile {
  position: relative;
  width: var(--tile-size);
  height: var(--tile-size);
  perspective: 700px;
}

.boot-tile-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  /* fill-mode is `forwards` (not `both`) on BOTH animations so the reverse
   * animation contributes nothing during its delay. With `both`, reverse's
   * backwards fill applies its 0% keyframe (rotateX(-180deg)) from t=0,
   * and because reverse is later in the animation-name list it wins over
   * the active forward animation — so the forward flip becomes invisible
   * and tiles appear to "only flip out." `forwards` keeps each animation
   * silent until its delay elapses. */
  animation:
    boot-flip-forward 1000ms linear var(--forward-start, 0ms) forwards,
    boot-flip-reverse 1000ms linear var(--reverse-start, 0ms) forwards;
}

.boot-face {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  font-family: 'Libre Franklin', sans-serif;
  font-weight: 700;
  font-size: calc(var(--tile-size) * 0.45);
  text-transform: uppercase;
  color: var(--tile-state-text);
}

/* Front face = empty outline. Opacity drops to 0 the instant the tile
 * reaches -90° (mid-forward-flip) so the outline doesn't reappear when the
 * tile rotates back to face-front orientation at the end of the reverse
 * phase. After both animations finish, every tile is blank. */
.boot-face.front {
  border: 2px solid var(--tile-empty-border);
  background: transparent;
  animation: boot-face-front-fade 1000ms linear var(--forward-start, 0ms) both;
}

.boot-face.back {
  transform: rotateX(180deg);
}

.boot-face.back[data-color='absent'] { background: var(--tile-absent-bg); }
.boot-face.back[data-color='present'] { background: var(--tile-present-bg); }
.boot-face.back[data-color='correct'] { background: var(--tile-correct-bg); }

@keyframes boot-flip-forward {
  0%   { transform: rotateX(0deg);    animation-timing-function: cubic-bezier(0.42, 0, 1, 1); }
  50%  { transform: rotateX(-90deg);  animation-timing-function: cubic-bezier(0.42, 0, 1, 1); }
  100% { transform: rotateX(-180deg); }
}

@keyframes boot-flip-reverse {
  0%   { transform: rotateX(-180deg); animation-timing-function: cubic-bezier(0.42, 0, 1, 1); }
  50%  { transform: rotateX(-270deg); animation-timing-function: cubic-bezier(0.42, 0, 1, 1); }
  100% { transform: rotateX(-360deg); }
}

@keyframes boot-face-front-fade {
  0%, 49.99% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* Tap-to-skip: JS adds .boot-skip on pointerdown to fast-fade the stage out.
 * Mirrors the app's tap-to-skip on app/index.tsx. */
.boot-stage.boot-skip {
  opacity: 0;
  transition: opacity 200ms ease-out;
  pointer-events: none;
}

/* Reduced-motion users skip the boot animation entirely and land on the
 * resting layout immediately. JS-side guard skips the DOM build too and
 * adds .boot-complete synchronously so the sibling selector fires on
 * first paint. */
@media (prefers-reduced-motion: reduce) {
  .boot-stage {
    display: none;
  }
  .resting {
    transition: none;
  }
}
