/* landing.css - the landing. Owner: P11.
   Loads after base.css, so it wins on equal specificity by cascade order.

   THE COMPOSITION (2026-09-05, Dan's brief): the Arecibo message in the middle
   of the page, and at the foot one word and one switch. Nothing else. The word
   is the route into the side the page is showing (a real <a>); the switch turns
   the page over to the other side, and the word, its link and the message's
   colour turn with it. Each .land__face carries its own copy of the foot in
   its own state, so the flip's clip-path wave reveals the new word and the new
   knob position per pixel exactly as it reveals the new ground.

   The message's own box and placement knobs live in arecibo.css; this file
   reserves the foot's band (--foot-h) so the artwork and the control never
   share a pixel, and draws the foot.

   Colour: nothing here spells a palette value. Each layer's --ground / --ink /
   --cell / --lat-dot / --dim are written onto it by flip.js, read out of
   tokens.css for the two polarities, so the white half of this page cannot
   drift from the white twin. --gray, --hairline and --red are the same on both
   sides and come straight from :root. */

/* ---- the frame ---- */

body.landing {
  /* one screen, no scroll */
  overflow: hidden;
}

.land {
  position: relative;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
  /* THE FOOT'S BAND. The message's canvas stops where this begins (arecibo.css
     sizes it to calc(100% - var(--foot-h))), so the artwork and the control
     each own their space by construction and no breakpoint has to solve a
     collision. word + gap + switch is 104px at the top of the word's clamp;
     the rest is air, split above and below the cluster by the foot's own
     centring. */
  --foot-h: 152px;
}

/* One polarity of the whole composition. Both are always laid out and always
   painted; only the stack order and the clip decide what is seen. */
.land__face {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-color: var(--ground);
  background-image: radial-gradient(var(--lat-dot) 1.1px, transparent 1.2px);
  background-size: var(--pitch) var(--pitch);
  color: var(--ink);
}

/* the active side sits on top; the incoming one is raised above both while it
   is being swept in (flip.js sets that z inline) */
.land__face[data-active="true"] { z-index: 2; }

/* ---- the foot: one word, one switch ---- */

.land__foot {
  --land-word: clamp(26px, 3.05vw, 44px);
  --land-gap: 16px;

  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: var(--foot-h);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--land-gap);
}

/* ---- the word: the route into the side being shown ---- */

.land__word {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.2em;
  font-family: var(--font-voice);
  font-weight: 500;
  font-size: var(--land-word);
  line-height: 1;
  letter-spacing: -0.025em;
  color: var(--ink);
  white-space: nowrap;
  transition: opacity var(--dur-micro) var(--ease);
}
.land__word:hover { opacity: 0.68; }

/* The word takes a small arrow - the page's one red mark, the accent's own job
   (spec 3: red means live / current / active): this is the live route. The
   glyph is CSS and its slot has a fixed width, so the word's box is the same
   on both faces and the two words centre on the same axis. */
.land__arrow {
  display: inline-block;
  width: 0.66em;
  flex: none;
  font-family: var(--font-readout);
  font-size: 0.40em;
  line-height: 1;
  color: var(--red);
}
.land__arrow::before { content: "\2192"; }

/* ---- the switch ----
   One control, two ends, and the reference's own two marks: a SQUARE at the
   left end for Developer, a CIRCLE at the right end for Storyteller - the shape
   is the identity - drawn in --gray as the ends of the track. The knob is solid
   --ink and sits over whichever mark is the side the page is showing, taking
   that mark's shape; the mark left uncovered is the side the switch goes to.
   So the black face shows a solid circle on the right with a ghost square on
   the left, and the white face the reverse, with no label needed to say which
   way the switch turns. */

.land__switch {
  display: inline-flex;
  /* a 44px hit target around a 24px track, without the track growing */
  padding: 10px 12px;
  transition: opacity var(--dur-micro) var(--ease);
}
.land__switch:hover { opacity: 0.68; }
.land__switch:focus-visible { outline-offset: 1px; }

.land__track {
  position: relative;
  display: block;
  width: 48px;
  height: 24px;
  border: 1px solid var(--gray);
}

/* the two ends, drawn as marks: 16px each, 3px in from the track's inner edge,
   so the inner 46px holds 3 + 16 + 8 + 16 + 3 */
.land__track::before,
.land__track::after {
  content: "";
  position: absolute;
  top: 3px;
  width: 16px;
  height: 16px;
  border: 1px solid var(--gray);
}
.land__track::before { left: 3px; }
.land__track::after { left: 27px; border-radius: 50%; }

.land__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  z-index: 1;
  width: 16px;
  height: 16px;
  background: var(--ink);
  border-radius: 0;
  transition: transform var(--dur-knob) var(--ease), border-radius var(--dur-knob) var(--ease);
}
/* Storyteller: the knob crosses to the circle's place and becomes the circle.
   The travel is the marks' own spacing (27 - 3), stated once here. */
.land__switch[data-state="storyteller"] .land__knob {
  transform: translateX(24px);
  border-radius: 50%;
}

/* ---- phone ---- */
@media (max-width: 640px) {
  .land { --foot-h: 140px; }
  .land__foot { --land-word: clamp(29px, 7.4vw, 34px); }
}

/* Reduced motion: the wave is JavaScript and flip.js swaps the two layers on a
   150ms opacity instead (spec 5); the knob simply takes its place. */
@media (prefers-reduced-motion: reduce) {
  .land__knob { transition: none; }
}
