/* ==========================================================================
   Little Beats Dayclub
   Mobile-first. Base styles target the phone; min-width queries add up from
   there. Nothing below 1024px depends on a desktop rule being overridden.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts
   Self-hosted woff2 — no Google Fonts request, no layout shift (PLAN.md §3).
   Drop the files into /assets/fonts/ and uncomment. The stack below degrades
   to the platform geometric sans until then, so the site ships either way.
   -------------------------------------------------------------------------- */
/*
@font-face {
  font-family: 'Space Grotesk';
  src: url('../assets/fonts/SpaceGrotesk-Variable.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-display: swap;
}
*/

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Surface */
  --bg: #0a0a0c;
  --surface: #121215;
  --surface-2: #16161b;
  --fg: #f4f4f0;
  --fg-muted: #8a8a93;

  /* Neon. Contrast on --bg: cyan 13.1:1, magenta 5.75:1 — both pass AA.
     Lime is mesh-only and never carries text. */
  --accent-1: #22e7ff; /* primary — CTA, glow, focus */
  --accent-2: #ff2e9a; /* partner — gradients, hover */
  --accent-3: #c8ff2e; /* mesh only */

  /* Chrome */
  --chrome-hi: #f2f2f6;
  --chrome-mid: #9aa0ac;
  --chrome-lo: #6c7280;
  --chrome: linear-gradient(
    140deg,
    var(--chrome-hi),
    var(--chrome-mid) 45%,
    var(--chrome-hi)
  );

  /* Hairline that binds the two panels into one instrument face */
  --edge: linear-gradient(
    148deg,
    rgba(34, 231, 255, 0.85) 0%,
    rgba(242, 242, 246, 0.55) 26%,
    rgba(154, 160, 172, 0.2) 52%,
    rgba(255, 46, 154, 0.7) 100%
  );

  /* Type */
  --font-display:
    "Space Grotesk", "Bahnschrift", "DIN Alternate",
    "Segoe UI Variable Display", system-ui, sans-serif;
  --font-body:
    "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
    sans-serif;

  /* Rhythm */
  --gutter: 1.25rem;
  --radius: 16px;
  --radius-sm: 10px;

  /* Video. ONE number controls the whole layout — see PLAN.md Q4.
     9:16 portrait = 0.5625 | 1:1 square = 1 | 16:9 landscape = 1.7778
     On desktop the video column sizes itself from this, and the form
     column absorbs whatever is left. Portrait video → wider form. */
  --video-ar: 0.5625;
  --video-cap: 55dvh;
}

/* --------------------------------------------------------------------------
   3. Reset
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

a {
  color: inherit;
}

button {
  font: inherit;
  color: inherit;
}

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

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   4. Background — photo + 80% black scrim, with the gradient mesh above it
   -------------------------------------------------------------------------- */

/* Layer 1: the photograph. Fixed so it does not scroll away on the legal
   pages, and centred so the laser fan stays in frame at any aspect ratio. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: url("../assets/bg.jpeg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* Layer 2: the scrim. 60% black over the photo — enough to keep off-white
   text and the neon accents legible, light enough that the lasers read. */
.backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
}

/* Layer 3: the drifting mesh, now on top of the scrim rather than on bare
   background. Dialled down so it reads as a glow over the photo instead of
   competing with the lasers already in it. Set --mesh-opacity: 0 to switch
   the mesh off entirely and leave the photo alone. */
.mesh {
  position: fixed;
  inset: -20%;
  z-index: 0;
  pointer-events: none;
  contain: strict;
  opacity: var(--mesh-opacity, 0.55);
}

.mesh__blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.5;
  will-change: transform;
}

.mesh__blob--1 {
  width: 62vmax;
  height: 62vmax;
  top: -12%;
  left: -18%;
  background: radial-gradient(
    circle at 50% 50%,
    var(--accent-1),
    transparent 68%
  );
  animation: drift-1 34s ease-in-out infinite alternate;
}

.mesh__blob--2 {
  width: 58vmax;
  height: 58vmax;
  bottom: -16%;
  right: -20%;
  background: radial-gradient(
    circle at 50% 50%,
    var(--accent-2),
    transparent 68%
  );
  animation: drift-2 41s ease-in-out infinite alternate;
}

.mesh__blob--3 {
  display: none;
  width: 40vmax;
  height: 40vmax;
  top: 42%;
  left: 46%;
  background: radial-gradient(
    circle at 50% 50%,
    var(--accent-3),
    transparent 66%
  );
  opacity: 0.16;
  animation: drift-3 52s ease-in-out infinite alternate;
}

/* Vignette so the neon never fights the panels for attention */
.mesh::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse at 50% 45%,
    transparent 8%,
    var(--bg) 76%
  );
}

@keyframes drift-1 {
  from {
    transform: translate3d(0, 0, 0) scale(1);
  }
  to {
    transform: translate3d(14vw, 12vh, 0) scale(1.18);
  }
}
@keyframes drift-2 {
  from {
    transform: translate3d(0, 0, 0) scale(1.1);
  }
  to {
    transform: translate3d(-16vw, -10vh, 0) scale(0.92);
  }
}
@keyframes drift-3 {
  from {
    transform: translate3d(-6vw, 4vh, 0);
  }
  to {
    transform: translate3d(8vw, -8vh, 0);
  }
}

/* --------------------------------------------------------------------------
   5. Shell
   -------------------------------------------------------------------------- */
.site {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  padding: 0 var(--gutter);
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}

/* --- Header --------------------------------------------------------------- */
.masthead {
  display: flex;
  justify-content: center; /* centered at every width — see §9 note */
  align-items: center;
  padding: 1.5rem 0 1.25rem;
  padding-top: max(1.5rem, env(safe-area-inset-top));
}

/* The real mark is a stacked lockup (848x623), not the wide wordmark the
   placeholder was — so it needs noticeably more height to stay legible.
   "DAYCLUB" is only ~11% of the artwork's height, which is what sets the
   floor here: below ~60px that line stops reading. */
.masthead__logo {
  width: auto;
  height: 64px;
  max-width: 74vw;
  object-fit: contain;
}

/* --- Stage ---------------------------------------------------------------- */
.stage {
  display: grid;
  gap: 1.25rem;
  align-content: center;
  flex: 1;
  padding-bottom: 1.5rem;
}

/* Stacked layouts put the FORM first. It is the page's only job, and below a
   video capped at 54dvh it would otherwise start below the fold. The video
   still sits directly under it, so the pitch is one thumb-flick away.
   Both two-column layouts reset this — see the 1024px and landscape queries. */
.panel--form {
  order: 1;
}
.panel--video {
  order: 2;
}

/* --------------------------------------------------------------------------
   6. Panels — the chrome hairline that makes video + form read as one face
   -------------------------------------------------------------------------- */
.panel {
  position: relative;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.9);
}

.panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  padding: 1px;
  background: var(--edge);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* --- Video ---------------------------------------------------------------- */
.panel--video {
  overflow: hidden;
  background: #000;
  justify-self: center;
  width: min(100%, calc(var(--video-cap) * var(--video-ar)));
}

.video {
  aspect-ratio: var(--video-ar);
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}

/* Sound toggle — the page's only voice, so it gets the one glow */
.sound {
  position: absolute;
  z-index: 3;
  right: 0.625rem;
  bottom: 0.625rem;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid rgba(244, 244, 240, 0.22);
  border-radius: 999px;
  background: rgba(10, 10, 12, 0.62);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  cursor: pointer;
  transition:
    border-color 0.18s ease,
    box-shadow 0.18s ease,
    background 0.18s ease;
}

.sound svg {
  width: 20px;
  height: 20px;
}

.sound .icon-on {
  display: none;
}
.sound .icon-off {
  display: block;
}

.sound[aria-pressed="true"] {
  border-color: var(--accent-1);
  background: rgba(34, 231, 255, 0.12);
  box-shadow:
    0 0 0 1px rgba(34, 231, 255, 0.28),
    0 0 22px -4px var(--accent-1);
  color: var(--accent-1);
}

.sound[aria-pressed="true"] .icon-on {
  display: block;
}
.sound[aria-pressed="true"] .icon-off {
  display: none;
}

@media (hover: hover) {
  .sound:hover {
    border-color: rgba(244, 244, 240, 0.5);
  }
  .sound[aria-pressed="true"]:hover {
    border-color: var(--accent-1);
  }
}

/* Autoplay refused (low-power mode, some in-app browsers) — offer the tap */
.video-start {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: none;
  place-items: center;
  border: 0;
  border-radius: inherit;
  background: rgba(10, 10, 12, 0.42);
  cursor: pointer;
}

.video-start[data-visible="true"] {
  display: grid;
}

.video-start__ring {
  display: grid;
  place-items: center;
  width: 68px;
  height: 68px;
  border: 1px solid var(--accent-1);
  border-radius: 999px;
  background: rgba(10, 10, 12, 0.72);
  box-shadow: 0 0 30px -6px var(--accent-1);
  color: var(--accent-1);
}

.video-start__ring svg {
  width: 24px;
  height: 24px;
  margin-left: 3px;
}

/* Portrait phones: the video is full-screen. It breaks out of the site
   gutters and fills the viewport, so the ad plays edge to edge instead of in
   a card. Scoped to portrait under 1024px — the landscape and desktop queries
   below put it back in a column, where a full-bleed video would bury the form.

   margin-inline: calc(50% - 50vw) resolves against the grid area, which is
   the gutter-inset content width — so it cancels whatever padding .site is
   currently applying (gutter or safe-area) without hard-coding either. */
@media (max-width: 1023px) and (orientation: portrait) {
  .panel--video {
    width: 100vw;
    max-width: none;
    margin-inline: calc(50% - 50vw);
    justify-self: stretch;
    height: 100dvh;
    border-radius: 0;
    box-shadow: none;
  }

  /* The chrome hairline frames a panel; on a full-bleed edge it is a seam. */
  .panel--video::before {
    display: none;
  }

  /* Fill the viewport rather than the 9:16 box — the sides crop on phones
     narrower than 9:16, which is the trade full-screen asks for. */
  .video {
    aspect-ratio: auto;
  }

  /* Nothing frames these any more, so they take their own safe-area offset */
  .sound {
    right: max(0.875rem, env(safe-area-inset-right));
    bottom: max(0.875rem, env(safe-area-inset-bottom));
  }
}

/* --- Form ----------------------------------------------------------------- */
.panel--form {
  padding: 6px;
  background: var(--surface-2);
}

.formFrame {
  position: relative;
  height: min(70dvh, 540px);
  min-height: 420px;
  border-radius: calc(var(--radius) - 6px);
  overflow: hidden;
  background: var(--surface);
}

.formFrame > div {
  width: 100%;
  height: 100%;
}

/* The embed sizes its own iframe, but a default border would sit inside the
   chrome hairline and read as a second frame. */
.formFrame iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* Fallback — shown when the embed script fails or no form ID is set.
   No dead ends (PLAN.md §4). */
.form-fallback {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  height: 100%;
  padding: 2rem 1.5rem;
  text-align: center;
}

.form-fallback[data-visible="true"] {
  display: flex;
}

.form-fallback__note {
  margin: 0;
  max-width: 30ch;
  color: var(--fg-muted);
  font-size: 0.9375rem;
}

.cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 1.75rem;
  border: 1px solid var(--accent-1);
  border-radius: 999px;
  background: rgba(34, 231, 255, 0.1);
  color: var(--accent-1);
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  text-transform: uppercase;
  box-shadow: 0 0 28px -8px var(--accent-1);
  transition:
    background 0.18s ease,
    box-shadow 0.18s ease,
    transform 0.18s ease;
}

@media (hover: hover) {
  .cta:hover {
    background: rgba(34, 231, 255, 0.18);
    box-shadow: 0 0 34px -4px var(--accent-1);
  }
}

.cta:active {
  transform: translateY(1px);
}

/* Loading shimmer while the Typeform SDK boots */
.formFrame__loading {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--fg-muted);
  font-size: 0.875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.formFrame__loading[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   7. Footer
   Text ships verbatim, pipes included (PLAN.md §1).
   -------------------------------------------------------------------------- */
.colophon {
  padding: 1.25rem 0;
  padding-bottom: max(1.25rem, env(safe-area-inset-bottom));
  color: var(--fg-muted);
  font-size: 0.8125rem;
  line-height: 1.9;
  text-align: center;
  text-wrap: balance;
}

.colophon a {
  color: var(--fg-muted);
  text-decoration: none;
  border-bottom: 1px solid rgba(138, 138, 147, 0.35);
  padding-bottom: 1px;
  transition:
    color 0.16s ease,
    border-color 0.16s ease;
}

@media (hover: hover) {
  .colophon a:hover {
    color: var(--accent-1);
    border-bottom-color: var(--accent-1);
  }
}

/* The spaces around each pipe are real characters in the markup, not
   padding — the footer line has to survive a copy-paste verbatim. */
.colophon .sep {
  opacity: 0.45;
}

/* Instagram is a glyph, not a word. The 44px box is the tap target; the
   negative block margin keeps it from stretching the footer's line height,
   since the line box here is only ~25px tall. The underline the other
   footer links carry would read as a stray rule under an icon. */
.colophon__ig {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-block: -0.75rem;
  vertical-align: middle;
  border-bottom: 0;
  padding-bottom: 0;
}

.colophon__ig svg {
  width: 18px;
  height: 18px;
}

/* --------------------------------------------------------------------------
   8. Legal pages
   -------------------------------------------------------------------------- */
.doc {
  width: 100%;
  max-width: 68ch;
  margin: 0 auto;
  padding: 0.5rem 0 3rem;
  flex: 1;
}

.doc__back {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  color: var(--fg-muted);
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  transition: color 0.16s ease;
}

@media (hover: hover) {
  .doc__back:hover {
    color: var(--accent-1);
  }
}

.doc__title {
  margin: 1.5rem 0 0.375rem;
  font-family: var(--font-display);
  font-size: clamp(1.875rem, 8vw, 2.75rem);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.02em;
}

.doc__effective {
  margin: 0 0 2.5rem;
  color: var(--fg-muted);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.doc__rule {
  height: 1px;
  margin: 0 0 2.5rem;
  border: 0;
  background: var(--edge);
  opacity: 0.7;
}

.doc section + section {
  margin-top: 2.5rem;
}

.doc h2 {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 0 0 0.75rem;
  font-family: var(--font-display);
  font-size: 1.1875rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* The 1–6 numbering is real sequence, not decoration — the plan requires it */
.doc h2 .num {
  flex: none;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.1em;
  background: var(--chrome);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.doc p {
  margin: 0 0 1rem;
  color: rgba(244, 244, 240, 0.82);
}

.doc p:last-child {
  margin-bottom: 0;
}

.doc a:not(.doc__back) {
  color: var(--accent-1);
}

.doc ul {
  margin: 0 0 1rem;
  padding-left: 1.25rem;
  color: rgba(244, 244, 240, 0.82);
}

.doc li {
  margin-bottom: 0.5rem;
}

/* Bold lead-ins on the Terms list items — full-strength against the 82% body */
.doc strong {
  color: var(--fg);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   9. Larger screens
   -------------------------------------------------------------------------- */
@media (min-width: 640px) {
  :root {
    --gutter: 2rem;
    --video-cap: 54dvh;
  }
  .masthead__logo {
    height: 76px;
  }
  .stage {
    gap: 1.5rem;
  }
}

@media (min-width: 1024px) {
  :root {
    --gutter: 2.5rem;
    --video-cap: 68dvh;
    --radius: 20px;
  }

  .mesh__blob {
    filter: blur(90px);
  }
  .mesh__blob--3 {
    display: block;
  }

  /* Capped so the form column stays a form and not a banner. Header, stage
     and footer share the measure, so the whole page reads on one axis. */
  .site {
    max-width: 1200px;
    margin-inline: auto;
  }

  /* Logo and footer stay centred on desktop. PLAN.md §1 asked for both to go
     left-aligned above 1024px; centred was chosen instead, so the mark, the
     stage and the colophon all sit on the same vertical axis. */
  .masthead {
    padding: 1.75rem 0;
    min-height: 80px;
  }

  .masthead__logo {
    height: 88px;
    max-width: 30vw;
  }

  /* Form left, video right. The video column takes exactly the width its
     aspect ratio needs at the height cap; the form absorbs the remainder.
     Portrait → wider form, with no per-ratio special-casing. */
  .stage {
    grid-template-columns: minmax(min(100%, 26rem), 1fr) auto;
    gap: 2rem;
    align-items: center;
    padding-bottom: 2rem;
  }

  /* Reversed against source order: form first, video second */
  .panel--form {
    order: 0;
  }
  .panel--video {
    order: 1;
    width: min(100%, calc(var(--video-cap) * var(--video-ar)), 46rem);
    justify-self: start;
    height: 100%;
    max-height: var(--video-cap);
  }

  .sound {
    right: 0.875rem;
    bottom: 0.875rem;
  }

  .formFrame {
    height: var(--video-cap);
    max-height: 720px;
    min-height: 480px;
  }

  .colophon {
    padding: 1.5rem 0;
  }

  .doc {
    padding: 1rem 0 5rem;
  }
  .doc__title {
    font-size: 3rem;
  }
  .doc h2 {
    font-size: 1.3125rem;
  }
}

/* Short and wide — landscape phones, small tablets held sideways.
   Stacking here pushes the form completely off-screen, so the two-column
   split arrives early and the video gives up the height instead. */
@media (max-width: 1023px) and (orientation: landscape) and (min-width: 700px) {
  :root {
    --gutter: 1.5rem;
    --video-cap: 62dvh;
  }

  .masthead {
    padding: 0.75rem 0;
    padding-top: max(0.75rem, env(safe-area-inset-top));
  }
  .masthead__logo {
    height: 48px;
  }

  .stage {
    grid-template-columns: minmax(min(100%, 17rem), 1fr) auto;
    gap: 1.25rem;
    align-items: center;
    padding-bottom: 0.75rem;
  }

  /* Two columns here too, so match desktop: form left, video right */
  .panel--form {
    order: 0;
  }
  .panel--video {
    order: 1;
    justify-self: start;
    height: 100%;
    max-height: var(--video-cap);
  }

  .formFrame {
    height: var(--video-cap);
    min-height: 0;
  }

  .colophon {
    padding: 0.75rem 0;
    padding-bottom: max(0.75rem, env(safe-area-inset-bottom));
  }
}

/* Small phones turned sideways — too narrow to split, so shrink the video
   until the top of the form is on screen. */
@media (max-width: 699px) and (orientation: landscape) {
  :root {
    --video-cap: 44dvh;
  }
  .masthead {
    padding: 0.75rem 0;
  }
  .masthead__logo {
    height: 48px;
  }
  .formFrame {
    min-height: 300px;
  }
}

/* --------------------------------------------------------------------------
   10. Reduced motion — static mesh, no drift (PLAN.md §3)
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .mesh__blob {
    animation: none;
  }
  .mesh__blob--1 {
    transform: translate3d(6vw, 5vh, 0);
  }
  .mesh__blob--2 {
    transform: translate3d(-7vw, -4vh, 0);
  }
}
