/* join.css - Rahti join flow (hero form, "Text me the link too", sticky bar,
   thank-you + share row, launch mode, #waitlist card, captcha sheet).

   Loaded AFTER the inline <style> in index.html, so equal-specificity rules here
   win by source order. Every colour, font and radius is an existing token from
   that inline :root (--ink, --cream, --gold, --btn-*, --err, ...). The only new
   :root entries are the layout tokens in the first block. No images, no font
   files, no external requests, no !important.

   Hooks this file relies on:
     .join / .join__* / .join-done / .share / .joinbar / .joinbar__*   structure
     [hidden]                          every show/hide the JS does
     [aria-expanded="true"]            on .join__more (the phone disclosure)
     [data-visible="true"|"false"]     on the sticky bar
     html.join-bar-open                page bottom padding while the bar is up

   Specificity note: the inline CSS still has `.wait form`, `.wait input` and
   `.wait .note` rules (0,1,1). Everything here that has to beat them is
   written with at least two classes. */


/* ---------------------------------------------------------------- 1. tokens */
:root{
  --field-bg:var(--ink-2);
  --field-border:rgba(212,175,143,.5);       /* 3.17:1 vs --ink, WCAG 1.4.11 */
  --field-border-focus:var(--gold);
  --focus-ring:var(--btn-gold);               /* 10.72:1 dark, 5.28:1 light */
  --bar-h:64px;                               /* bar row height, excludes border + safe area */
  --z-bar:40; --z-nav:50; --z-sheet:60;
  --join-scheme:dark;                         /* native widgets (checkbox, autofill) follow the theme */
}
@media (prefers-color-scheme: light){
  :root{
    --field-border:rgba(122,92,51,.8);        /* gold at any alpha fails 3:1 on the light page */
    --join-scheme:light;
  }
}

button, [type=submit], a.btn{touch-action:manipulation;-webkit-tap-highlight-color:transparent}
:where(input, button, a, summary):focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px}
#join, #waitlist{scroll-margin-top:96px}      /* nav 70 + 26 */

.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}


/* ----------------------------------------- 2. hero first-screen adjustments */
.sub{font-size:17px;line-height:1.5;margin:18px 0 22px;max-width:46ch;text-wrap:pretty}
.hero-link{position:relative;display:inline-block;margin-top:2px;font-size:13.5px;line-height:1.65;
  color:var(--cream-dim);transition:color .2s}
.hero-link:hover{color:var(--cream)}
:has(> .join-done:not([hidden])) ~ .hero-link{margin-top:14px}   /* breathing room under the share row */
/* 44px tap target without growing the layout box: extends downward only so it
   never overlaps the 44px "Text me the link too" toggle above it. */
.hero-link::after{content:'';position:absolute;inset:-2px -10px -20px}

@media (max-width:860px){
  .hero{padding:80px 0 56px}                  /* near-moon star ends at y=145, eyebrow starts 151 */
  .eyebrow{margin-bottom:14px}                /* was 18 */
  .nav-links .btn{display:none}               /* the bottom bar is the phone's join control */
}
@media (min-width:861px){
  .sub{font-size:18px;line-height:1.6;margin:22px 0 28px}
  .hero{padding:140px 0 64px}                 /* copy column starts at y=211: clears the near-moon star (ends 205) by 6px */
  .hero-in{align-items:start}                 /* nothing re-centres when the form changes state */
  .demo-wrap{margin-top:-44px}                /* phone stays exactly where it was (top 167); hero height unchanged */
}


/* ------------------------------------------------------------ 3. .join form */
/* The form is a one-column grid. The email field and the submit button share
   grid cell 1/1 (button inset on the right, like a pill). Opening the phone
   disclosure moves the button to the last row by CSS alone, so it works whether
   or not the markup puts the button inside .join__row or after the panel. The
   `order` values give the visual order: field, message, note, toggle, panel,
   (expanded) button. */
.join{position:relative;display:grid;grid-template-columns:minmax(0,1fr);align-content:start;
  max-width:460px;color-scheme:var(--join-scheme)}
.join .join__row{display:contents}

.join .join__email,
.join .join__phone{
  width:100%;min-width:0;height:52px;padding:0 18px;
  background:var(--field-bg);color:var(--cream);
  border:1px solid var(--field-border);border-radius:100px;
  font-family:inherit;font-size:16px;line-height:1;
}
.join .join__email{grid-area:1/1;order:0;padding-right:132px}   /* 117 button + 4 inset + 11 air; fits "name@example.com" at 360 */
.join .join__email::placeholder,
.join .join__phone::placeholder{color:var(--cream-faint);opacity:1}
.join .join__email:focus-visible,
.join .join__phone:focus-visible{
  border-color:var(--field-border-focus);
  outline:2px solid var(--focus-ring);outline-offset:2px;       /* beats the legacy `.wait input{outline:none}` */
}
.join .join__email[aria-invalid="true"],
.join .join__phone[aria-invalid="true"]{border-color:var(--err)}
.join .join__email:disabled,
.join .join__phone:disabled{opacity:.55;cursor:default}

/* Keep browser autofill (the main phone path) inside the pill and on-theme. */
.join .join__email:-webkit-autofill,
.join .join__phone:-webkit-autofill,
.joinbar .joinbar__email:-webkit-autofill{
  -webkit-text-fill-color:var(--cream);caret-color:var(--cream);
  box-shadow:0 0 0 100px var(--field-bg) inset;
}

.join .join__submit{
  grid-area:1/1;order:1;justify-self:end;align-self:center;z-index:1;
  margin:0 4px 0 0;min-width:117px;height:44px;padding:0 18px;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:14px;line-height:1;white-space:nowrap;
}
.join .join__submit:active{transform:translateY(0) scale(.98)}
.join .join__submit:disabled,
.join .join__submit:disabled:hover{opacity:.6;cursor:default;transform:none;box-shadow:none;filter:none}

.join .join__msg{order:2;margin-top:10px;font-size:13.5px;line-height:1.5;color:var(--err)}
.join .join__msg[data-tone="info"],
.join .join__msg.is-info{color:var(--cream-dim)}
.join .join__note{order:3;margin-top:10px;font-size:12.5px;line-height:1.5;color:var(--cream-faint);text-wrap:pretty}
/* JavaScript off: index.html hides every form in a <noscript><style>, and this
   note takes their place. It sits outside .join, so it is styled on its own. */
noscript > .join__note{display:block;max-width:460px;font-size:14px;line-height:1.55;color:var(--cream-dim);text-wrap:pretty}
.wait noscript > .join__note{margin:30px auto 0}
#join > noscript > .join__note{margin-bottom:12px}   /* air above "See Congregation Mode" */

/* "+ Text me the link too". The +/minus glyph is drawn here from aria-expanded,
   so it never disagrees with the real state; any literal glyph span is hidden. */
.join .join__more{
  order:4;justify-self:start;
  display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0;
  background:none;border:0;cursor:pointer;
  font-family:inherit;font-size:13.5px;font-weight:500;line-height:1.2;
  color:var(--btn-gold);                       /* --gold fails 4.5:1 in light; dark value is near-identical */
}
.join .join__more:disabled{opacity:.55;cursor:default}
.join .join__more::before{content:'+';content:'+' / '';font-size:17px;line-height:1;transform:translateY(-1px)}   /* "/ ''" = empty alt text, so the glyph is not part of the accessible name */
.join .join__more[aria-expanded="true"]::before{content:'\2212';content:'\2212' / ''}
.join .join__more-glyph{display:none}

/* The panel: a grid-row 0fr/1fr animation driven by the [hidden] attribute
   (display is transitioned discretely, so open and close both animate; engines
   without that support simply show/hide instantly). The inner box clips during
   the animation; its padding + negative margin leave room for focus rings. */
.join .join__sms{order:5;display:grid;grid-template-rows:1fr}
.join .join__sms-in{min-height:0;overflow:hidden;padding:6px 6px 8px;margin:-6px -6px -8px}
.join .join__sms[hidden]{grid-template-rows:0fr}
.join .join__sms[hidden] .join__sms-in{opacity:0}
.join .join__sms-in > :first-child{margin-top:4px}

.join .join__label{display:block;margin:4px 0 6px;font-size:13px;color:var(--cream-dim)}
.join .join__help{margin-top:8px;font-size:12.5px;line-height:1.5;color:var(--cream-faint)}

/* Consent: the whole card is the hit target; the box is a native checkbox so
   keyboard, VoiceOver and autofill keep working. Never pre-ticked (markup). */
.join .join__consent{
  display:grid;grid-template-columns:22px minmax(0,1fr);gap:12px;align-items:start;
  margin-top:16px;padding:14px 16px;text-align:left;
  background:rgba(212,175,143,.05);
  background:color-mix(in srgb, var(--gold) 5%, transparent);
  border:1px solid var(--gold-faint);border-radius:16px;
  font-size:12.5px;line-height:1.5;color:var(--cream-dim);cursor:pointer;
}
.join .join__consent input{
  width:22px;height:22px;min-width:0;margin:1px 0 0;padding:0;flex:none;
  accent-color:var(--btn-gold);cursor:pointer;
  /* undo the legacy `.wait input` pill styling so the native box stays native */
  background:revert;border:revert;border-radius:revert;font-size:inherit;
}
.join .join__consent input:disabled{opacity:.55;cursor:default}
.join .join__consent:has(input:disabled){cursor:default}
.join .join__consent a{color:var(--btn-gold);text-decoration:underline;text-underline-offset:2px}
.join .join__consent:focus-within{border-color:var(--gold)}
.join .join__consent:has(input[aria-invalid="true"]){border-color:var(--err)}
/* Light scheme: the 5% gold tint under --cream-dim text measures 4.43:1 on the hero
   (the page, not --ink-2, sits behind it). No tint = 4.62:1 on the page, ~5.0:1 in the card. */
@media (prefers-color-scheme: light){
  .join .join__consent{background:transparent}
}

/* Stacked fallback: field, then a full-width 52px button. Hero and bar need it
   below 360px; the #waitlist card (20px card padding) already truncates the
   "name@example.com" placeholder below ~400px, so it stacks up to 420px.
   Declared before the "disclosure open" rule so that one still wins. */
@media (max-width:359px){
  .join .join__email{padding-right:18px}
  .join .join__submit{grid-area:auto;order:1;justify-self:stretch;align-self:auto;
    width:100%;min-width:0;height:52px;margin:8px 0 0}
}
@media (max-width:420px){
  .join.join--card .join__email{padding-right:18px}
  .join.join--card .join__submit{grid-area:auto;order:1;justify-self:stretch;align-self:auto;
    width:100%;min-width:0;height:52px;margin:8px 0 0}
}

/* Disclosure open: field keeps its exact box (only its right padding relaxes),
   the button drops to a full-width 52px row under the consent card. */
.join:is(.is-expanded, [data-expanded="true"], :has([aria-expanded="true"])) .join__email{padding-right:18px}
.join:is(.is-expanded, [data-expanded="true"], :has([aria-expanded="true"])) .join__submit{
  grid-area:auto;order:7;justify-self:stretch;align-self:auto;
  width:100%;min-width:0;height:52px;margin:16px 0 0;
}
/* ...and the message moves with it (just above the button), so an error such as
   "Tick the box..." is read where the thumb is, not 400px up under the email field. */
.join:is(.is-expanded, [data-expanded="true"], :has([aria-expanded="true"])) .join__msg{order:6;margin-top:12px}

/* In the #waitlist card: left-aligned inside the centred card, 100% of the
   460px column (replaces `.wait form` and `.wait input{min-width:240px}`). */
.join.join--card{display:grid;gap:0;flex-wrap:nowrap;justify-content:normal;
  margin:30px auto 0;text-align:left}
@media (max-width:860px){
  .wait{padding:40px 20px}                    /* field is 287px wide at 375, nothing overflows */
}


/* --------------------------------------------------- 4. thank-you + share */
.join-done{display:flex;flex-direction:column;align-items:flex-start;max-width:460px;text-align:left}
.join-done .wl-check{width:46px;height:46px;margin-bottom:10px;background:var(--btn-bg);color:var(--btn-ink)}
.join-done .wl-done-title,
.join-done [data-join-done-title]{
  font-family:'Cormorant Garamond','Cormorant Fallback G','Cormorant Fallback T',serif;font-size:28px;font-weight:500;line-height:1.1;color:var(--btn-gold);
}
.join-done .wl-done-sub,
.join-done .wl-done-phone,
.join-done [data-join-done-sub]{
  max-width:44ch;margin-top:8px;font-size:15px;line-height:1.55;color:var(--cream-dim);
}
.join-done :is(.wl-done-title, [data-join-done-title], .wl-done-sub, .wl-done-phone, [data-join-done-sub]):focus-visible,
.join-done:focus-visible{outline:2px solid var(--focus-ring);outline-offset:4px;border-radius:6px}
/* The done title only ever gets focus from script, and Chromium does not match
   :focus-visible for that, so a keyboard user would see no ring. Plain :focus here. */
.join-done [data-join-done-title]:focus{outline:2px solid var(--focus-ring);outline-offset:4px;border-radius:6px}
.wait .join-done,
.join--card .join-done{align-items:center;margin:30px auto 0;text-align:center}

.share, [data-join-share]{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:18px}
.share__label{margin-right:4px;font-size:12.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--cream-faint)}
.share .btn{height:44px;padding:0 18px;display:inline-flex;align-items:center;justify-content:center;font-size:13.5px}
.share [data-join-share-url]{padding:10px 16px;border:1px solid var(--gold-faint);border-radius:100px;
  font-size:13.5px;line-height:1.3;color:var(--cream);overflow-wrap:anywhere}   /* last-resort: selectable URL */
.wait .share,
.join--card .share{justify-content:center}
/* Phones: the label gets its own line, then WhatsApp + Messages + Copy link share one row
   (375 and 390) instead of leaving a lone orphan button. The bar's compact row is untouched. */
@media (max-width:480px){
  .share__label{flex-basis:100%;margin-right:0}
  .join-done:not(.joinbar__done) .share .btn{padding:0 16px}
  .wait .share .btn{flex:1 1 auto}            /* narrow card: a wrapped button fills its row instead of sitting alone */
}


/* ----------------------------------------------------------- 5. sticky bar */
/* Phones only. Hidden = off-screen, transparent, visibility:hidden (so nothing
   inside is tabbable or read); data-visible="true" brings it in. The motion is
   in section 9 so reduced motion toggles it instantly. */
:is(.joinbar, [data-join-bar]){
  position:fixed;left:0;right:0;bottom:var(--kb, 0px);z-index:var(--z-bar);
  padding:10px max(16px, env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  background:var(--nav-bg);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  border-top:1px solid var(--gold-faint);box-shadow:0 -1px 24px rgba(0,0,0,.18);
  color-scheme:var(--join-scheme);
  visibility:hidden;opacity:0;pointer-events:none;transform:translateY(calc(100% + 24px));
}
:is(.joinbar, [data-join-bar])[data-visible="true"]{
  visibility:visible;opacity:1;pointer-events:auto;transform:none;
}
@media (min-width:861px){
  :is(.joinbar, [data-join-bar]){display:none}
}

.joinbar .joinbar__row{max-width:460px;margin:0 auto}
.joinbar .joinbar__fields{display:flex;gap:8px}
.joinbar .joinbar__email{
  flex:1;min-width:0;height:44px;padding:0 16px;
  background:var(--field-bg);color:var(--cream);
  border:1px solid var(--field-border);border-radius:100px;
  font-family:inherit;font-size:16px;line-height:1;
}
.joinbar .joinbar__email{text-overflow:ellipsis}                 /* 320px: truncate the placeholder cleanly, not mid-letter */
.joinbar .joinbar__email::placeholder{color:var(--cream-faint);opacity:1}
.joinbar .joinbar__email:focus-visible{border-color:var(--field-border-focus);outline:2px solid var(--focus-ring);outline-offset:2px}
.joinbar .joinbar__email[aria-invalid="true"]{border-color:var(--err)}
.joinbar .joinbar__email:disabled{opacity:.55;cursor:default}
.joinbar .joinbar__submit{height:44px;min-width:117px;padding:0 18px;display:inline-flex;align-items:center;justify-content:center;
  font-size:14px;line-height:1;white-space:nowrap}
.joinbar .joinbar__submit:disabled,
.joinbar .joinbar__submit:disabled:hover{opacity:.6;cursor:default;transform:none;box-shadow:none;filter:none}
.joinbar .joinbar__msg{margin:0 0 8px;font-size:13px;line-height:1.4;color:var(--err)}

/* Compact confirmation inside the bar (only visible if the bar is kept open
   after a join): check + one line + share buttons. */
.joinbar .join-done{flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px 12px;max-width:460px;margin:0 auto}
.joinbar .join-done .wl-check{width:28px;height:28px;margin:0;font-size:15px}
.joinbar .join-done .wl-done-title,
.joinbar .join-done [data-join-done-title]{font-family:inherit;font-size:13.5px;font-weight:600;line-height:1.3;color:var(--cream)}
.joinbar .join-done :is(.wl-done-sub, .wl-done-phone, [data-join-done-sub], .share__label){display:none}
.joinbar .join-done .share{margin:0 0 0 auto;gap:8px}
.joinbar .join-done .share .btn{font-size:13px}

/* Page bottom padding while the bar is up, so footer links and the last FAQ
   item can scroll clear of it; scroll-padding keeps Tab focus out from under it. */
@media (max-width:860px){
  html.join-bar-open body{padding-bottom:calc(var(--bar-h) + 1px + env(safe-area-inset-bottom))}
  html.join-bar-open{scroll-padding-bottom:calc(var(--bar-h) + 1px + env(safe-area-inset-bottom) + 16px)}
}


/* --------------------------------------------------------------- 6. launch */
.btn--store{height:52px;padding:0 26px;display:inline-flex;align-items:center;justify-content:center;
  font-size:15px;line-height:1;white-space:nowrap}
.join--launch .btn--store{justify-self:start}
#join:has(> .join--launch:not([hidden])) ~ .hero-link{margin-top:10px}   /* .hero-link is a sibling of #join, not of .join--launch */
@media (max-width:480px){
  .join--launch .btn--store{justify-self:stretch;width:100%}
}
.joinbar .btn--store{display:flex;width:100%;max-width:460px;height:48px;margin:0 auto}
@media (max-width:860px){
  html.join-bar-open:has(.joinbar .btn--store:not([hidden])){--bar-h:68px}   /* 48px button + 20px padding */
}


/* ------------------------------------------------------- 7. captcha sheet */
/* Only shown when Turnstile asks for interaction; normal users never see it.
   join.js flips [data-join-turnstile][data-visible="true"] on the one container
   (which ships visually hidden via .sr-only), so the visible state has to undo
   every .sr-only declaration. The spec's .captcha-sheet class styles the same box. */
:is(.captcha-sheet, [data-join-turnstile][data-visible="true"]){
  position:fixed;inset:auto 0 0 0;z-index:var(--z-sheet);
  width:auto;height:auto;margin:0;overflow:visible;clip:auto;clip-path:none;white-space:normal;
  padding:20px 20px calc(24px + env(safe-area-inset-bottom));
  background:var(--ink-2);border:0;border-top:1px solid var(--gold-faint);border-radius:20px 20px 0 0;
  box-shadow:0 -20px 60px rgba(0,0,0,.5);color-scheme:var(--join-scheme);
}
:is(.captcha-sheet, [data-join-turnstile][data-visible="true"]) h3{
  margin-bottom:12px;font-family:'Cormorant Garamond','Cormorant Fallback G','Cormorant Fallback T',serif;font-size:24px;font-weight:500;color:var(--cream);
}
:is(.captcha-sheet, [data-join-turnstile][data-visible="true"]) :is(.btn, [data-join-turnstile-cancel]){min-height:44px}
@media (min-width:861px){
  :is(.captcha-sheet, [data-join-turnstile][data-visible="true"]){
    inset:50% auto auto 50%;translate:-50% -50%;width:360px;
    border:1px solid var(--gold-faint);border-radius:20px;
  }
}


/* ------------------------------------------------------------- 8. [hidden] */
/* Author `display` rules above would otherwise beat the UA `[hidden]` rule.
   Declared late and with an extra type selector so it outranks them. */
html :is(.join, .joinbar, [data-join-bar], .join-done, .share, .captcha-sheet) [hidden],
html :is(.join, .joinbar, [data-join-bar], .join-done, .share, .captcha-sheet)[hidden]{display:none}


/* ------------------------------------------------------------- 9. motion */
/* All motion lives here, so prefers-reduced-motion users get none by
   construction (the bar and the panel then toggle instantly). Only transform,
   opacity, border-color and the grid-row trick are animated. */
@keyframes joinIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes joinFade{from{opacity:0}to{opacity:1}}
@keyframes joinSheetIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion: no-preference){
  .join .join__email,
  .join .join__phone,
  .joinbar .joinbar__email{transition:border-color .15s ease}
  .join .join__submit{transition:transform .1s ease-out, box-shadow .15s ease, filter .15s ease}

  .join .join__sms{transition:grid-template-rows .24s cubic-bezier(.2,.8,.2,1), display .24s allow-discrete}
  .join .join__sms-in{transition:opacity .16s ease .08s}
  .join .join__sms[hidden]{transition-duration:.2s}
  .join .join__sms[hidden] .join__sms-in{transition-delay:0s;transition-duration:.12s}

  .join .join__msg:not([hidden]),
  .joinbar .joinbar__msg:not([hidden]){animation:joinFade .15s ease}
  .join-done{animation:joinIn .5s ease}
  :is(.captcha-sheet:not([hidden]), [data-join-turnstile][data-visible="true"]){animation:joinSheetIn .2s ease-out}

  :is(.joinbar, [data-join-bar]){
    transition:transform .2s cubic-bezier(.4,0,1,1), opacity .15s ease, visibility 0s linear .2s;
  }
  :is(.joinbar, [data-join-bar])[data-visible="true"]{
    transition:transform .26s cubic-bezier(.2,.8,.2,1), opacity .18s ease, visibility 0s;
  }
  :is(.joinbar, [data-join-bar])[data-typing="true"]{transition:none}   /* follow the iOS keyboard without lag */
}
@starting-style{
  .join .join__sms{grid-template-rows:0fr}
  .join .join__sms-in{opacity:0}
}
