/* ==========================================================================
   Landing — the front door.

   One screen: the brand, one line of promise, one input. Submitting it plays
   the launch transition and hands off to the assembler (/build/), so the two
   pages read as one motion rather than two documents.

   Palette is the light set from the live properties, matching assembler.css:
     --brand #1d969e   --brand-dark #17787f   --ink #17262b   --line #e2eaec
   The handoff colour (--arrive) is the assembler's page background, so the
   veil that covers this page is already the colour of the next one.
   ========================================================================== */

:root {
  --brand: #1d969e;
  --brand-dark: #17787f;
  --ink: #17262b;
  --ink-2: #33414a;
  --muted: #6b7a84;
  --line: #dce2e5;
  --surface: #ffffff;
  --page: #ffffff;
  --arrive: #f4f7f8;

  /* Water. Four passes at different speeds read as depth. */
  --w1: rgba(29, 150, 158, 0.16);
  --w2: rgba(45, 180, 190, 0.11);
  --w3: rgba(29, 150, 158, 0.08);
  --w4: rgba(29, 150, 158, 0.22);
  /* The four translucent layers stacked on the page background, flattened.
     .flood__body has to be this exact colour or the join between the crests
     and the fill below them shows as a horizontal seam while the water rises —
     one alpha pass cannot match four. Recompute it if any --w* changes. */
  --flood-fill: #98d1d5;

  --f-sans: Poppins, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* The launch clock. Every duration below is derived from these two so the
     sequence can be retimed in one place. */
  --t-exit: 260ms;
  --t-rise: 700ms;
}

:root[data-theme="dark"] {
  --ink: #e6edf3;
  --ink-2: #cfdae0;
  --muted: #8496a0;
  --line: #2a3744;
  --surface: #12202c;
  --page: #0f1824;
  /* --arrive is deliberately *not* overridden: it is the colour of the page
     being navigated to, and the assembler has no dark theme. Fading to this
     page's own dark grey would only move the change of surface to after the
     navigation, where it lands as a flash instead of a cross-fade. */

  --w1: rgba(45, 212, 191, 0.12);
  --w2: rgba(56, 189, 248, 0.09);
  --w3: rgba(45, 212, 191, 0.06);
  --w4: rgba(20, 160, 180, 0.20);
  --flood-fill: #175763;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--page);
  color: var(--ink);
  font-family: var(--f-sans);
  font-weight: 400;
  overflow-x: hidden;
}

.sr-only {
  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;
  border: 0;
}

/* --------------------------------------------------------------------------
   The water
   -------------------------------------------------------------------------- */

.flood {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 26vh;
  min-height: 150px;
  z-index: 0;
  pointer-events: none;
  transform: translate3d(0, 0, 0);
  transition: transform var(--t-rise) cubic-bezier(.66, 0, .34, 1);
}

.flood__waves,
.flood__waves .waves {
  width: 100%;
  height: 100%;
  display: block;
}

/* Hangs below the crests. Off-screen at rest; it is what fills the viewport
   once the whole .flood block is raised. */
.flood__body {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 200vh;
  background: var(--flood-fill);
}

.waves__set > use { animation: wave-drift 26s cubic-bezier(.55, .5, .45, .5) infinite; }
.waves__l1 { animation-delay: -2s; animation-duration:  9s; fill: var(--w1); }
.waves__l2 { animation-delay: -3s; animation-duration: 13s; fill: var(--w2); }
.waves__l3 { animation-delay: -4s; animation-duration: 17s; fill: var(--w3); }
.waves__l4 { animation-delay: -5s; animation-duration: 24s; fill: var(--w4); }

@keyframes wave-drift {
  from { transform: translate3d(-90px, 0, 0); }
  to   { transform: translate3d( 85px, 0, 0); }
}

/* --------------------------------------------------------------------------
   Dark-mode lamp
   -------------------------------------------------------------------------- */

.lamp {
  position: fixed;
  top: 22px;
  right: 26px;
  z-index: 3;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: #e0a92b;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(20, 60, 66, .06);
  transition: transform .12s ease, border-color .15s ease, box-shadow .15s ease;
}
.lamp:hover { transform: translateY(-1px); border-color: var(--brand); }
.lamp:active { transform: scale(.94); }
.lamp svg { width: 22px; height: 22px; }
:root[data-theme="dark"] .lamp { color: #ffd766; box-shadow: none; }

/* --------------------------------------------------------------------------
   Hero

   Centred, then lifted off the true middle: the waves own the bottom quarter
   of the screen and a mathematically centred block sits visibly low against
   them.
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 40px 20px calc(20vh + env(safe-area-inset-bottom));
}

.hero__inner {
  width: min(720px, 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.hero__logo {
  width: 478px;
  max-width: 84%;
  height: auto;
}
.hero__logo--dark { display: none; }
:root[data-theme="dark"] .hero__logo--light { display: none; }
:root[data-theme="dark"] .hero__logo--dark { display: block; }

.hero__tagline {
  margin: 18px 0 0;
  font-size: 1.12rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   The call to action — a chat bar that is really one button

   Shaped like the composer it leads to, so the affordance is legible at a
   glance, but it takes no text: the conversation belongs to the assembler.
   The whole bar is the target, not just the circle at its end.
   -------------------------------------------------------------------------- */

.cta {
  width: 100%;
  margin-top: 42px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 6px 5px 18px;
  border: 1px solid var(--line);
  border-radius: 26px;
  background: var(--surface);
  box-shadow: 0 2px 12px rgba(20, 60, 66, .06);
  text-decoration: none;
  cursor: pointer;
  transition: border-color .2s ease, box-shadow .25s ease, transform .25s ease;
}
.cta:hover {
  border-color: var(--brand);
  box-shadow: 0 10px 26px -14px rgba(29, 150, 158, .55);
  transform: translateY(-1px);
}
.cta:focus-visible {
  outline: 0;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(29, 150, 158, .18);
}
.cta:active { transform: translateY(0) scale(.995); }
:root[data-theme="dark"] .cta { box-shadow: none; }

/* Holds the line at a constant height while the text is still being typed —
   an empty span would collapse the bar on the first frame. */
.cta__line {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  height: 40px;
  font-size: 1rem;
  line-height: 1.2;
  color: #9aa7ac;
  text-align: left;
  overflow: hidden;
  white-space: nowrap;
}
:root[data-theme="dark"] .cta__line { color: #7d909a; }

.cta__type { flex-shrink: 1; overflow: hidden; text-overflow: clip; }

.cta__caret {
  flex-shrink: 0;
  width: 2px;
  height: 1.1em;
  margin-left: 2px;
  background: var(--brand);
  border-radius: 1px;
  animation: caret-blink 1.06s steps(1, end) infinite;
}
@keyframes caret-blink { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }

/* Once the line has been typed out in full there is nothing left to point at,
   so the caret stands down until the loop starts over. */
.cta[data-typing="done"] .cta__caret { animation-duration: 1.6s; opacity: .55; }

.cta__send {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--brand-dark);
  color: #fff;
  transition: transform .2s cubic-bezier(.2, .8, .3, 1.4), background .15s ease;
}
.cta__send svg { width: 17px; height: 17px; margin-left: 1px; }
.cta:hover .cta__send { background: var(--brand); transform: scale(1.06); }
.cta:active .cta__send { transform: scale(.93); }

/* --------------------------------------------------------------------------
   Nav pills and footnote
   -------------------------------------------------------------------------- */

.hero__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 22px;
}

.pill {
  padding: 9px 20px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  font-size: .9rem;
  text-decoration: none;
  transition: border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.pill:hover {
  border-color: var(--brand);
  color: var(--brand-dark);
  box-shadow: 0 4px 12px -6px rgba(29, 150, 158, .4);
}
:root[data-theme="dark"] .pill:hover { color: #7fe9d6; box-shadow: none; }

.hero__foot {
  margin: 16px 0 0;
  font-size: .74rem;
  color: var(--muted);
}
.hero__foot a {
  color: var(--brand-dark);
  text-decoration: none;
}
.hero__foot a:hover { text-decoration: underline; }
:root[data-theme="dark"] .hero__foot a { color: #7fe9d6; }

/* --------------------------------------------------------------------------
   Launch transition

   Roughly one second, in four overlapping beats:
     0ms    the bar takes the press; the hero leaves, staggered, furthest
            element first, and settles under a slight blur as it goes
     40ms   a circle of water grows out of the send button, from the exact
            point the user clicked
     60ms   the tide rises to meet it, so the flood arrives from two directions
     640ms  the veil resolves to the assembler's background colour
   landing.js navigates when the veil lands, with a timer behind it in case the
   transitionend never fires (a backgrounded tab will not fire one).
   -------------------------------------------------------------------------- */

.reveal {
  position: fixed;
  top: var(--ry, 50%);
  left: var(--rx, 50%);
  z-index: 2;
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  border-radius: 50%;
  background: var(--flood-fill);
  transform: scale(0);
  opacity: 0;
  pointer-events: none;
  will-change: transform;
}

body.is-launching .reveal {
  transform: scale(var(--rs, 20));
  opacity: 1;
  /* Out-in: quick off the button so the click feels answered, then long and
     slow across the screen. A single ease would look like a loading spinner. */
  transition: transform 780ms cubic-bezier(.62, .01, .3, 1),
              opacity 120ms linear;
  transition-delay: 40ms, 40ms;
}

.veil {
  position: fixed;
  inset: 0;
  z-index: 4;
  background: var(--arrive);
  opacity: 0;
  pointer-events: none;
  transition: opacity 320ms ease;
}

body.is-launching .veil {
  opacity: 1;
  transition-delay: 640ms;
}

body.is-launching { cursor: progress; }
body.is-launching .cta { pointer-events: none; }

body.is-launching .flood {
  /* Past the top edge — the crests clear the viewport and .flood__body, which
     is twice the viewport tall, covers everything they leave behind. */
  transform: translate3d(0, -112vh, 0);
}

body.is-launching .lamp {
  opacity: 0;
  transition: opacity 160ms ease;
}

body.is-launching .hero__logo,
body.is-launching .hero__tagline,
body.is-launching .hero__nav,
body.is-launching .hero__foot {
  animation: hero-exit var(--t-exit) cubic-bezier(.32, 0, .67, 0) both;
}
/* Furthest from the bar leaves first, so the hero recedes towards the thing
   that was clicked instead of all going at once. */
body.is-launching .hero__logo    { animation-delay:  0ms; }
body.is-launching .hero__tagline { animation-delay: 45ms; }
body.is-launching .hero__foot    { animation-delay: 60ms; }
body.is-launching .hero__nav     { animation-delay: 90ms; }

/* The bar is the thing the user just acted on, so it holds a beat longer, dips
   under the press, then lifts away — carried into the next page rather than
   dismissed with everything else. */
body.is-launching .cta {
  animation: cta-exit 460ms cubic-bezier(.4, 0, .2, 1) both;
  animation-delay: 90ms;
  border-color: var(--brand);
}
body.is-launching .cta__caret { animation: none; opacity: 0; }
body.is-launching .cta__send { background: var(--brand); transform: scale(1.12); }

@keyframes hero-exit {
  from { opacity: 1; transform: none; filter: blur(0); }
  to   { opacity: 0; transform: translateY(-18px) scale(.985); filter: blur(4px); }
}

@keyframes cta-exit {
  0%   { opacity: 1; transform: none; }
  22%  { opacity: 1; transform: translateY(3px) scale(.99); }
  100% { opacity: 0; transform: translateY(-52px) scale(1.03); filter: blur(3px); }
}

/* --------------------------------------------------------------------------
   Small screens
   -------------------------------------------------------------------------- */

@media (max-width: 620px) {
  .hero { padding-bottom: calc(24vh + env(safe-area-inset-bottom)); }
  .hero__logo { width: 300px; }
  .hero__tagline { font-size: 1rem; }
  .cta { margin-top: 30px; padding-left: 15px; }
  .cta__line { font-size: .92rem; }
  .hero__nav { gap: 8px; }
  .pill { padding: 8px 15px; font-size: .84rem; }
  .lamp { top: 14px; right: 14px; }
}

/* --------------------------------------------------------------------------
   Reduced motion

   The drift, the rise and the stagger all go; the veil stays, because without
   any cover the navigation is a hard white flash. It becomes a plain
   cross-fade — landing.js shortens its own wait to match.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .waves__set > use { animation: none; }
  .cta__caret { animation: none; }
  .flood { transition: none; }
  .reveal { display: none; }
  body.is-launching .flood { transform: none; }
  body.is-launching .hero__logo,
  body.is-launching .hero__tagline,
  body.is-launching .cta,
  body.is-launching .hero__nav,
  body.is-launching .hero__foot { animation: none; opacity: 0; transition: opacity 160ms linear; }
  body.is-launching .veil { transition-delay: 0ms; transition-duration: 160ms; }
}
