// Vapor — tab views.
// Dark website chrome. Phone mockups stay light (they're the app screen).
// Tabs: still / ethos / features / research / faq

const D = {
  bg:       '#181613',
  bgSoft:   '#1f1c18',
  bgCard:   '#221f1b',
  ink:      '#E8E2D9',
  inkSoft:  'rgba(232, 226, 217, 0.62)',
  inkMid:   'rgba(232, 226, 217, 0.45)',
  inkFaint: 'rgba(232, 226, 217, 0.28)',
  inkGhost: 'rgba(232, 226, 217, 0.06)',
  sage:     '#7EA882',
  rule:     'rgba(232, 226, 217, 0.09)',
  ruleStrong: 'rgba(232, 226, 217, 0.2)',
};

// ─────────────────────────────────────────────────────────────────
// STILL — the landing
// ─────────────────────────────────────────────────────────────────
function ViewStill() {
  const [idx, setIdx] = React.useState(0);
  // phase: 'typing' | 'holding' | 'fading' | 'gap'
  const [phase, setPhase] = React.useState('typing');
  const [chars, setChars] = React.useState(0);

  const word = COPY.heroCycle[idx];

  React.useEffect(() => {
    let timer;
    if (phase === 'typing') {
      if (chars < word.length) {
        timer = setTimeout(() => setChars(c => c + 1), 150);
      } else {
        timer = setTimeout(() => setPhase('holding'), 0);
      }
    } else if (phase === 'holding') {
      timer = setTimeout(() => setPhase('fading'), 1400);
    } else if (phase === 'fading') {
      timer = setTimeout(() => setPhase('gap'), 1200);
    } else if (phase === 'gap') {
      timer = setTimeout(() => {
        setIdx(i => (i + 1) % COPY.heroCycle.length);
        setChars(0);
        setPhase('typing');
      }, 280);
    }
    return () => clearTimeout(timer);
  }, [phase, chars, word]);

  const displayWord = word.slice(0, chars);
  const showCaret = phase === 'typing' || phase === 'holding';
  const opacity = phase === 'fading' ? 0 : (phase === 'gap' ? 0 : 1);

  return (
    <section style={{
      minHeight: 'calc(100vh - 64px)',
      padding: '80px 40px 120px',
      position: 'relative', overflow: 'hidden',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
    }}>
      <DarkGhost top="6%" size="clamp(180px, 30vw, 420px)">APR</DarkGhost>
      <DarkGhost bottom="2%" size="clamp(130px, 20vw, 280px)" letterSpacing="0.06em">2026</DarkGhost>
      <div style={{ position: 'relative', zIndex: 2, textAlign: 'center' }}>
        <div style={{ fontSize: 10, letterSpacing: 3, color: D.inkMid, marginBottom: 32, textTransform: 'uppercase', fontWeight: 500 }}>journal</div>
        <div style={{
          position: 'relative', height: 'clamp(78px, 14vw, 170px)',
          display: 'flex', justifyContent: 'center', alignItems: 'center',
        }}>
          <div style={{
            fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
            fontSize: 'clamp(72px, 13vw, 160px)', lineHeight: 1, letterSpacing: '-0.01em',
            color: D.ink, whiteSpace: 'pre',
            opacity, transition: phase === 'fading' ? 'opacity 1.2s ease' : 'opacity 0s',
          }}>
            {displayWord}
            <span style={{
              display: 'inline-block', width: '0.06em', height: '0.85em',
              background: D.ink, verticalAlign: 'baseline',
              marginLeft: '0.04em',
              opacity: showCaret ? 1 : 0,
              animation: showCaret ? 'vapor-blink 0.9s steps(2, end) infinite' : 'none',
            }} />
          </div>
        </div>
        <div style={{ width: 24, height: 1, background: D.ruleStrong, margin: '32px auto' }} />
        <div style={{ fontSize: 11, letterSpacing: 3, textTransform: 'uppercase', color: D.inkMid }}>{COPY.heroTagline}</div>
        <div style={{ marginTop: 44, display: 'flex', justifyContent: 'center', gap: 14, flexWrap: 'wrap' }}>
          <AppStoreBadge height={54} />
          <PlayStoreBadge height={54} />
        </div>
        <div style={{ marginTop: 16, fontSize: 9, letterSpacing: 2.5, textTransform: 'uppercase', color: D.inkFaint }}>iPhone & android · free</div>
      </div>
      <style>{`
        @keyframes vapor-blink {
          0%, 50% { opacity: 1; }
          50.01%, 100% { opacity: 0; }
        }
      `}</style>
    </section>
  );
}

function DarkGhost({ top, bottom, size = 240, letterSpacing = '-0.02em', children }) {
  return (
    <div style={{
      position: 'absolute', top, bottom, left: '50%', transform: 'translateX(-50%)',
      fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 300, fontSize: size,
      color: D.inkGhost, lineHeight: 1, pointerEvents: 'none', userSelect: 'none',
      letterSpacing, whiteSpace: 'nowrap',
    }}>{children}</div>
  );
}

// ─────────────────────────────────────────────────────────────────
// ETHOS — the thesis as a slow carousel, witness-don't-amplify close
// ─────────────────────────────────────────────────────────────────
const ETHOS_FRAMES = [
  {
    kind: 'hero',
    label: 'the brand',
    title: 'show up.\nthat\u2019s the whole thing.',
    tagline: 'your day, distilled.',
  },
  {
    label: 'vapor',
    title: 'a journal that asks for\none word a day.',
    body:  'that\u2019s the entire ask. free. no accounts. no cloud. nothing leaves your phone.',
  },
  {
    label: 'who\u2019d love this',
    title: 'someone whose leather\njournal lives in a drawer.',
    paras: [
      'someone who\u2019s tried day one twice. someone who wants a small ritual without the pressure.',
      'people in transition. new parents. someone in the first year of sobriety. someone leaving a long job or relationship. one word is sometimes all you can manage. that\u2019s the whole feature.',
    ],
  },
  {
    label: 'mental health stance',
    title: 'witness,\ndon\u2019t amplify.',
    paras: [
      'vapor reflects your words back. for someone in crisis, that reflection can amplify rather than help. so the stance is non-clinical and privacy-preserving. no AI crisis detection. no content monitoring. no analytics.',
      'every phrase the app speaks back was audited line by line. phrases ending in finality were replaced with phrases ending in observation.',
    ],
  },
  {
    label: 'we know our limits',
    title: 'vapor is a mirror.\nmirrors aren\u2019t therapy.',
    paras: [
      'it doesn\u2019t read your words, doesn\u2019t try to detect when you\u2019re struggling, doesn\u2019t suggest a thing.',
      'what it does do: keep crisis resources one tap away in settings, for fifty countries, always offline.',
    ],
    closing: 'if you\u2019re going through something, please talk to someone real. that\u2019s what people are for.',
  },
];

function ViewEthos() {
  const [idx, setIdx] = React.useState(0);
  const [touched, setTouched] = React.useState(false);
  React.useEffect(() => {
    if (touched) return;
    const id = setInterval(() => setIdx((i) => (i + 1) % ETHOS_FRAMES.length), 9000);
    return () => clearInterval(id);
  }, [touched]);
  function nudge(d) { setTouched(true); setIdx((i) => (i + d + ETHOS_FRAMES.length) % ETHOS_FRAMES.length); }

  return (
    <section style={{ padding: '80px 40px 120px', minHeight: 'calc(100vh - 64px)' }}>
      <div style={{ maxWidth: 1000, margin: '0 auto', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 'clamp(16px, 4vw, 50px)' }}>
        <DarkArrow direction="left" onClick={() => nudge(-1)} />
        <div style={{ position: 'relative', textAlign: 'center', flex: '1 1 auto', minWidth: 0, minHeight: 'clamp(480px, 60vw, 540px)' }}>
          {ETHOS_FRAMES.map((fr, i) => {
            const active = i === idx;
            return (
              <div key={i} style={{
                position: 'absolute', inset: 0,
                display: 'flex', flexDirection: 'column', justifyContent: 'flex-start', alignItems: 'center',
                opacity: active ? 1 : 0, transform: `translateY(${active ? 0 : 10}px)`,
                transition: 'opacity 0.6s, transform 0.6s', pointerEvents: active ? 'auto' : 'none',
              }}>
                {fr.label && (
                  <div style={{ fontSize: 10, letterSpacing: 3, textTransform: 'uppercase', color: D.sage, marginBottom: 22, fontWeight: 500, whiteSpace: 'nowrap' }}>{fr.label}</div>
                )}
                <div className="big-title" style={{
                  fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
                  fontSize: 'clamp(32px, 5vw, 60px)', lineHeight: 1.12, color: D.ink,
                  marginBottom: fr.kind === 'hero' ? 30 : 36, whiteSpace: 'pre', letterSpacing: '-0.01em',
                }}>{fr.title}</div>
                {fr.kind === 'hero' && (
                  <div style={{ fontSize: 11, letterSpacing: 3, textTransform: 'uppercase', color: D.inkMid, fontWeight: 500 }}>{fr.tagline}</div>
                )}
                {fr.body && (
                  <div style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 15, lineHeight: 1.75, color: D.inkSoft, maxWidth: 520, margin: '0 auto' }}>{fr.body}</div>
                )}
                {fr.paras && fr.paras.map((p, pi) => (
                  <div key={pi} style={{
                    fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 15, lineHeight: 1.75,
                    color: D.inkSoft, maxWidth: 520, margin: pi === 0 ? '0 auto' : '18px auto 0',
                  }}>{p}</div>
                ))}
                {fr.closing && (
                  <div style={{
                    maxWidth: 520, margin: '32px auto 0', textAlign: 'left',
                    paddingLeft: 18, borderLeft: `1px solid ${D.sage}`,
                    fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400, fontSize: 17, lineHeight: 1.55,
                    color: D.sage,
                  }}>{fr.closing}</div>
                )}
              </div>
            );
          })}
        </div>
        <DarkArrow direction="right" onClick={() => nudge(1)} />
      </div>
      <div style={{ display: 'flex', justifyContent: 'center', gap: 8, marginTop: 44 }}>
        {ETHOS_FRAMES.map((_, i) => (
          <button key={i} onClick={() => { setTouched(true); setIdx(i); }} aria-label={`frame ${i+1}`} style={{
            border: 'none', cursor: 'pointer', padding: 0,
            width: i === idx ? 22 : 6, height: 6, borderRadius: 3,
            background: i === idx ? D.ink : 'rgba(232,226,217,0.22)',
            transition: 'all 0.35s',
          }} />
        ))}
      </div>
    </section>
  );
}

function DarkArrow({ direction, onClick }) {
  return (
    <button onClick={onClick} aria-label={direction} style={{
      flex: '0 0 auto', width: 44, height: 44, borderRadius: '50%',
      border: `0.5px solid ${D.rule}`, background: 'transparent', cursor: 'pointer',
      color: D.inkMid, display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'all 0.25s', padding: 0,
    }}
    onMouseOver={(e) => { e.currentTarget.style.color = D.ink; e.currentTarget.style.borderColor = D.ruleStrong; }}
    onMouseOut={(e) => { e.currentTarget.style.color = D.inkMid; e.currentTarget.style.borderColor = D.rule; }}>
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round">
        {direction === 'left' ? <path d="M9 2L4 7l5 5"/> : <path d="M5 2l5 5-5 5"/>}
      </svg>
    </button>
  );
}

// ─────────────────────────────────────────────────────────────────
// FEATURES — horizontal carousel of the 5 features
// ─────────────────────────────────────────────────────────────────
const FEATURE_SLIDES = [
  { key: 'today',    label: 'today',         title: 'write one word.\nclose the app.',           body: 'that\u2019s it. the rest is there if you want it - tap your word for its meaning, long-press to share, tap your streak to see what\u2019s accumulated. but you don\u2019t have to.' },
  { key: 'calendar', label: 'calendar',      title: 'your year,\nin your own handwriting.',      body: 'every word you\u2019ve written, one square per day, set in italic. older entries fade gently the further back they go. the closest vapor gets to a diary. and even then, still just words.' },
  { key: 'words',    label: 'words',         title: 'the words you\nreached for most.',          body: 'a cloud, a top ten, a 3d orbit you can share. patterns you didn\u2019t know were yours.' },
  { key: 'letters',  label: 'letters',       title: 'a word to your\nfuture self.',              body: 'seal it for a week, a month, a year. opens on the date you choose. not before.' },
  { key: 'soul',     label: 'soul weather',  title: 'a forecast for\nyour inner climate.',       body: 'fog burning off. frost overnight maybe. the storm not done. hand-written. no ai.' },
];

function ViewFeatures() {
  const [idx, setIdx] = React.useState(0);
  const [wordsView, setWordsView] = React.useState('orbit');
  const f = FEATURE_SLIDES[idx];
  function nudge(d) { setIdx((i) => (i + d + FEATURE_SLIDES.length) % FEATURE_SLIDES.length); }

  // keyboard nav
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'ArrowLeft') nudge(-1);
      if (e.key === 'ArrowRight') nudge(1);
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  return (
    <section style={{ padding: '60px 40px 100px', minHeight: 'calc(100vh - 64px)' }}>
      {/* feature counter + pager */}
      <div style={{ maxWidth: 1180, margin: '0 auto 48px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap' }} className="feature-header">
        <div style={{ fontSize: 10, letterSpacing: 3, color: D.inkMid, fontWeight: 500, textTransform: 'uppercase', flex: '0 0 auto' }}>
          <span style={{ color: D.sage }}>{String(idx + 1).padStart(2, '0')}</span>
          <span style={{ margin: '0 10px', color: D.inkFaint }}>/</span>
          <span>{String(FEATURE_SLIDES.length).padStart(2, '0')}</span>
          <span style={{ marginLeft: 20, color: D.inkFaint }}>feature</span>
        </div>
        <div className="feature-tabs" style={{ display: 'flex', gap: 6, alignItems: 'center', flexWrap: 'wrap' }}>
          {FEATURE_SLIDES.map((s, i) => (
            <button key={s.key} onClick={() => setIdx(i)} style={{
              border: 'none', cursor: 'pointer', padding: '6px 12px',
              background: 'transparent',
              fontFamily: VAPOR.sans, fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', fontWeight: 500,
              color: i === idx ? D.ink : D.inkFaint,
              transition: 'color 0.25s',
              borderBottom: i === idx ? `1px solid ${D.sage}` : '1px solid transparent',
              whiteSpace: 'nowrap',
            }}>{s.label}</button>
          ))}
        </div>
      </div>

      <div style={{ maxWidth: 1180, margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 60, alignItems: 'center', position: 'relative' }} className="features-grid">
        {/* COPY */}
        <div style={{ position: 'relative', minHeight: 460 }}>
          {FEATURE_SLIDES.map((slide, i) => (
            <div key={slide.key} style={{
              position: 'absolute', inset: 0,
              opacity: i === idx ? 1 : 0, transform: `translateY(${i === idx ? 0 : 12}px)`,
              transition: 'opacity 0.5s, transform 0.5s', pointerEvents: i === idx ? 'auto' : 'none',
              display: 'flex', flexDirection: 'column', justifyContent: 'center',
            }}>
              <div style={{ fontSize: 10, letterSpacing: 3, textTransform: 'uppercase', color: D.sage, marginBottom: 22, fontWeight: 500 }}>{slide.label}.</div>
              <div className="big-title" style={{
                fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
                fontSize: 'clamp(36px, 4.6vw, 60px)', lineHeight: 1.12, color: D.ink,
                marginBottom: 28, whiteSpace: 'pre', letterSpacing: '-0.01em',
              }}>{slide.title}</div>
              <div style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 15, lineHeight: 1.78, color: D.inkSoft, maxWidth: 420 }}>{slide.body}</div>

              {slide.key === 'words' && i === idx && (
                <div style={{ display: 'inline-flex', alignSelf: 'flex-start', marginTop: 28, padding: 4, borderRadius: 30, border: `0.5px solid ${D.rule}` }}>
                  {['orbit', 'cloud'].map((k) => (
                    <button key={k} onClick={() => setWordsView(k)} style={{
                      border: 'none', cursor: 'pointer',
                      background: wordsView === k ? D.ink : 'transparent',
                      color: wordsView === k ? D.bg : D.inkMid,
                      fontFamily: VAPOR.sans, fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', fontWeight: 600,
                      padding: '8px 18px', borderRadius: 30, transition: 'all 0.25s',
                    }}>{k}</button>
                  ))}
                </div>
              )}

              <div style={{ marginTop: 44, display: 'flex', gap: 14 }}>
                <DarkArrow direction="left" onClick={() => nudge(-1)} />
                <DarkArrow direction="right" onClick={() => nudge(1)} />
              </div>
            </div>
          ))}
        </div>

        {/* PHONE */}
        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', position: 'relative', minHeight: 560 }}>
          <div style={{ width: 390 * 0.62, height: 844 * 0.62, position: 'relative' }}>
            <PhoneShell scale={0.62}>
              <FeaturePhone slide={f.key} wordsView={wordsView} />
            </PhoneShell>
          </div>
        </div>
      </div>

      <style>{`
        @media (max-width: 820px) {
          .features-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
        }
        @media (max-width: 600px) {
          .big-title { white-space: pre-line !important; }
        }
        @media (max-width: 520px) {
          .feature-tabs { width: 100%; justify-content: flex-start; gap: 2px !important; }
          .feature-tabs button { padding: 6px 8px !important; font-size: 9.5px !important; letter-spacing: 1.5px !important; }
        }
      `}</style>
    </section>
  );
}

function FeaturePhone({ slide, wordsView }) {
  return (
    <div style={{ width: 390, height: 844, position: 'relative', overflow: 'hidden', background: VAPOR.sand }}>
      <div style={{ position: 'absolute', inset: 0, transition: 'opacity 0.45s', opacity: slide === 'today' ? 1 : 0 }}>
        {slide === 'today' && <TodayScreen />}
      </div>
      <div style={{ position: 'absolute', inset: 0, transition: 'opacity 0.45s', opacity: slide === 'calendar' ? 1 : 0 }}>
        {slide === 'calendar' && <CalendarFeatureScreen />}
      </div>
      <div style={{ position: 'absolute', inset: 0, transition: 'opacity 0.45s', opacity: slide === 'words' ? 1 : 0 }}>
        {slide === 'words' && <WordsFeatureScreen view={wordsView} />}
      </div>
      <div style={{ position: 'absolute', inset: 0, transition: 'opacity 0.45s', opacity: slide === 'letters' ? 1 : 0 }}>
        {slide === 'letters' && <LettersFeatureScreen />}
      </div>
      <div style={{ position: 'absolute', inset: 0, transition: 'opacity 0.45s', opacity: slide === 'soul' ? 1 : 0 }}>
        {slide === 'soul' && <SoulFeatureScreen />}
      </div>
    </div>
  );
}

function CalendarFeatureScreen() {
  return (
    <div style={{ width: 390, height: 844, background: VAPOR.sand, position: 'relative' }}>
      <div style={{ position: 'absolute', top: 60, left: 0, right: 0, textAlign: 'center', zIndex: 3 }}>
        <div style={{ fontSize: 11, letterSpacing: 3, color: 'rgba(26,28,25,0.45)', fontWeight: 500 }}>CALENDAR</div>
        <div style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 24, color: VAPOR.green, marginTop: 10 }}>every day, one word</div>
        <div style={{ width: 22, height: 1, background: 'rgba(26,28,25,0.25)', margin: '14px auto 0' }} />
      </div>
      <div style={{ paddingTop: 200, paddingLeft: 28, paddingRight: 28 }}>
        <CalendarMini width={334} />
      </div>
      <TabBar active="calendar" />
    </div>
  );
}

function WordsFeatureScreen({ view = 'orbit' }) {
  return (
    <div style={{ width: 390, height: 844, background: VAPOR.sand, position: 'relative' }}>
      <div style={{ position: 'absolute', top: 60, left: 0, right: 0, textAlign: 'center', zIndex: 3 }}>
        <div style={{ fontSize: 11, letterSpacing: 3, color: 'rgba(26,28,25,0.45)', fontWeight: 500 }}>WORDS</div>
        <div style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 24, color: VAPOR.green, marginTop: 10 }}>every feeling you&apos;ve felt</div>
        <div style={{ width: 22, height: 1, background: 'rgba(26,28,25,0.25)', margin: '14px auto 0' }} />
      </div>
      <div style={{ position: 'absolute', top: 200, left: 0, right: 0, display: 'flex', borderBottom: '0.5px solid rgba(26,28,25,0.12)', zIndex: 3 }}>
        <div style={{ flex: 1, textAlign: 'center', padding: '14px 0', fontSize: 12, letterSpacing: 2, fontWeight: view === 'cloud' ? 600 : 500, color: view === 'cloud' ? VAPOR.green : 'rgba(26,28,25,0.45)', borderBottom: view === 'cloud' ? `2px solid ${VAPOR.green}` : '2px solid transparent', transition: 'all 0.3s' }}>CLOUD</div>
        <div style={{ flex: 1, textAlign: 'center', padding: '14px 0', fontSize: 12, letterSpacing: 2, fontWeight: view === 'orbit' ? 600 : 500, color: view === 'orbit' ? VAPOR.green : 'rgba(26,28,25,0.45)', borderBottom: view === 'orbit' ? `2px solid ${VAPOR.green}` : '2px solid transparent', transition: 'all 0.3s' }}>ORBIT</div>
      </div>
      <div style={{ position: 'absolute', top: 250, left: 0, right: 0, bottom: 100, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', opacity: view === 'orbit' ? 1 : 0, transition: 'opacity 0.4s' }}>
          <WordOrbit width={340} height={420} />
        </div>
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', opacity: view === 'cloud' ? 1 : 0, transition: 'opacity 0.4s' }}>
          <FeatWordCloud />
        </div>
      </div>
      <TabBar active="words" />
    </div>
  );
}

function FeatWordCloud() {
  const cloud = [
    { w: 'healing', s: 30, x: 50, y: 46, c: VAPOR.green },
    { w: 'tired', s: 22, x: 26, y: 28, c: VAPOR.ink },
    { w: 'hopeful', s: 26, x: 72, y: 24, c: VAPOR.green },
    { w: 'open', s: 20, x: 30, y: 62, c: VAPOR.ink },
    { w: 'pensive', s: 17, x: 78, y: 58, c: VAPOR.ink, op: 0.55 },
    { w: 'soft', s: 15, x: 18, y: 48, c: VAPOR.green, op: 0.7 },
    { w: 'still', s: 18, x: 60, y: 70, c: VAPOR.ink, op: 0.7 },
    { w: 'tender', s: 16, x: 82, y: 40, c: VAPOR.green, op: 0.7 },
    { w: 'grateful', s: 19, x: 50, y: 18, c: VAPOR.ink, op: 0.75 },
    { w: 'lifting', s: 17, x: 42, y: 78, c: VAPOR.green, op: 0.7 },
    { w: 'anxious', s: 14, x: 14, y: 70, c: VAPOR.ink, op: 0.45 },
    { w: 'clear', s: 15, x: 70, y: 84, c: VAPOR.ink, op: 0.55 },
    { w: 'alive', s: 13, x: 86, y: 72, c: VAPOR.green, op: 0.6 },
    { w: 'brave', s: 14, x: 60, y: 36, c: VAPOR.green, op: 0.65 },
    { w: 'lonely', s: 12, x: 12, y: 18, c: VAPOR.ink, op: 0.4 },
  ];
  return (
    <div style={{ position: 'relative', width: 340, height: 380 }}>
      {cloud.map((w, i) => (
        <span key={i} style={{
          position: 'absolute', left: `${w.x}%`, top: `${w.y}%`, transform: 'translate(-50%,-50%)',
          fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
          fontSize: w.s, color: w.c, opacity: w.op != null ? w.op : 1, whiteSpace: 'nowrap',
        }}>{w.w}</span>
      ))}
    </div>
  );
}

function LettersFeatureScreen() {
  return (
    <div style={{ width: 390, height: 844, background: VAPOR.sand, position: 'relative' }}>
      <div style={{ position: 'absolute', top: 60, left: 0, right: 0, textAlign: 'center', zIndex: 3 }}>
        <div style={{ fontSize: 11, letterSpacing: 3, color: 'rgba(26,28,25,0.45)', fontWeight: 500 }}>LETTERS</div>
        <div style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 24, color: VAPOR.green, marginTop: 10 }}>to your future self</div>
        <div style={{ width: 22, height: 1, background: 'rgba(26,28,25,0.25)', margin: '14px auto 24px' }} />
      </div>
      <div style={{ position: 'absolute', top: 200, left: 28, right: 28 }}>
        <LetterStack width={334} />
      </div>
      <TabBar active="letters" />
    </div>
  );
}

function SoulFeatureScreen() {
  return (
    <div style={{ width: 390, height: 844, background: VAPOR.sand, position: 'relative', overflow: 'hidden' }}>
      <div style={{ position: 'absolute', inset: 0 }}>
        <SoulWeatherDrift width={390} height={844} count={16} />
      </div>
      <div style={{ position: 'absolute', top: 60, left: 0, right: 0, textAlign: 'center', zIndex: 3 }}>
        <div style={{ fontSize: 11, letterSpacing: 3, color: 'rgba(26,28,25,0.45)', fontWeight: 500 }}>SOUL WEATHER</div>
        <div style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 24, color: VAPOR.green, marginTop: 10 }}>your inner weather</div>
        <div style={{ width: 22, height: 1, background: 'rgba(26,28,25,0.25)', margin: '14px auto 0' }} />
      </div>
      <div style={{ position: 'absolute', top: 380, left: 0, right: 0, textAlign: 'center', zIndex: 3 }}>
        <div style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 40, color: VAPOR.ink, lineHeight: 1.1 }}>sun returning,<br/>slowly</div>
        <div style={{ marginTop: 14, fontSize: 10, letterSpacing: 2.5, color: 'rgba(26,28,25,0.5)', fontWeight: 500 }}>TODAY&apos;S FORECAST</div>
      </div>
      <TabBar active="today" />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────
// RESEARCH — "the weight of words"
// ─────────────────────────────────────────────────────────────────
const RESEARCH_SOURCES = [
  { cite: 'Warriner, A. B., Kuperman, V., & Brysbaert, M. (2013). Norms of valence, arousal, and dominance for 13,915 English lemmas.', pub: 'Behavior Research Methods, 45(4), 1191\u20131207.', note: 'Gold-standard English affective norm dataset. Primary calibration source for the \u201310 to +10 scale.' },
  { cite: 'Mohammad, S. (2018). Obtaining reliable human ratings of valence, arousal, and dominance for 20,000 English words.', pub: 'Proceedings of the Annual Conference of the Association for Computational Linguistics (ACL).', note: 'The NRC VAD Lexicon v1. Cross-validated against warriner where both contain a given word. Feeds the 60/40 hybrid.' },
  { cite: 'Mohammad, S. (2025). NRC VAD Lexicon v2: Norms for valence, arousal, and dominance for over 55k English terms.', pub: 'arXiv:2503.23547.', note: 'Expanded VAD norms including multi-word expressions. Used for coverage extension only \u2014 its 7-point likert methodology differs from v1 and is excluded from the hybrid.' },
  { cite: 'Bradley, M. M., & Lang, P. J. (1999). Affective Norms for English Words (ANEW).', pub: 'Technical Report C-1, CSEA, University of Florida.', note: 'Methodological precursor to warriner and NRC VAD.' },
  { cite: 'Mohammad, S. M., & Turney, P. D. (2013). Crowdsourcing a word-emotion association lexicon.', pub: 'Computational Intelligence, 29(3), 436\u2013465.', note: 'The NRC Emotion Lexicon (EmoLex). Categorical sanity check against the dimensional scoring.' },
  { cite: 'Mohammad, S. (2018). Word affect intensities.', pub: 'Proceedings of the 11th Language Resources and Evaluation Conference (LREC).', note: 'Informed the band-extreme tuning at the \u20139/\u201310 and +9/+10 cells.' },
  { cite: 'Zhao, X., He, X., & Zhang, W. (2016). A heavy heart: The association between weight and emotional words.', pub: 'Frontiers in Psychology, 7:920.', note: 'Empirical support for the body-state amplification rule. Heavy, light, tight, open, hollow weighted higher than their literal norm value. Amplification constant is editorial.' },
  { cite: 'Schrauf, R. W., & S\u00e1nchez, J. (2004). The preponderance of negative emotion words in the emotion lexicon: A cross-generational and cross-linguistic study.', pub: 'Journal of Multilingual and Multicultural Development, 25(2-3), 266\u2013284.', note: 'Confirmed the ~50% negative / ~30% positive / ~20% neutral asymmetry. Shaped soul weather\u2019s dictionary distribution.' },
  { cite: 'Stevenson, R. A., Mikels, J. A., & James, T. W. (2007). Characterization of the Affective Norms for English Words by discrete emotional categories.', pub: 'Behavior Research Methods, 39(4), 1020\u20131024.', note: 'Cross-referenced for category coherence.' },
];

function ViewResearch() {
  return (
    <section style={{ padding: '60px 40px 120px', minHeight: 'calc(100vh - 64px)' }}>
      <div style={{ maxWidth: 980, margin: '0 auto' }}>
        {/* header */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingBottom: 18, marginBottom: 38, borderBottom: `0.5px solid ${D.rule}` }}>
          <span style={{ width: 7, height: 7, borderRadius: '50%', background: D.sage }} />
          <span style={{ fontSize: 10, letterSpacing: 3, textTransform: 'uppercase', color: D.inkMid, fontWeight: 500 }}>Research</span>
          <span style={{ flex: 1 }} />
          <span style={{ fontSize: 10, letterSpacing: 2.5, textTransform: 'uppercase', color: D.inkFaint }}>soul weather · lexicon</span>
        </div>

        {/* hero */}
        <div style={{ marginBottom: 56 }}>
          <h1 style={{
            fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
            fontSize: 'clamp(48px, 7vw, 96px)', lineHeight: 1.08, color: D.ink,
            letterSpacing: '-0.01em', marginBottom: 28,
          }}>the weight<br/>of words.</h1>
          <p style={{
            fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
            fontSize: 'clamp(20px, 2.2vw, 26px)', lineHeight: 1.4, color: D.inkSoft,
            maxWidth: '32ch', marginBottom: 28,
          }}>every word has a temperature. every phrase the app speaks back was written by hand.</p>
          <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 15, lineHeight: 1.78, color: D.inkSoft, maxWidth: '64ch' }}>
            soul weather is the affect-classification engine inside vapor journal. its classifier and word-weight dictionary were calibrated against peer-reviewed psycholinguistic norms. the phrase library is hand-written line by line. no machine learning in the classifier or scoring layer.
          </p>
        </div>

        {/* stats */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 1, background: D.rule, border: `0.5px solid ${D.rule}`, marginBottom: 72 }} className="research-stats-grid">
          <Stat n="~250"    label="classifier stems" />
          <Stat n="~1,500"  label={<>weighted words<br/>−10 to +10</>} />
          <Stat n="9"       label="peer-reviewed sources" />
        </div>

        {/* methodology */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 64, alignItems: 'start', marginBottom: 72 }} className="research-body-grid">
          <div>
            <h3 style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 26, color: D.ink, marginBottom: 18 }}>methodology, in brief.</h3>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 18 }}>
              words present in both warriner and the original NRC VAD (mohammad 2018) receive a hybrid weight. the split is 60% NRC VAD, 40% warriner, a calibration we settled on after auditing roughly 60 cross-source disagreements.
            </p>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 18 }}>
              NRC VAD v1 uses best&ndash;worst scaling, which is more reliable than direct rating; warriner has the larger sample and longer citation history. neither dominated cleanly, so the hybrid leans toward methodology while keeping warriner&rsquo;s coverage breadth in the mix. words present in only one source take that source&rsquo;s value.
            </p>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 18 }}>
              NRC VAD v2 (mohammad 2025) is used to extend coverage into multi-word expressions. v2 switched from best&ndash;worst scaling to a 7-point likert scale, so it sits outside the 60/40 hybrid and is used for coverage only.
            </p>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 18 }}>
              body-state words (heavy, light, tight, open, hollow) receive +1 to +2 amplification. this is informed by zhao et al. (2016), who showed weight perception and emotional word judgment are linked in priming experiments. the amplification value itself is editorial.
            </p>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 18 }}>
              australian and british colloquial vocabulary (knackered, chuffed, rapt, gutted) is hand-tagged from thesaurus synonyms - mapped to their nearest US-english neighbours, since those terms don&rsquo;t appear in US-english norm databases.
            </p>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft }}>
              crime and violence terms are excluded regardless of their norm valence. they aren&rsquo;t emotional self-descriptions a daily journal user writes about themselves.
            </p>
          </div>
          <div>
            <h3 style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 26, color: D.ink, marginBottom: 18 }}>the phrase audit.</h3>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 18 }}>
              the soul weather phrase library was authored separately and audited line by line for a <strong style={{ color: D.ink, fontWeight: 500 }}>&ldquo;witness, don&rsquo;t amplify&rdquo;</strong> principle.
            </p>
            <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14.5, lineHeight: 1.78, color: D.inkSoft, marginBottom: 24 }}>
              phrases ending in finality (&ldquo;no end to it,&rdquo; &ldquo;no break ever&rdquo;) were replaced with phrases ending in observation (&ldquo;the wind, ongoing,&rdquo; &ldquo;weather, still moving&rdquo;).
            </p>
            <blockquote style={{
              fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 22, lineHeight: 1.35, color: D.sage,
              borderLeft: `1px solid ${D.sage}`, paddingLeft: 18, maxWidth: '32ch',
            }}>witness,<br/>don&rsquo;t amplify.</blockquote>
          </div>
        </div>

        {/* sources */}
        <div style={{ marginBottom: 56 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', paddingBottom: 18, marginBottom: 32, borderBottom: `0.5px solid ${D.rule}` }}>
            <h3 style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 26, color: D.ink }}>sources cited.</h3>
            <span style={{ fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 22, color: D.inkMid }}>{RESEARCH_SOURCES.length}</span>
          </div>
          <ol style={{ listStyle: 'none', counterReset: 'bib', display: 'flex', flexDirection: 'column', gap: 22 }}>
            {RESEARCH_SOURCES.map((s, i) => (
              <li key={i} style={{ position: 'relative', paddingLeft: 36 }}>
                <span style={{
                  position: 'absolute', left: 0, top: 1, width: 24, textAlign: 'right',
                  fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 15, color: D.sage,
                }}>{i + 1}</span>
                <div style={{ fontFamily: VAPOR.sans, fontWeight: 400, fontSize: 13.5, lineHeight: 1.55, color: D.ink }}>
                  {s.cite} <span style={{ fontStyle: 'italic', fontWeight: 300, color: D.inkSoft }}>{s.pub}</span>
                </div>
                <div style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 13, lineHeight: 1.55, color: D.inkMid, marginTop: 4 }}>{s.note}</div>
              </li>
            ))}
          </ol>
        </div>

        {/* foot */}
        <div style={{ paddingTop: 28, borderTop: `0.5px solid ${D.rule}` }}>
          <p style={{ fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 14, lineHeight: 1.75, color: D.inkSoft, maxWidth: '64ch' }}>
            the full word-weight dictionary, including bucket-cutoff calibration against the warriner distribution and a 60-word sanity-check audit, is available on request for academic review. email{' '}
            <a href="mailto:hello@vaporjournal.app" style={{ color: D.sage, textDecoration: 'none', borderBottom: `0.5px solid rgba(126,168,130,0.4)` }}>hello@vaporjournal.app</a>.
          </p>
        </div>
      </div>

      <style>{`
        @media (max-width: 820px) {
          .research-stats-grid { grid-template-columns: 1fr !important; }
          .research-body-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
        }
      `}</style>
    </section>
  );
}

function Stat({ n, label }) {
  return (
    <div style={{ background: D.bg, padding: '36px 28px' }}>
      <div style={{
        fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
        fontSize: 'clamp(46px, 5vw, 72px)', lineHeight: 1, color: D.ink, letterSpacing: '-0.02em',
      }}>{n}</div>
      <div style={{ fontFamily: VAPOR.sans, fontSize: 10, fontWeight: 500, letterSpacing: 3, textTransform: 'uppercase', color: D.inkMid, marginTop: 14, lineHeight: 1.6 }}>{label}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────
// FAQ — questions + Android wait-list
// ─────────────────────────────────────────────────────────────────
const FAQ = [
  { q: 'is this therapy?',
    a: 'no. vapor is a mirror. mirrors aren\u2019t therapy. it doesn\u2019t read your words, doesn\u2019t try to detect when you\u2019re struggling, doesn\u2019t suggest a thing. if you\u2019re going through something, please talk to someone real. that\u2019s what people are for.' },
  { q: 'is it on android?',
    a: <>yes. out now on <a href={PLAY_STORE_URL} target="_blank" rel="noopener noreferrer" style={{ color: D.sage, textDecoration: 'none', borderBottom: `0.5px solid rgba(126,168,130,0.4)` }}>google play</a>. iPhone version on the <a href={APP_STORE_URL} target="_blank" rel="noopener noreferrer" style={{ color: D.sage, textDecoration: 'none', borderBottom: `0.5px solid rgba(126,168,130,0.4)` }}>app store</a>. feature parity at launch.</> },
  { q: 'do you use AI?',
    a: 'no. no AI prompts. no coach. no conversation engine. no crisis detection. every phrase the app speaks back was written by hand and audited line by line.' },
  { q: 'where does my data go?',
    a: 'nowhere. it stays on your phone. no cloud. no sync. no accounts. no analytics. no third-party data SDKs in the binary. apple\u2019s privacy manifest declares \u201cdata not collected.\u201d' },
  { q: 'what if i miss a day?',
    a: 'your streak resets. that\u2019s the honest answer. but the counter is past tense by design - \u201cyou\u2019ve shown up X times in a row\u201d - and there\u2019s no broken-streak shame, no panic ping, no notification badge waiting for you. every day you missed is still in your calendar, blank, exactly as it happened. show up again tomorrow.' },
  { q: 'can i export my entries?',
    a: 'yes. CSV export, every entry, anytime, free. delete-all is one tap in settings.' },
  { q: 'is it free?',
    a: 'yes. all features today. a premium tier is planned for later in 2026 - the core ritual (write one word a day, see it back) will remain free forever. there will never be ads.' },
  { q: 'what\u2019s coming?',
    a: <>
      <span>premium tier later in 2026 - depth tools for people who\u2019ve been writing a while. then more languages, beyond the six the dictionary already speaks. </span>
      <span>updates land in the app store notes - <a href="https://substack.com/@zacharydegit" target="_blank" rel="noopener noreferrer" style={{ color: D.sage, textDecoration: 'none', borderBottom: `0.5px solid rgba(126,168,130,0.4)` }}>zac writes occasionally on substack</a> if you want the long version.</span>
    </> },
  { q: 'who made this?',
    a: <>built solo in melbourne by zac de git. he reads every email. reach him at <a href="mailto:hello@vaporjournal.app" style={{ color: D.sage, textDecoration: 'none', borderBottom: `0.5px solid rgba(126,168,130,0.4)` }}>hello@vaporjournal.app</a>.</> },
];

function ViewFaq() {
  return (
    <section style={{ padding: '60px 40px 120px', minHeight: 'calc(100vh - 64px)' }}>
      <div style={{ maxWidth: 780, margin: '0 auto' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingBottom: 18, marginBottom: 38, borderBottom: `0.5px solid ${D.rule}` }}>
          <span style={{ width: 7, height: 7, borderRadius: '50%', background: D.sage }} />
          <span style={{ fontSize: 10, letterSpacing: 3, textTransform: 'uppercase', color: D.inkMid, fontWeight: 500 }}>FAQ</span>
        </div>
        <h1 style={{
          fontFamily: VAPOR.serif, fontStyle: 'italic', fontWeight: 400,
          fontSize: 'clamp(44px, 6vw, 80px)', lineHeight: 1.08, color: D.ink, letterSpacing: '-0.01em', marginBottom: 48,
        }}>questions,<br/>plainly answered.</h1>

        <div style={{ display: 'flex', flexDirection: 'column' }}>
          {FAQ.map((item, i) => (
            <FaqRow key={i} q={item.q} a={item.a} hasForm={item.form} first={i === 0} />
          ))}
        </div>

        <p style={{
          marginTop: 64, fontFamily: VAPOR.serif, fontStyle: 'italic',
          fontSize: 14, lineHeight: 1.7, color: D.inkMid, maxWidth: '60ch',
        }}>{COPY.honest}</p>
      </div>
    </section>
  );
}

function FaqRow({ q, a, hasForm, first }) {
  const [open, setOpen] = React.useState(first);
  return (
    <div style={{ borderTop: `0.5px solid ${D.rule}`, padding: '22px 0' }}>
      <button onClick={() => setOpen(o => !o)} style={{
        all: 'unset', cursor: 'pointer', display: 'flex', alignItems: 'baseline', justifyContent: 'space-between',
        width: '100%', gap: 24, boxSizing: 'border-box',
      }}>
        <div style={{ flex: 1, fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 'clamp(20px, 2.3vw, 26px)', color: D.ink, lineHeight: 1.3, textAlign: 'left' }}>{q}</div>
        <div style={{
          fontFamily: VAPOR.serif, fontStyle: 'italic', fontSize: 22, color: open ? D.sage : D.inkMid,
          transition: 'color 0.25s, transform 0.35s', transform: open ? 'rotate(45deg)' : 'rotate(0deg)',
          flex: '0 0 auto', width: 22, height: 22, display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>+</div>
      </button>
      <div style={{
        overflow: 'hidden', maxHeight: open ? 1000 : 0,
        transition: 'max-height 0.5s ease', opacity: open ? 1 : 0,
      }}>
        <div style={{
          paddingTop: 14, fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 15, lineHeight: 1.78,
          color: D.inkSoft, maxWidth: '60ch',
        }}>{a}</div>
        {hasForm && <AndroidWaitlist />}
      </div>
    </div>
  );
}

function AndroidWaitlist() {
  const [state, setState] = React.useState('idle');
  const inputRef = React.useRef(null);
  function handleSubmit(e) {
    e.preventDefault();
    const email = (inputRef.current && inputRef.current.value || '').trim();
    if (!email || !email.includes('@')) return;
    if (typeof window.emailjs === 'undefined') { setState('ok'); return; }
    setState('sending');
    window.emailjs.send('service_nt36efb', 'template_1podhnn', {
      from_email: email,
      created_at: new Date().toLocaleString('en-AU', { timeZone: 'Australia/Melbourne' }),
    }).then(() => setState('ok')).catch(() => setState('err'));
  }
  return (
    <div style={{ marginTop: 22, maxWidth: 460 }}>
      {state === 'ok' ? (
        <div style={{ fontFamily: VAPOR.sans, fontSize: 11, letterSpacing: 2.5, textTransform: 'uppercase', color: D.sage, padding: '14px 0' }}>you&apos;re on the list.</div>
      ) : (
        <form onSubmit={handleSubmit} style={{ display: 'flex' }}>
          <input ref={inputRef} type="email" required placeholder="your@email.com" disabled={state === 'sending'} style={{
            flex: 1, background: 'rgba(255,255,255,0.04)', border: `0.5px solid ${D.rule}`, borderRight: 'none',
            borderRadius: '50px 0 0 50px', padding: '12px 20px',
            fontFamily: VAPOR.sans, fontWeight: 300, fontSize: 13, color: D.ink, outline: 'none', letterSpacing: 0.5,
          }} />
          <button type="submit" disabled={state === 'sending'} style={{
            background: D.ink, color: D.bg, border: 'none', borderRadius: '0 50px 50px 0',
            padding: '12px 22px', fontFamily: VAPOR.sans, fontWeight: 500, fontSize: 10, letterSpacing: 2, textTransform: 'uppercase',
            cursor: state === 'sending' ? 'default' : 'pointer', opacity: state === 'sending' ? 0.7 : 1,
          }}>{state === 'sending' ? '…' : state === 'err' ? 'try again' : 'notify me'}</button>
        </form>
      )}
      <div style={{ marginTop: 12, fontSize: 10, lineHeight: 1.7, color: D.inkFaint }}>
        we&apos;ll only email you about vapor. no spam.{' '}
        <a href="unsubscribe.html" style={{ color: D.inkMid, textDecoration: 'none', borderBottom: `0.5px solid ${D.rule}` }}>unsubscribe</a>{' '}any time.
      </div>
    </div>
  );
}

// expose
Object.assign(window, { D, ViewStill, ViewEthos, ViewFeatures, ViewResearch, ViewFaq });
