/* ==========================================================================
   MAXX — style.css

   Sections, in order:
     0 · THE KNOBS      colour, space, type, shape — change things here first
     1 · THE PAGE       the one-screen frame
     2 · THE THREAD     bubbles, stamps, the data line
     3 · THE HERO       the glass card that fades in at the end
     4 · SMALL SCREENS
   ========================================================================== */


/* ==========================================================================
   0 · THE KNOBS
   ========================================================================== */
:root {
  /* --- colour ------------------------------------------------------------
     --you-bubble is iMessage blue on purpose: the page is a text thread, and
     borrowing the cue people already read as "outgoing message" is worth more
     than being different for its own sake.

     Parked alternatives:
        #1f6f5c  deep green      health without emergency
        #2f3a8c  ink / indigo    quieter, more clinical
        #3f4854  graphite        no colour at all */
  --ground:      #f7f7f2;
  --ink:         #111214;
  --ink-soft:    #8a8f97;
  --maxx-bubble: #e9e9eb;
  --maxx-text:   #111214;
  --you-bubble:  #2b6cf6;
  --you-text:    #ffffff;

  /* --- how far the thread recedes when the hero arrives ------------------- */
  --thread-faded: 0.4;      /* opacity it drops to */
  --thread-blur:  2px;      /* and how soft it goes */

  /* --- the glass ---------------------------------------------------------- */
  --glass:        rgba(255, 255, 255, 0.62);
  --glass-edge:   rgba(255, 255, 255, 0.85);
  --glass-blur:   22px;
  --glass-shadow: 0 24px 70px rgba(17, 18, 20, 0.10);

  /* --- space -------------------------------------------------------------
     Two gaps in the thread and nothing else: --gap-same between consecutive
     messages from one speaker, --gap-turn when the speaker changes. */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;

  --gap-same:  var(--s1);
  --gap-turn:  var(--s3);

  /* --- type --------------------------------------------------------------- */
  --font:      -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif;
  --font-data: ui-monospace, "SF Mono", Menlo, monospace;

  /* clamp(min, preferred, max) — scales smoothly with the viewport instead of
     jumping at breakpoints, which is what makes zooming and odd phone sizes
     behave rather than needing a media query per device. */
  --size-bubble: clamp(15px, 4.1vw, 17px);   /* iMessage is 17px */
  --size-name:   clamp(38px, 13vw, 56px);    /* the big MAXX */
  --size-line:   clamp(17px, 5vw, 20px);
  --size-sub:    clamp(14px, 3.8vw, 15px);
  --size-small:  12px;
  --size-stamp:  12px;
  --leading:     1.32;

  /* --- shape --------------------------------------------------------------- */
  --bubble-radius: 20px;
  --card-radius:   28px;
  --pill:          999px;
  --column:        420px;   /* phone width, so the laptop shows the phone layout */
  --bubble-max:    82%;
}

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


/* ==========================================================================
   1 · THE PAGE
   The window height exactly, and it never scrolls. The hero sits ON TOP of
   the thread rather than after it, so nothing has to be scrolled to.
   ========================================================================== */
body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--size-bubble);
  line-height: var(--leading);
  -webkit-font-smoothing: antialiased;
}

/* Two screens tall. This is the scroll distance the handover is spread over —
   make it 300dvh for a slower, longer transition. */
.scroller {
  height: 200vh;
  height: 200dvh;
}

/* Sticks for the whole scroller, so the page never actually moves. Scrolling
   drives the animation instead.

   100dvh, not 100vh: on mobile Safari 100vh is the height WITHOUT the address
   bar, so a 100vh layout is taller than the screen. vh first as a fallback. */
.stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  width: var(--column);
  max-width: 100%;
  margin: 0 auto;
  padding: var(--s5) var(--s4);
  overflow: hidden;
}


/* ==========================================================================
   2 · THE THREAD
   ========================================================================== */
.thread {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--gap-same);
  overflow: hidden;
  padding-bottom: var(--s7);   /* room for the scroll hint */
}

/* Every message is a full-width row and the bubble is measured against the
   row, never against its own contents — that is what puts all the outgoing
   bubbles on one right edge. */
.row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  width: 100%;
}

.row.from-maxx { justify-content: flex-start; }
.row.from-you  { justify-content: flex-end; }

.bubble {
  max-width: var(--bubble-max);
  padding: 9px var(--s4);
  border-radius: var(--bubble-radius);
  text-align: left;
}

.from-maxx .bubble { background: var(--maxx-bubble); color: var(--maxx-text); }
.from-you  .bubble { background: var(--you-bubble);  color: var(--you-text); }

/* One step more air when the speaker changes, derived from the two gap values
   rather than typed onto individual bubbles. */
.row.from-maxx + .row.from-you,
.row.from-you + .row.from-maxx {
  margin-top: calc(var(--gap-turn) - var(--gap-same));
}

/* What Messages puts between two days. It earns its place: without it a
   month-long lookup arriving after the first entry reads as a non-sequitur. */
.stamp {
  align-self: center;
  font-size: var(--size-stamp);
  color: var(--ink-soft);
  margin: var(--s4) 0 var(--s2);
}
.stamp b { color: #55595f; font-weight: 600; }

/* Only the block characters are monospaced — they need fixed width to line
   up. The sentence around them stays in the same voice as every message. */
.has-data .spark {
  display: block;
  font-family: var(--font-data);
  font-size: 15px;
  letter-spacing: 1px;
  margin-bottom: 6px;
}


/* ==========================================================================
   3 · THE HERO
   Sits over the thread, centred. Hidden until script.js brings it in.
   ========================================================================== */
.hero {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--s4);
  /* The layer ignores clicks so the thread behind stays selectable; only the
     card itself takes them back. */
  pointer-events: none;
}

.hero-card {
  pointer-events: auto;
  width: 100%;
  text-align: center;
  padding: var(--s6) var(--s5) var(--s5);
  border-radius: var(--card-radius);
  background: var(--glass);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow);
  /* The frost. It has the thread behind it to blur, which is the only reason
     glass reads as glass — over a flat colour it looks like a grey box. */
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(150%);
  backdrop-filter: blur(var(--glass-blur)) saturate(150%);
}

.hero-badge {
  display: inline-block;
  font-size: var(--size-small);
  color: #55595f;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(17, 18, 20, 0.07);
  border-radius: var(--pill);
  padding: 5px var(--s3);
  margin-bottom: var(--s4);
}

.hero-name {
  font-size: var(--size-name);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1;
  margin-bottom: var(--s3);
}

.hero-line {
  font-size: var(--size-line);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: var(--s2);
}

.hero-sub {
  font-size: var(--size-sub);
  line-height: 1.45;
  color: #5c6067;
  margin-bottom: var(--s5);
}

.hero-cta {
  display: block;
  background: var(--you-bubble);
  color: var(--you-text);
  font-size: 17px;
  font-weight: 600;
  text-decoration: none;
  padding: 15px var(--s4);
  border-radius: var(--pill);
  box-shadow: 0 8px 24px rgba(43, 108, 246, 0.28);
}

.hero-foot {
  font-size: var(--size-small);
  color: var(--ink-soft);
  margin-top: var(--s3);
}

/* Tells them there is something below. Sits over the thread, fades as they
   start scrolling. */
.scroll-hint {
  position: absolute;
  left: 0;
  right: 0;
  /* Well clear of the bottom edge. iOS Safari and Chrome both float a bar
     over the last ~50px, and env(safe-area-inset-bottom) is what a phone
     reports for the part of the screen its own chrome is sitting on. */
  bottom: calc(var(--s8) + env(safe-area-inset-bottom, 0px));
  text-align: center;
  font-size: var(--size-small);
  color: var(--ink-soft);
  letter-spacing: 0.04em;
}

/* A chevron drawn from two borders on a rotated square — no image, no font. */
.chev {
  display: block;
  width: 7px;
  height: 7px;
  margin: 5px auto 0;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
}


/* ==========================================================================
   4 · SMALL SCREENS
   ========================================================================== */
@media (max-height: 620px) {
  :root { --size-name: 42px; --size-line: 18px; }
  .hero-card { padding: var(--s5) var(--s4) var(--s4); }
}
