/* ============================================================================
   samantha.design — AIR — styles

   Same DOM budget as the antechamber: the canvas is the page. A wordmark, one
   invitation line, a dev readout. Everything rides the --sun-* custom
   properties js/sun.js writes from the local clock, so the paper the ink sits
   in and the page around it are lit by the same sun.

   NOTE ON MOTION: the only CSS transitions here are the day/night collapse
   pair and the invitation's wipe pair — both are responses to a real event
   (the clock moving, the mic being granted). There is no ambient/looping
   animation anywhere in this file, on purpose: the page's claim is that
   nothing moves without sound, and a keyframe loop in the CSS would break
   that claim just as surely as a clock in the shader would.
   ============================================================================ */

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

/* 100dvh, not 100vh. On iPhone `vh` is locked to the LARGE viewport — the one
   with Safari's toolbar collapsed — so at rest the page is taller than the
   visible area and the bottom of the canvas sits behind the toolbar. `dvh`
   tracks the viewport as the toolbar collapses and expands, so the piece is
   always exactly the size of what you can see. `vh` first as the fallback for
   anything that doesn't know `dvh`. */
html,body{ height:100vh; height:100dvh; }
body{ overscroll-behavior:none; }

body{
  font-family:var(--f-primary);
  background:var(--sun-bg);
  color:var(--sun-ink);
  overflow:hidden;
  transition:background-color var(--collapse-dur) var(--collapse-ease),
             color var(--collapse-dur) var(--collapse-ease);
  -webkit-font-smoothing:antialiased;
}

#air{
  position:fixed; inset:0;
  width:100%; height:100%;
  display:block;
  cursor:default;              /* nothing here is clickable — the room is the input */
  /* the canvas is not a scroll surface; without this a drag on iOS rubber-bands
     the whole page instead of doing nothing */
  touch-action:none;
}

/* ---- centre title — sharp over soft plate ---- */

/* ---- wordmark — same placement grammar as V3 and the antechamber ---- */
.nav{
  position:fixed;
  /* 12/20, not the old 16/16: MEASURED to land the wordmark on exactly the
     same pixel as the work page's (V3 rest: x:20, y:12) — the name must not
     jump when the dive hands one page to the other (2026-08-10). */
  /* VERTICALLY CENTRED (2026-09-02, per direct request) — kept at the left edge,
     lifted from the top corner to the screen's midline so the name, the prompt and
     Enter read as one horizontal band across the middle. */
  top:50%; transform:translateY(-50%);
  left:calc(20px + env(safe-area-inset-left));
  z-index:3; pointer-events:none;
}
.nav__word{
  /* EXACT match to the work page's wordmark (2026-08-10, "I like how it is
     being set at Work"): same family (Junicode, the artist voice), same 500
     weight — it was inheriting the body sans here, so the same name rendered
     in two different faces across the dive. */
  font-family:var(--f-secondary); font-weight:500;
  font-size:var(--t-nav-word);
  line-height:var(--lh-nav-word);
  letter-spacing:var(--ls-nav-word);
  color:var(--sun-ink);
  transition:color var(--collapse-dur) var(--collapse-ease);
}

/* ---- the one line — Junicode, artist voice, bottom centre ---- */
.cues{
  /* Full-width and centred by text-align, NOT left:50% + translateX(-50%).
     The transform version sizes to its content, so "listening to the quiet of
     your room" runs off both edges of a phone before it can wrap. */
  /* CENTRED on screen now (2026-09-02, per direct request), not pinned to the
     bottom. top:50% + a translateY is safe where a translateX was not — the
     warning at the width note is about horizontal sizing; left:0/right:0 still
     gives full width to wrap in, and only the vertical axis is transformed. */
  position:fixed; left:0; right:0; top:50%;
  transform:translateY(-50%);
  z-index:3;
  pointer-events:none;
  padding:0 var(--sp-24);
  text-align:center;
}
.line{
  font-family:var(--f-secondary);
  font-size:var(--t-hint);
  line-height:var(--lh-hint);
  color:var(--sun-ink-muted);
  text-align:center;
  opacity:0;
  transition:opacity var(--wipe-dur) var(--wipe-ease),
             color var(--collapse-dur) var(--collapse-ease);
  user-select:none;
}
.line.is-visible{ opacity:1; }

/* The invitation is a real <button> so it is keyboard reachable — the only
   interactive element on the page. It removes itself once the mic is on;
   there is nothing else to ask for. */
.invite{
  font:inherit; color:inherit;
  background:none; border:none;
  border-bottom:1px solid currentColor;
  cursor:pointer;
  pointer-events:auto;
  padding:0 1px 1px;
  margin-left:.35em;
}
.invite:focus-visible{ outline:1px solid var(--sun-ink-muted); outline-offset:3px; }
/* the button's visibility is driven from JS now (it comes BACK for the deaf
   state), so the old blanket hide would fight it */

/* ---- dev-only state readout (press D) — read-only, never ships meaning.
   It exists to make the page's one claim checkable by eye: whether the field
   is moving, and if so, what is moving it. ---- */
.state{
  position:fixed; right:var(--sp-16); bottom:var(--sp-16); z-index:4;
  font:11px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;
  letter-spacing:.02em;
  /* PLAIN BLACK (2026-09-02, per direct request). It was --sun-ink-muted, the
     same grey the hint copy uses — but this is an instrument readout, not page
     furniture, and the band bars are drawn in it too. Both are one colour. */
  color:var(--sun-ink);
  display:none; white-space:pre;
  pointer-events:none; user-select:none;
}
.state.is-on{ display:block; }

/* ---- WebGL2 / float-render-target fallback. This page cannot degrade to a
   cheaper visual the way the antechamber could — a fluid sim without float
   render targets is not a fluid sim — so it says so plainly rather than
   showing an empty room. ---- */
.nogl{
  position:fixed; inset:0; z-index:10;
  display:none; align-items:center; justify-content:center;
  padding:var(--sp-32);
  background:var(--sun-bg); color:var(--sun-ink-muted);
  font-family:var(--f-secondary); font-size:var(--t-hint); line-height:var(--lh-hint);
  text-align:center;
}
.nogl.is-on{ display:flex; }

@media (prefers-reduced-motion: reduce){
  body, .nav__word, .line{ transition-duration:1ms; }
}

/* ---- tap to resume — only ever visible after the GL context has been lost.
   Full-bleed and deliberately plain: at that moment the canvas is dead, so this
   is the entire page. ---- */
.resume{
  position:fixed; inset:0; z-index:8;
  display:none; align-items:center; justify-content:center;
  background:var(--sun-bg); color:var(--sun-ink-muted);
  font-family:var(--f-secondary); font-size:var(--t-hint); line-height:var(--lh-hint);
  cursor:pointer; user-select:none;
  padding:calc(var(--sp-32) + env(safe-area-inset-top)) var(--sp-24);
}
.resume.is-on{ display:flex; }

/* ---- preview controls (this build only) -------------------------------------
   Opposite the wordmark, same type voice as the nav, --sun-ink colours so
   they survive their own toggles. Whole-pixel offsets. */
.enter{
  /* THE MIRROR of the wordmark. Same face, weight and size as .nav__word, on the
     opposite top corner, on the SAME baseline (top:12/right:20 = nav's 12/20), so
     the name and the way out frame the field between them. */
  position:fixed; z-index:5;
  top:50%; transform:translateY(-50%);   /* the mirror stays a mirror — same midline as the name */
  right:calc(20px + env(safe-area-inset-right));
  appearance:none; background:none; border:0; padding:0;
  font-family:var(--f-secondary); font-weight:500;
  font-size:var(--t-nav-word); line-height:var(--lh-nav-word);
  letter-spacing:var(--ls-nav-word);
  color:var(--sun-ink);
  cursor:pointer; user-select:none;
  transition:opacity var(--collapse-dur) var(--collapse-ease);
}
.enter:hover{ opacity:0.6; }
.enter:focus-visible{ outline:1px solid var(--sun-ink-muted); outline-offset:4px; }

