/* Onboarding front door + live status page.
   Uses the fancy-v2-light tokens (--w-*, --green-*) from fancy.css.

   Note on headings: fancy.css sets
     h1,h2 { font-family:...!important; font-weight:700!important; letter-spacing:-0.03em!important }
   so this file only ever sets font-size on an h1. Re-declaring the other three
   here would be dead weight — they cannot win. */

.start-page {
  padding: 150px 24px 110px;
  min-height: 78vh;
  min-height: 78dvh;
  display: flex;
  align-items: center;
}

.start-wrap {
  width: 100%;
  /* Without this, a long unbroken group name in a grid/flex child can push the
     whole page wider than the viewport instead of wrapping. */
  min-width: 0;
}

.start-wrap--narrow {
  max-width: 560px;
  margin: 0 auto;
}

/* ---------- head ---------- */

.start-head {
  text-align: center;
  max-width: 620px;
  margin: 0 auto 48px;
}

.start-title {
  font-size: clamp(34px, 5vw, 52px);
  line-height: 1.05;
  color: var(--w-ink);
  margin: 10px 0 14px;
}

.start-sub {
  font-size: 17px;
  line-height: 1.55;
  color: var(--w-mut);
  margin: 0;
}

/* ---------- doors ---------- */

.start-doors {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 22px;
  align-items: start;
  max-width: 900px;
  margin: 0 auto;
}

.start-door {
  min-width: 0;
  background: var(--w-panel);
  border: 1px solid var(--w-line);
  border-radius: 22px;
  padding: 28px 26px 26px;
  box-shadow: rgba(31, 35, 33, 0.06) 0 6px 26px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.start-door--primary {
  padding-bottom: 30px;
  border-color: var(--w-line2);
  box-shadow: rgba(31, 35, 33, 0.09) 0 10px 34px;
}

.start-door-head {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.start-door-head > div {
  min-width: 0;
}

.start-door-head h2 {
  font-size: 19px;
  color: var(--w-ink);
  margin: 0 0 3px;
}

.start-door-head p {
  font-size: 14.5px;
  color: var(--w-mut);
  margin: 0;
  line-height: 1.45;
}

.start-door-icon {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  background: rgba(51, 117, 77, 0.1);
  color: var(--green-600);
  font-size: 15px;
}

/* ---------- live tile ---------- */

.start-tilewrap {
  display: flex;
  justify-content: center;
  padding: 6px 0 2px;
}

.start-tilewrap--lg {
  padding: 0 0 22px;
}

.start-tile {
  width: 78px;
  height: 78px;
  border-radius: 22px;
  display: grid;
  place-items: center;
  /* Two wide graphemes (emoji, CJK) must not spill past the rounded corners. */
  padding: 0 6px;
  overflow: hidden;
  white-space: nowrap;
  font-size: 30px;
  line-height: 1;
  font-weight: 650;
  letter-spacing: -0.02em;
  color: #fffdf4;
  transition: background 0.35s ease;
}

.start-tilewrap--lg .start-tile {
  width: 96px;
  height: 96px;
  border-radius: 27px;
  padding: 0 8px;
  font-size: 37px;
}

.start-tile.empty {
  background: var(--w-input-bg);
  border: 2px dashed var(--w-dash);
}

.start-tile.filled {
  animation: startTilePop 0.34s cubic-bezier(0.2, 1.3, 0.5, 1);
}

@keyframes startTilePop {
  from { transform: scale(0.82); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}

/* ---------- input ---------- */

.start-inputwrap {
  position: relative;
}

.start-input {
  width: 100%;
  /* Padding and border must not push the field past its container. */
  box-sizing: border-box;
  font: inherit;
  font-size: 17px;
  font-weight: 550;
  color: var(--w-ink);
  background: var(--w-input-bg);
  border: 1px solid var(--w-input-line);
  border-radius: 13px;
  padding: 14px 16px;
  outline: none;
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}

.start-input:focus {
  border-color: var(--green-400);
  box-shadow: 0 0 0 3px var(--w-focus);
}

.start-input--plain {
  font-size: 15.5px;
  font-weight: 500;
}

.start-input--plain::placeholder {
  color: var(--w-ph);
}

.start-ph {
  position: absolute;
  left: 17px;
  /* Stay clear of the caret and never overlap the field's right edge. */
  right: 17px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 17px;
  font-weight: 550;
  color: var(--w-ph);
}

.start-ph.in {
  animation: startPhIn 0.32s ease;
}

@keyframes startPhIn {
  from { opacity: 0; transform: translateY(-30%); }
  to   { opacity: 1; transform: translateY(-50%); }
}

.start-helper {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-top: -6px;
}

.start-hint,
.start-counter {
  font-size: 13px;
  color: var(--w-mut2);
}

.start-counter {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* Dark enough on the cream surface to clear WCAG AA for body text. */
.start-error {
  font-size: 14px;
  color: #8f3527;
  margin: -6px 0 0;
}

/* ---------- buttons ---------- */

.start-submit {
  width: 100%;
  justify-content: center;
}

.start-submit.invalid {
  opacity: 0.5;
}

.start-submit.busy {
  opacity: 0.7;
  cursor: progress;
}

.start-submit--ghost {
  background: var(--w-input-bg);
  border: 1px solid var(--w-input-line);
  color: var(--w-ink2);
}

.start-submit--ghost:hover {
  background: rgba(51, 117, 77, 0.09);
}

.shake {
  animation: startShake 0.32s ease;
}

@keyframes startShake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-6px); }
  75%      { transform: translateX(6px); }
}

/* ---------- status page ---------- */

.start-page--status {
  text-align: center;
}

.start-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  min-width: 0;
}

/* `display: flex` above beats the UA stylesheet's `[hidden] { display: none }`,
   which would leave all four states stacked on top of each other. */
.start-state[hidden],
.start-invite[hidden] {
  display: none;
}

.start-state h1 {
  font-size: clamp(27px, 4vw, 36px);
  color: var(--w-ink);
  margin: 0 0 10px;
  /* Group names are user input and can be one 100-character word. */
  overflow-wrap: anywhere;
}

.start-spinner {
  width: 44px;
  height: 44px;
  margin-bottom: 26px;
}

.start-spinner span {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 3px solid rgba(51, 117, 77, 0.18);
  border-top-color: var(--green-500);
  animation: startSpin 0.8s linear infinite;
}

@keyframes startSpin {
  to { transform: rotate(360deg); }
}

.start-expired-icon {
  width: 68px;
  height: 68px;
  border-radius: 20px;
  display: grid;
  place-items: center;
  margin-bottom: 24px;
  font-size: 26px;
  background: var(--w-input-bg);
  color: var(--w-mut);
}

/* code + invite rows */

.start-code,
.start-invite {
  width: 100%;
  min-width: 0;
  margin: 26px 0 6px;
}

.start-code-label {
  display: block;
  font-size: 12.5px;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--w-mut2);
  margin-bottom: 9px;
}

.start-code-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
}

.start-code-row code {
  /* min-width:0 is what actually lets the ellipsis happen inside a flex row. */
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--w-ink);
  background: var(--w-input-bg);
  border: 1px solid var(--w-input-line);
  border-radius: 12px;
  padding: 13px 15px;
  /* Deliberately NOT flex: text-overflow is ignored on a flex container, so a
     long invite URL would clip with no ellipsis. Block + line-height centres
     the single line just as well and keeps the truncation legible. */
  display: block;
  line-height: 24px;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* The code is the one thing a visitor may have to read off the screen and
     type into a phone, so one click selects the whole thing. */
  user-select: all;
}

.start-invite .start-code-row code {
  font-size: 14px;
  letter-spacing: 0;
  text-align: left;
}

.start-copy {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font: inherit;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--w-ink2);
  background: var(--w-input-bg);
  border: 1px solid var(--w-input-line);
  border-radius: 12px;
  padding: 0 16px;
  cursor: pointer;
  transition: background 0.16s ease, color 0.16s ease;
}

.start-copy:hover {
  background: rgba(51, 117, 77, 0.1);
}

.start-copy.copied {
  background: rgba(51, 117, 77, 0.14);
  color: var(--green-700);
  animation: startCopied 0.34s cubic-bezier(0.2, 1.35, 0.5, 1);
}

/* A small settle, so the confirmation is felt as well as read — the label
   swap alone is easy to miss when the button is under your cursor. */
@keyframes startCopied {
  0%   { transform: scale(1); }
  40%  { transform: scale(0.955); }
  100% { transform: scale(1); }
}

/* fancy.css gives .btn-f a focus ring; these plain buttons need their own. */
.start-copy:focus-visible,
.start-retry:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--w-focus);
}

.start-code-help {
  font-size: 13.5px;
  color: var(--w-mut2);
  margin: 10px 0 0;
}

.start-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 28px;
  width: 100%;
}

.start-actions .btn-f {
  width: 100%;
  /* Full-bleed reads as a mistake on a wide screen; the card is 560px. */
  max-width: 340px;
  justify-content: center;
}

.start-retry {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: inherit;
  font-size: 14.5px;
  font-weight: 550;
  color: var(--w-mut);
  background: none;
  border: 0;
  border-radius: 10px;
  padding: 6px 10px;
  cursor: pointer;
}

.start-retry:hover {
  color: var(--w-ink2);
}

.start-waiting-note {
  font-size: 13.5px;
  color: var(--w-mut2);
  margin: 26px 0 0;
}

/* Waiting is the dead stretch of this flow — the visitor is off in another
   app and this tab has nothing to say. A slow ring easing outward from the
   tile reads as "still holding this for you" without pretending to be
   progress, which would be a lie: we have no idea how far along they are. */
[data-state="waiting"] .start-tilewrap {
  position: relative;
}

[data-state="waiting"] .start-tilewrap::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 96px;
  height: 96px;
  margin-top: -11px;
  border-radius: 27px;
  border: 2px solid var(--green-400);
  transform: translate(-50%, -50%);
  pointer-events: none;
  animation: startHold 2.9s cubic-bezier(0.25, 0.6, 0.3, 1) infinite;
}

@keyframes startHold {
  0%        { transform: translate(-50%, -50%) scale(1);    opacity: 0.4; }
  70%, 100% { transform: translate(-50%, -50%) scale(1.34); opacity: 0; }
}

/* ---------- the burst ---------- */

.start-burst {
  position: fixed;
  z-index: 60;
  width: 0;
  height: 0;
  pointer-events: none;
}

.start-burst i {
  position: absolute;
  top: 0;
  left: 0;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  opacity: 0;
  animation: startBurst 900ms cubic-bezier(0.15, 0.7, 0.4, 1) forwards;
}

/* The extra 26px on the way out gives the pieces a little weight, so they
   arc and drop rather than radiating like a starburst. */
@keyframes startBurst {
  0% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(0.4) rotate(0deg);
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform:
      translate(calc(-50% + var(--dx)), calc(-50% + var(--dy) + 26px))
      scale(1)
      rotate(var(--rot));
  }
}

/* live celebration */

.start-live-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--green-700);
  background: rgba(51, 117, 77, 0.13);
  border-radius: 980px;
  padding: 5px 13px;
  margin: 0 0 14px;
}

.start-state--live.pop .start-tile {
  animation: startLivePop 0.5s cubic-bezier(0.18, 1.35, 0.42, 1);
}

@keyframes startLivePop {
  0%   { transform: scale(0.7) rotate(-4deg); opacity: 0; }
  60%  { transform: scale(1.06) rotate(1deg); }
  100% { transform: scale(1) rotate(0); opacity: 1; }
}

.start-state--live.pop h1,
.start-state--live.pop .start-sub,
.start-state--live.pop .start-invite,
.start-state--live.pop .start-actions {
  animation: startRise 0.5s cubic-bezier(0.25, 0.9, 0.3, 1) backwards;
}

.start-state--live.pop h1             { animation-delay: 0.08s; }
.start-state--live.pop .start-sub     { animation-delay: 0.14s; }
.start-state--live.pop .start-invite  { animation-delay: 0.2s; }
.start-state--live.pop .start-actions { animation-delay: 0.26s; }

@keyframes startRise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- narrow screens ---------- */

@media (max-width: 780px) {
  .start-doors {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  /* The fixed header is shorter here, and 150px of dead space above the fold
     pushes the name field off a phone screen. */
  .start-page {
    padding: 112px 16px 72px;
    align-items: flex-start;
  }

  .start-head {
    margin-bottom: 32px;
  }

  .start-door {
    padding: 22px 18px 20px;
    border-radius: 18px;
  }

  .start-code-row {
    flex-direction: column;
  }

  .start-copy {
    justify-content: center;
    padding: 11px 16px;
  }

  .start-actions .btn-f {
    max-width: none;
  }
}

/* The flip from waiting to live is the point of this page, but it must never
   be the reason someone feels unwell. Reduced motion gets a plain cross-fade. */
@media (prefers-reduced-motion: reduce) {
  .start-tile.filled,
  .start-state--live.pop .start-tile,
  .start-state--live.pop h1,
  .start-state--live.pop .start-sub,
  .start-state--live.pop .start-invite,
  .start-state--live.pop .start-actions,
  .start-ph.in,
  .start-copy.copied,
  .shake {
    animation: none;
  }

  /* The burst never renders at all (start-status.js returns early), but the
     holding ring is generated by CSS alone, so it has to be stopped here. */
  [data-state="waiting"] .start-tilewrap::after {
    animation: none;
    opacity: 0;
  }

  .start-state {
    animation: startFade 0.25s ease;
  }

  @keyframes startFade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  .start-spinner span {
    animation-duration: 2.4s;
  }
}
