// screens-member.jsx — member-facing phone screens for BHCAC Attendance
// All screens are bilingual (EN + 中文). Designed for a 402×874 iPhone canvas.

const { useState, useEffect, useMemo } = React;

const D = window.BHCAC_DATA;

// ─────────────────────────────────────────────────────────────
// Screen 1: WELCOME — sign-in
// Mobile: dark hero with form on top.
// Desktop (≥ 768px): two-column — hero panel left, sign-in card right.
// onSignIn(user) is called with the authenticated user object.
// ─────────────────────────────────────────────────────────────
function useIsDesktop(breakpoint = 768) {
  const [match, setMatch] = useState(typeof window !== 'undefined' && window.innerWidth >= breakpoint);
  useEffect(() => {
    if (typeof window === 'undefined' || !window.matchMedia) return;
    const mql = window.matchMedia(`(min-width: ${breakpoint}px)`);
    const handler = (e) => setMatch(e.matches);
    setMatch(mql.matches);
    // Safari < 14 / older Android only support the deprecated addListener API.
    // Using addEventListener unconditionally throws there and blanks the page.
    if (typeof mql.addEventListener === 'function') {
      mql.addEventListener('change', handler);
      return () => mql.removeEventListener('change', handler);
    }
    if (typeof mql.addListener === 'function') {
      mql.addListener(handler);
      return () => mql.removeListener(handler);
    }
  }, [breakpoint]);
  return match;
}

function ScreenWelcome({ onSignIn }) {
  const AUTH = window.BHCAC_AUTH;
  const isDesktop = useIsDesktop();
  const [mode, setMode] = useState('login');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [name, setName] = useState('');
  const [zh, setZh] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const supportsPasskey = !!(AUTH && AUTH.browserSupportsPasskeys && AUTH.browserSupportsPasskeys());

  const submit = async (e) => {
    e?.preventDefault?.();
    setError(null); setSubmitting(true);
    try {
      const user = mode === 'register'
        ? await AUTH.register({ email, password, en: name, zh })
        : await AUTH.login({ email, password });
      onSignIn(user);
    } catch (err) {
      setError(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  const passkey = async () => {
    setError(null); setSubmitting(true);
    try {
      const user = await AUTH.loginWithPasskey({ email: email || undefined });
      onSignIn(user);
    } catch (err) {
      setError(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  const formState = {
    mode, setMode, email, setEmail, password, setPassword,
    name, setName, zh, setZh, submitting, error, setError,
    submit, passkey, supportsPasskey,
  };

  return isDesktop
    ? <DesktopWelcome {...formState} />
    : <MobileWelcome {...formState} />;
}

// --- Mobile sign-in (full-bleed dark hero) ---
function MobileWelcome(p) {
  const inputStyle = {
    width: '100%', boxSizing: 'border-box',
    padding: '13px 16px',
    borderRadius: 12,
    border: '1px solid rgba(255,255,255,0.18)',
    background: 'rgba(255,255,255,0.08)',
    color: '#fff', fontSize: 15, fontFamily: 'Inter, sans-serif',
    outline: 'none',
  };
  return (
    <div style={{
      height: '100%', position: 'relative', overflow: 'hidden',
      background: 'var(--brand-navy)', color: '#fff',
      display: 'flex', flexDirection: 'column',
    }}>
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'url("assets/cc-event-1.jpg")',
        backgroundSize: 'cover', backgroundPosition: 'center',
        opacity: 0.35,
      }} />
      <div style={{
        position: 'absolute', inset: 0,
        background: 'linear-gradient(to bottom, rgba(15,23,42,0.5) 0%, rgba(15,23,42,0.92) 55%, var(--brand-navy) 100%)',
      }} />

      <div style={{
        position: 'relative', zIndex: 2,
        height: '100%', overflowY: 'auto',
        display: 'flex', flexDirection: 'column',
        padding: 'max(40px, env(safe-area-inset-top, 28px)) 26px 28px',
      }}>
        <BrandRow dark />
        <FormHeader dark mode={p.mode} />
        <SigninForm dark inputStyle={inputStyle} {...p} />
        <div style={{
          marginTop: 24, fontSize: 11, color: 'rgba(255,255,255,0.45)', textAlign: 'center',
          fontFamily: "'Noto Sans TC', Inter, sans-serif",
          paddingTop: 14, borderTop: '1px solid rgba(255,255,255,0.08)',
        }}>
          2/4 Gladstone Rd, Castle Hill · 國語 9:15 · 粵語 11:00 · 英語 4:30
        </div>
      </div>
    </div>
  );
}

// --- Desktop sign-in (split-screen hero + form card) ---
function DesktopWelcome(p) {
  const inputStyle = {
    width: '100%', boxSizing: 'border-box',
    padding: '13px 16px',
    borderRadius: 12,
    border: '1px solid var(--border-strong)',
    background: 'var(--bg-1)',
    color: 'var(--fg-1)', fontSize: 15, fontFamily: 'Inter, sans-serif',
    outline: 'none',
    transition: 'border-color 150ms, box-shadow 150ms',
  };
  return (
    <div style={{
      height: '100%', display: 'grid',
      gridTemplateColumns: 'minmax(420px, 1fr) minmax(440px, 1fr)',
      background: 'var(--bg-1)',
    }}>
      {/* Left — pastoral hero */}
      <div style={{
        position: 'relative', overflow: 'hidden',
        background: 'var(--brand-navy)', color: '#fff',
        display: 'flex', flexDirection: 'column',
      }}>
        <div style={{
          position: 'absolute', inset: 0,
          backgroundImage: 'url("assets/congregation.jpg")',
          backgroundSize: 'cover', backgroundPosition: 'center',
          opacity: 0.45,
        }} />
        <div style={{
          position: 'absolute', inset: 0,
          background: 'linear-gradient(135deg, rgba(15,23,42,0.55) 0%, rgba(15,23,42,0.9) 65%, rgba(15,23,42,0.95) 100%)',
        }} />
        <div style={{
          position: 'relative', zIndex: 2,
          flex: 1, display: 'flex', flexDirection: 'column',
          padding: '48px 56px',
        }}>
          <BrandRow dark large />

          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', maxWidth: 520 }}>
            <Eyebrow color="var(--coral-400)" style={{ marginBottom: 16 }}>BHCAC · ATTENDANCE</Eyebrow>
            <h1 style={{
              fontSize: 'clamp(40px, 5vw, 64px)', fontWeight: 700, lineHeight: 1.05,
              letterSpacing: '-0.025em', margin: 0,
            }}>
              You are<br/>welcome here.
            </h1>
            <div style={{
              fontFamily: "'Noto Sans TC', sans-serif", fontSize: 'clamp(22px, 2.4vw, 30px)',
              fontWeight: 600, color: 'rgba(255,255,255,0.85)',
              marginTop: 12, lineHeight: 1.3,
            }}>
              歡迎來到迦南堂
            </div>
            <p style={{
              fontSize: 17, color: 'rgba(255,255,255,0.78)', lineHeight: 1.55,
              marginTop: 24, maxWidth: 460,
            }}>
              One app for the whole congregation — sign in to check your family in,
              register a visitor, or follow this Sunday's services.
            </p>
            <p style={{
              fontFamily: "'Noto Sans TC', sans-serif", fontSize: 14,
              color: 'rgba(255,255,255,0.55)', lineHeight: 1.6,
              marginTop: 14, maxWidth: 460,
            }}>
              一個應用程式，服侍全會眾 — 登入即可代家人簽到、登記新朋友，或了解本主日的崇拜安排。
            </p>
          </div>

          <div style={{
            display: 'flex', gap: 24, flexWrap: 'wrap',
            paddingTop: 24, borderTop: '1px solid rgba(255,255,255,0.1)',
            fontSize: 13, color: 'rgba(255,255,255,0.7)',
          }}>
            <ServiceTime time="9:15"  label="Mandarin · 國語" />
            <ServiceTime time="11:00" label="Cantonese · 粵語" />
            <ServiceTime time="4:30"  label="One Hope · 英語" />
            <div style={{ marginLeft: 'auto', alignSelf: 'flex-end', textAlign: 'right' }}>
              2/4 Gladstone Rd<br/>Castle Hill NSW
            </div>
          </div>
        </div>
      </div>

      {/* Right — form card */}
      <div style={{
        background: 'var(--bg-1)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        padding: '40px 48px', overflowY: 'auto',
      }}>
        <div style={{ width: '100%', maxWidth: 400 }}>
          <FormHeader mode={p.mode} />
          <SigninForm inputStyle={inputStyle} {...p} />
          <p style={{
            marginTop: 28, fontSize: 11, color: 'var(--fg-3)',
            lineHeight: 1.55, fontFamily: "'Noto Sans TC', Inter, sans-serif",
            paddingTop: 18, borderTop: '1px solid var(--border-subtle)',
          }}>
            By signing in you agree to BHCAC handling your information under the Australian Privacy Principles.
            <br/>本會將遵行澳洲保護個人私隱條例處理閣下資料。
          </p>
        </div>
      </div>
    </div>
  );
}

function BrandRow({ dark, large }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
      <img src="assets/bhcac-logo-red.jpg" style={{
        width: large ? 48 : 40, height: large ? 48 : 40,
        borderRadius: '50%', objectFit: 'cover',
        boxShadow: dark ? '0 0 0 2px rgba(255,255,255,0.15)' : '0 0 0 1px var(--border-subtle)',
      }} />
      <div>
        <div style={{ fontSize: large ? 18 : 15, fontWeight: 700, letterSpacing: '-0.01em', color: dark ? '#fff' : 'var(--fg-1)' }}>BHCAC</div>
        <div style={{
          fontSize: large ? 11 : 10, fontWeight: 500, letterSpacing: '0.12em',
          color: dark ? 'rgba(255,255,255,0.7)' : 'var(--fg-3)',
        }}>迦南堂 · ATTENDANCE</div>
      </div>
    </div>
  );
}

function FormHeader({ dark, mode }) {
  const fg = dark ? '#fff' : 'var(--fg-1)';
  const fgMuted = dark ? 'rgba(255,255,255,0.85)' : 'var(--fg-3)';
  return (
    <div style={{ marginTop: dark ? 28 : 0, marginBottom: 24 }}>
      <Eyebrow color={dark ? 'var(--coral-400)' : 'var(--brand-coral)'} style={{ marginBottom: 10 }}>
        {mode === 'register' ? 'Create account · 建立帳戶' : 'Sign in · 登入'}
      </Eyebrow>
      <h2 style={{ fontSize: 28, fontWeight: 700, lineHeight: 1.15, letterSpacing: '-0.02em', margin: 0, color: fg }}>
        {mode === 'register' ? 'Welcome — let’s set you up.' : 'Welcome back.'}
      </h2>
      <div style={{
        fontFamily: "'Noto Sans TC', sans-serif", fontSize: 15, fontWeight: 500,
        color: fgMuted, marginTop: 6,
      }}>
        {mode === 'register' ? '歡迎，請建立您的帳戶' : '請登入以繼續'}
      </div>
    </div>
  );
}

function SigninForm({ dark, inputStyle, mode, setMode, email, setEmail, password, setPassword,
                     name, setName, zh, setZh, submitting, error, setError, submit, passkey, supportsPasskey }) {
  const dividerColor = dark ? 'rgba(255,255,255,0.1)' : 'var(--border-subtle)';
  const dividerText  = dark ? 'rgba(255,255,255,0.45)' : 'var(--fg-3)';
  const passkeyBtn = dark ? {
    background: 'rgba(255,255,255,0.08)', color: '#fff',
    border: '1px solid rgba(255,255,255,0.25)', backdropFilter: 'blur(8px)',
  } : {
    background: 'var(--bg-1)', color: 'var(--fg-1)',
    border: '1px solid var(--border-strong)',
  };
  const linkColor = dark ? 'var(--coral-400)' : 'var(--brand-coral)';
  const linkMuted = dark ? 'rgba(255,255,255,0.6)' : 'var(--fg-3)';

  return (
    <>
      <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {mode === 'register' && (
          <>
            <input style={inputStyle} type="text" placeholder="Your name · 姓名"
              value={name} onChange={e => setName(e.target.value)} required />
            <input style={inputStyle} type="text" placeholder="中文姓名 (optional)"
              value={zh} onChange={e => setZh(e.target.value)} />
          </>
        )}
        <input style={inputStyle} type="email" placeholder="Email · 電郵"
          value={email} onChange={e => setEmail(e.target.value)} required autoComplete="email" />
        <input style={inputStyle} type="password" placeholder="Password · 密碼"
          value={password} onChange={e => setPassword(e.target.value)} required
          autoComplete={mode === 'register' ? 'new-password' : 'current-password'}
          minLength={mode === 'register' ? 8 : undefined} />

        {error && (
          <div style={{
            fontSize: 13, color: dark ? '#fecaca' : 'var(--coral-700)',
            background: dark ? 'rgba(244,63,94,0.18)' : 'var(--coral-100)',
            border: dark ? '1px solid rgba(244,63,94,0.4)' : '1px solid rgba(244,63,94,0.3)',
            borderRadius: 10, padding: '10px 12px',
          }}>{error}</div>
        )}

        <button type="submit" disabled={submitting} style={{
          marginTop: 6, padding: '14px 22px',
          background: 'var(--brand-coral)', color: '#fff',
          border: 'none', borderRadius: 9999,
          fontSize: 15, fontWeight: 700, cursor: submitting ? 'wait' : 'pointer',
          fontFamily: 'Inter, sans-serif',
          opacity: submitting ? 0.7 : 1,
          boxShadow: '0 6px 16px -6px rgba(244,63,94,0.6)',
        }}>
          {submitting ? '…' : (mode === 'register' ? 'Create account · 建立帳戶' : 'Sign in · 登入')}
        </button>
      </form>

      {supportsPasskey && (
        <>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 10,
            margin: '20px 0', color: dividerText, fontSize: 11, fontWeight: 600,
            letterSpacing: '0.1em', textTransform: 'uppercase',
          }}>
            <div style={{ flex: 1, height: 1, background: dividerColor }} />
            or · 或
            <div style={{ flex: 1, height: 1, background: dividerColor }} />
          </div>
          <button type="button" onClick={passkey} disabled={submitting} style={{
            width: '100%',
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10,
            padding: '13px 22px', borderRadius: 9999,
            fontSize: 15, fontWeight: 600, cursor: submitting ? 'wait' : 'pointer',
            fontFamily: 'Inter, sans-serif',
            ...passkeyBtn,
          }}>
            <Icon name="key" size={18} />
            <span>Continue with passkey · 通行密鑰</span>
          </button>
        </>
      )}

      <div style={{ marginTop: 22, textAlign: 'center', fontSize: 13 }}>
        {mode === 'register' ? (
          <>
            <span style={{ color: linkMuted }}>Already have an account? </span>
            <button type="button" onClick={() => { setError(null); setMode('login'); }}
              style={{ color: linkColor, background: 'transparent', border: 'none', fontWeight: 600, cursor: 'pointer', fontSize: 13 }}>
              Sign in · 登入
            </button>
          </>
        ) : (
          <>
            <span style={{ color: linkMuted }}>New to BHCAC? </span>
            <button type="button" onClick={() => { setError(null); setMode('register'); }}
              style={{ color: linkColor, background: 'transparent', border: 'none', fontWeight: 600, cursor: 'pointer', fontSize: 13 }}>
              Create account · 建立帳戶
            </button>
          </>
        )}
      </div>
    </>
  );
}

function ServiceTime({ time, label }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <div style={{ fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em', color: '#fff' }}>{time}</div>
      <div style={{ fontSize: 12, fontFamily: "'Noto Sans TC', sans-serif", color: 'rgba(255,255,255,0.65)' }}>{label}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Screen 2: TODAY (member home)
// ─────────────────────────────────────────────────────────────
function computeRecentSundays(user, checkIns) {
  const today = new Date();
  const todaySunday = new Date(today);
  if (todaySunday.getDay() !== 0) {
    todaySunday.setDate(todaySunday.getDate() - todaySunday.getDay());
  }
  const items = [];
  for (let i = 4; i >= 0; i--) {
    const d = new Date(todaySunday);
    d.setDate(d.getDate() - i * 7);
    items.push(d);
  }
  const memberIdSet = new Set([user?.id, user?.authUserId, user?.memberId].filter(Boolean));
  const userDates = new Set(
    (checkIns || []).filter(c => memberIdSet.has(c.member_id)).map(c => c.date)
  );
  const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  return items.map(d => {
    const dateStr = d.toISOString().slice(0, 10);
    const isToday = d.toDateString() === new Date().toDateString();
    const isThisSunday = d.toDateString() === todaySunday.toDateString();
    return {
      date: dateStr,
      label: (isToday || isThisSunday) ? 'Today' : `${d.getDate()} ${months[d.getMonth()]}`,
      here: userDates.has(dateStr),
      today: isToday || isThisSunday,
    };
  });
}

function greetingFor(d) {
  const h = d.getHours();
  if (h < 12) return 'Good morning';
  if (h < 17) return 'Good afternoon';
  return 'Good evening';
}

// Sydney timezone helpers — services are scheduled in local time, so we
// compare everything in Australia/Sydney rather than UTC.
function todayDateInSydney(now = new Date()) {
  return new Intl.DateTimeFormat('en-CA', { timeZone: 'Australia/Sydney' }).format(now);
}
function nowMinutesInSydney(now = new Date()) {
  const fmt = new Intl.DateTimeFormat('en-GB', { timeZone: 'Australia/Sydney', hour: '2-digit', minute: '2-digit', hour12: false });
  const [hh, mm] = fmt.format(now).split(':').map(Number);
  return hh * 60 + mm;
}
function parseServiceTimeMinutes(timeStr) {
  if (!timeStr) return null;
  const m = String(timeStr).match(/(\d{1,2}):(\d{2})\s*(AM|PM)?/i);
  if (!m) return null;
  let h = parseInt(m[1]);
  const min = parseInt(m[2]);
  const ap = (m[3] || '').toUpperCase();
  if (ap === 'PM' && h < 12) h += 12;
  if (ap === 'AM' && h === 12) h = 0;
  return h * 60 + min;
}
// Default window: opens 60 min before service, stays open 180 min after.
function checkinWindow(serviceTime, now = new Date(), beforeMin = 60, afterMin = 180) {
  const eventMin = parseServiceTimeMinutes(serviceTime);
  if (eventMin == null) return { state: 'unknown', open: true };
  const nowMin = nowMinutesInSydney(now);
  const opensAt = eventMin - beforeMin;
  const closesAt = eventMin + afterMin;
  if (nowMin < opensAt) return { state: 'too-early', open: false, opensAt, eventMin };
  if (nowMin > closesAt) return { state: 'too-late', open: false, closesAt, eventMin };
  return { state: 'open', open: true, eventMin };
}
function formatHM(totalMinutes) {
  if (totalMinutes == null) return '';
  const h24 = Math.floor(totalMinutes / 60);
  const m = totalMinutes % 60;
  const ap = h24 >= 12 ? 'PM' : 'AM';
  const h12 = h24 === 0 ? 12 : h24 > 12 ? h24 - 12 : h24;
  return `${h12}:${String(m).padStart(2, '0')} ${ap}`;
}
function formatTodayLabel(date = new Date()) {
  const days = ['SUN','MON','TUE','WED','THU','FRI','SAT'];
  const months = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'];
  const dayName = days[date.getDay()] === 'SUN' ? 'SUNDAY' : days[date.getDay()];
  const isSunday = date.getDay() === 0;
  return `${dayName} · ${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}${isSunday ? ' · 主日' : ''}`;
}

function ScreenToday({ user, family, members, events = [], congregations = [], checkIns, onCheckIn, onOpenAdmin, onOpenSettings, onSignOut, onAddPasskey }) {
  const today = todayDateInSydney();
  const familyMembers = members.filter(m => family && m.family === family.id);
  const hasFamily = familyMembers.length > 0;
  const roster = hasFamily
    ? familyMembers
    : (user?.id ? [members.find(m => m.id === user.id) || user].filter(Boolean) : []);
  const checkedInIds = new Set(checkIns.filter(c => c.date === today).map(c => c.member_id));
  const rosterCheckedCount = roster.filter(m => checkedInIds.has(m.id)).length;
  const allRosterChecked = roster.length > 0 && rosterCheckedCount === roster.length;

  // Congregations represented across the roster
  const congList = congregations.length > 0 ? congregations : (D.congregations || []);
  const rosterCongregationIds = [...new Set(roster.map(m => m.congregation))];
  // Events scheduled for today (i.e., a Sunday recurring event or a special
  // event whose date matches today). The user's congregation must appear on
  // at least one of them for check-in to be available.
  const todayEvents = events.filter(e => e.date === today);
  const myCongregation = congList.find(s => s.id === user?.congregation);
  const myEventToday = todayEvents.find(e =>
    Array.isArray(e.congregations) && e.congregations.includes(user?.congregation));
  const eventTime = myEventToday?.time || myCongregation?.defaultTime;
  const myWindow = myEventToday
    ? checkinWindow(eventTime)
    : { state: 'no-service', open: false };
  const checkinAllowed = myWindow.open;

  return (
    <div className="today-root" style={{ height: '100%', overflowY: 'auto', background: 'var(--bg-2)' }}>
      {/* Header — solid navy so the headline always reads cleanly */}
      <div className="today-hero" style={{
        background: 'linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f766e 120%)',
        color: '#fff',
        padding: '52px 24px 48px',
        position: 'relative',
      }}>
        <div className="today-hero-inner">
          <div className="mobile-only" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 28 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <img src="assets/bhcac-logo-red.jpg" style={{ width: 32, height: 32, borderRadius: '50%', objectFit: 'cover' }} />
              <div>
                <div style={{ fontSize: 13, fontWeight: 700, letterSpacing: '-0.01em' }}>BHCAC</div>
                <div style={{ fontSize: 10, color: 'rgba(255,255,255,0.65)', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Attendance</div>
              </div>
            </div>
            <CircleBtn icon="user" onClick={onOpenSettings} dark />
          </div>

          <Eyebrow color="var(--coral-400)" className="hero-eyebrow" style={{ marginBottom: 8 }}>
            {formatTodayLabel()}
          </Eyebrow>
          <h1 style={{ fontSize: 'clamp(28px, 3vw, 36px)', fontWeight: 700, letterSpacing: '-0.02em', margin: 0, lineHeight: 1.15, color: '#fff' }}>
            {greetingFor(new Date())}, {user.en.split(' ')[0]}.
          </h1>
          {user.zh && (
            <div style={{ fontFamily: "'Noto Sans TC', sans-serif", fontSize: 16, color: 'rgba(255,255,255,0.78)', marginTop: 6 }}>
              {user.zh}，主日平安。
            </div>
          )}
        </div>
      </div>

      <div className="today-body">
        <div className="today-main">

      {/* Floating family check-in card */}
      <div className="floating-card" style={{ padding: '0 16px', marginTop: -36, position: 'relative', zIndex: 5 }}>
        <Card padding={0} accent={allRosterChecked ? 'var(--brand-teal)' : 'var(--brand-coral)'} style={{ overflow: 'hidden' }}>
          <div style={{ padding: '20px 20px 16px' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 16 }}>
              <div>
                <Eyebrow color={allRosterChecked ? 'var(--teal-700)' : 'var(--brand-coral)'} style={{ marginBottom: 6 }}>
                  {hasFamily ? `Your Family · 您的家庭` : 'Your Check-in · 您的簽到'}
                </Eyebrow>
                <h3 style={{ fontSize: 20, fontWeight: 700, letterSpacing: '-0.015em', margin: 0 }}>
                  {hasFamily ? family.en : user.en}
                </h3>
                {hasFamily && (
                  <div style={{ fontSize: 13, color: 'var(--fg-3)', fontFamily: "'Noto Sans TC', sans-serif", marginTop: 2 }}>{family.zh}</div>
                )}
              </div>
              {allRosterChecked && (
                <Pill tone="success" icon="check">All Here · 全到</Pill>
              )}
            </div>

            {/* Member chips */}
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 14 }}>
              {familyMembers.map(m => {
                const checked = checkedInIds.has(m.id);
                return (
                  <div key={m.id} style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    padding: '6px 12px 6px 6px',
                    background: checked ? 'rgba(13,148,136,0.08)' : 'var(--bg-2)',
                    borderRadius: 9999,
                    border: `1px solid ${checked ? 'rgba(13,148,136,0.2)' : 'var(--border-subtle)'}`,
                  }}>
                    <Avatar member={m} size={26} />
                    <div style={{ fontSize: 13, fontWeight: 600 }}>{m.en.split(' ')[0]}</div>
                    {checked && <Icon name="check" size={13} color="var(--teal-700)" strokeWidth={3} style={{ marginRight: 2 }} />}
                  </div>
                );
              })}
            </div>

            {!allRosterChecked ? (
              <Btn variant="primary" full size="lg" trailingIcon={checkinAllowed ? 'arrow-right' : null}
                disabled={!checkinAllowed} onClick={() => checkinAllowed && onCheckIn()}>
                {checkinAllowed
                  ? `Check in${hasFamily ? ` ${roster.length - rosterCheckedCount}${rosterCheckedCount > 0 ? ' more' : ''}` : ''} · 簽到`
                  : myWindow.state === 'too-early'
                    ? `Opens at ${formatHM(myWindow.opensAt)} · 簽到尚未開放`
                    : myWindow.state === 'too-late'
                      ? 'Closed for today · 今日簽到已結束'
                      : myWindow.state === 'no-service'
                        ? 'No service today · 今日沒有聚會'
                        : 'Check in · 簽到'}
              </Btn>
            ) : (
              <Btn variant="outline" full size="md" icon="edit" onClick={() => onCheckIn()}>
                Edit check-in · 修改簽到
              </Btn>
            )}
            {myWindow.state === 'too-early' && eventTime && (
              <div style={{ fontSize: 12, color: 'var(--fg-3)', textAlign: 'center', marginTop: 8, lineHeight: 1.5 }}>
                {myEventToday?.en || myCongregation?.en} starts at {eventTime}.<br/>
                Check-in opens 1 hour before · 崇拜開始前一小時開放簽到
              </div>
            )}
            {myWindow.state === 'no-service' && (
              <div style={{ fontSize: 12, color: 'var(--fg-3)', textAlign: 'center', marginTop: 8, lineHeight: 1.5 }}>
                There's no service scheduled for today.<br/>
                Next: {(() => {
                  const next = events.filter(e => e.date > today && e.congregations?.includes(user?.congregation))[0];
                  return next ? `${next.en} · ${next.date} ${next.time || ''}` : 'TBA';
                })()}
              </div>
            )}
          </div>

          {/* Congregation times row */}
          {rosterCongregationIds.length > 0 && (
            <div style={{
              background: 'var(--bg-2)', padding: '12px 20px',
              display: 'flex', flexDirection: 'column', gap: 8,
              borderTop: '1px solid var(--border-subtle)',
            }}>
              {rosterCongregationIds.map(cid => {
                const s = congList.find(x => x.id === cid);
                if (!s) return null;
                const w = checkinWindow(s.defaultTime);
                return (
                  <div key={cid} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13, flexWrap: 'wrap' }}>
                    <Icon name="clock" size={14} color={`var(--brand-${s.accent})`} />
                    <span style={{ fontWeight: 600 }}>{s.defaultTime}</span>
                    <span style={{ color: 'var(--fg-3)' }}>·</span>
                    <span>{s.en}</span>
                    {s.zh && <span style={{ color: 'var(--fg-3)', fontFamily: "'Noto Sans TC', sans-serif" }}>· {s.zh}</span>}
                    {w.state === 'open' && <Pill tone="success" style={{ fontSize: 9, padding: '2px 7px' }}>OPEN</Pill>}
                  </div>
                );
              })}
            </div>
          )}
        </Card>
      </div>
        </div>{/* /.today-main */}
        <div className="today-side">

      {/* This week's events */}
      {events.length > 0 && (
        <div style={{ padding: '32px 16px 16px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12, padding: '0 4px' }}>
            <div>
              <Eyebrow style={{ marginBottom: 4 }}>This Week · 本週</Eyebrow>
              <h2 style={{ fontSize: 20, fontWeight: 700, letterSpacing: '-0.015em', margin: 0 }}>Special events</h2>
            </div>
          </div>
          <div className="events-strip" style={{ display: 'flex', gap: 12, overflowX: 'auto', padding: '4px 4px 12px', margin: '0 -4px', scrollSnapType: 'x mandatory' }}>
            {events.slice(0, 3).map((e, i) => (
              <EventCard key={e.id || i} event={e}
                accent={['var(--brand-coral)', 'var(--brand-teal)', 'var(--brand-navy)'][i % 3]} />
            ))}
          </div>
        </div>
      )}

      {/* History strip — real data, hidden when there's nothing yet */}
      {(() => {
        const recent = computeRecentSundays(user, checkIns);
        const hasAnyHistory = recent.some(s => s.here);
        if (!hasAnyHistory) return null;
        const past4 = recent.slice(0, 4);
        const attended = past4.filter(s => s.here).length;
        return (
          <div style={{ padding: '8px 16px 24px' }}>
            <div style={{ marginBottom: 12, padding: '0 4px' }}>
              <Eyebrow style={{ marginBottom: 4 }}>Your Journey · 您的旅程</Eyebrow>
              <h2 style={{ fontSize: 20, fontWeight: 700, letterSpacing: '-0.015em', margin: 0 }}>Recent Sundays</h2>
            </div>
            <Card padding={16}>
              <div style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'flex-end', height: 70, marginBottom: 12 }}>
                {recent.map((w, i) => (
                  <div key={w.date} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, flex: 1 }}>
                    <div style={{
                      width: 36, height: w.here ? 50 : 14,
                      borderRadius: 6,
                      background: w.today ? 'repeating-linear-gradient(45deg, var(--coral-100), var(--coral-100) 4px, #fff 4px, #fff 8px)' :
                                  w.here ? 'var(--brand-coral)' : 'var(--border-subtle)',
                      border: w.today ? '1.5px dashed var(--brand-coral)' : 'none',
                    }} />
                    <div style={{ fontSize: 10, fontWeight: 600, color: w.today ? 'var(--brand-coral)' : 'var(--fg-3)', letterSpacing: '0.02em' }}>
                      {w.label}
                    </div>
                  </div>
                ))}
              </div>
              <div style={{ fontSize: 13, color: 'var(--fg-2)', textAlign: 'center', borderTop: '1px solid var(--border-subtle)', paddingTop: 12 }}>
                <span style={{ fontWeight: 600, color: 'var(--brand-navy)' }}>{attended} of {past4.length} Sundays</span> attended this past month · 過去{past4.length}週出席{attended}次
              </div>
            </Card>
          </div>
        );
      })()}

      {/* Set up passkey (if signed-in user has none yet) */}
      {onAddPasskey && (user.passkeyCount === 0 || user.passkeyCount === undefined) && user.authUserId && (
        <div style={{ padding: '0 16px 12px' }}>
          <Card padding={16} interactive onClick={onAddPasskey} accent="var(--brand-teal)">
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <div style={{ width: 40, height: 40, borderRadius: 10, background: 'rgba(13,148,136,0.12)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon name="key" size={20} color="var(--teal-700)" />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 700 }}>Skip the password next time · 設定通行密鑰</div>
                <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>Add a passkey to this device</div>
              </div>
              <Icon name="chevron-right" size={18} color="var(--fg-3)" />
            </div>
          </Card>
        </div>
      )}

      {/* Footer admin link (if user is admin) */}
      {user.isAdmin && (
        <div style={{ padding: '0 16px 24px' }}>
          <Card padding={16} interactive onClick={onOpenAdmin} style={{ background: 'var(--brand-navy)', color: '#fff', border: 'none' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <div style={{ width: 40, height: 40, borderRadius: 10, background: 'rgba(244,63,94,0.2)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon name="settings" size={20} color="#fff" />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 14, fontWeight: 700 }}>Admin tools · 管理員工具</div>
                <div style={{ fontSize: 12, color: 'rgba(255,255,255,0.65)' }}>Members, events, reports</div>
              </div>
              <Icon name="chevron-right" size={18} color="rgba(255,255,255,0.5)" />
            </div>
          </Card>
        </div>
      )}

      <div style={{ height: 40 }} />
        </div>{/* /.today-side */}
      </div>{/* /.today-body */}
    </div>
  );
}

function CircleBtn({ icon, onClick, dark, badge }) {
  return (
    <button onClick={onClick} style={{
      width: 40, height: 40, borderRadius: '50%',
      background: dark ? 'rgba(255,255,255,0.12)' : 'var(--bg-1)',
      border: dark ? '1px solid rgba(255,255,255,0.2)' : '1px solid var(--border-subtle)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      cursor: 'pointer', position: 'relative',
      backdropFilter: dark ? 'blur(8px)' : 'none',
    }}>
      <Icon name={icon} size={18} color={dark ? '#fff' : 'var(--brand-navy)'} />
      {badge != null && (
        <div style={{
          position: 'absolute', top: -2, right: -2,
          background: 'var(--brand-coral)', color: '#fff',
          fontSize: 9, fontWeight: 700, padding: '2px 5px',
          borderRadius: 9999, minWidth: 16, height: 16,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: '0 0 0 2px var(--brand-navy)',
        }}>{badge}</div>
      )}
    </button>
  );
}

function EventCard({ event, accent, image, registered }) {
  if (!event) return null;
  const date = event.date || '';
  const month = date.slice(5, 7);
  const day = date.slice(8, 10);
  const monthLabel = ({ '01':'JAN','02':'FEB','03':'MAR','04':'APR','05':'MAY','06':'JUN','07':'JUL','08':'AUG','09':'SEP','10':'OCT','11':'NOV','12':'DEC' })[month] || '';
  const reg = event.registered || 0;
  const cap = event.capacity || 0;
  const pct = cap > 0 ? Math.min(100, (reg / cap) * 100) : 0;
  return (
    <div style={{
      flexShrink: 0, width: 220, scrollSnapAlign: 'start',
      borderRadius: 'var(--radius-xl)', overflow: 'hidden',
      background: 'var(--bg-1)',
      boxShadow: 'var(--shadow-md)',
      border: '1px solid var(--border-subtle)',
    }}>
      <div style={{
        height: 100,
        background: image ? `linear-gradient(180deg, transparent, rgba(15,23,42,0.5)), url("${image}")` : `linear-gradient(135deg, ${accent}, color-mix(in oklab, ${accent} 70%, white))`,
        backgroundSize: 'cover', backgroundPosition: 'center',
        position: 'relative',
      }}>
        <div style={{ position: 'absolute', top: 10, left: 10 }}>
          <Pill tone={registered ? 'success' : 'navy'} icon={registered ? 'check' : 'calendar'} style={{ background: 'rgba(255,255,255,0.95)' }}>
            {registered ? 'Registered' : (day && monthLabel ? `${day} ${monthLabel}` : 'Soon')}
          </Pill>
        </div>
      </div>
      <div style={{ padding: 14 }}>
        <div style={{ fontSize: 14, fontWeight: 700, lineHeight: 1.2, letterSpacing: '-0.01em' }}>{event.en || 'Event'}</div>
        {event.zh && <div style={{ fontSize: 12, color: 'var(--fg-3)', fontFamily: "'Noto Sans TC', sans-serif", marginTop: 2 }}>{event.zh}</div>}
        {event.time && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 4, marginTop: 6, fontSize: 12, fontWeight: 600, color: 'var(--brand-navy)' }}>
            <Icon name="clock" size={12} color="var(--fg-3)" />
            <span>{event.time}</span>
          </div>
        )}
        {cap > 0 && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 10, fontSize: 11, color: 'var(--fg-3)' }}>
            <Icon name="users" size={12} />
            <span>{reg}/{cap}</span>
            <div style={{ flex: 1, height: 4, background: 'var(--border-subtle)', borderRadius: 4, marginLeft: 4 }}>
              <div style={{ width: `${pct}%`, height: '100%', background: accent, borderRadius: 4 }}/>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Screen 3: CHECK-IN — pick who's here
// ─────────────────────────────────────────────────────────────
function ScreenCheckIn({ user, family, members, congregations = [], checkIns, onConfirm, onBack }) {
  const today = todayDateInSydney();
  // Roster = the family members if family exists, otherwise just the user.
  // Make sure the user themselves is always present (handles solo accounts).
  const rosterRaw = family
    ? members.filter(m => m.family === family.id)
    : [];
  const userMember = members.find(m => m.id === user?.id) || (user?.id ? user : null);
  const roster = userMember && !rosterRaw.some(m => m.id === userMember.id)
    ? [userMember, ...rosterRaw]
    : rosterRaw;
  const hasFamily = !!family && rosterRaw.length > 0;

  const checkedInIds = new Set(checkIns.filter(c => c.date === today).map(c => c.member_id));
  const [selected, setSelected] = useState(() => new Set(roster.filter(m => !checkedInIds.has(m.id)).map(m => m.id)));
  const congList = congregations.length > 0 ? congregations : (D.congregations || []);

  const toggle = (id) => {
    const s = new Set(selected);
    if (s.has(id)) s.delete(id); else s.add(id);
    setSelected(s);
  };

  const rosterLabel = hasFamily
    ? `${family.en}${family.zh ? ' · ' + family.zh : ''}`
    : 'Just me · 您自己';

  return (
    <div className="focused-screen" style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-2)' }}>
      {/* Header */}
      <div style={{ padding: '60px 20px 16px', background: 'var(--bg-1)', borderBottom: '1px solid var(--border-subtle)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
          <CircleBtn icon="chevron-left" onClick={onBack} />
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg-3)' }}>Step 1 of 2</div>
          <div style={{ width: 40 }} />
        </div>
        <Eyebrow style={{ marginBottom: 6 }}>Check In · 簽到</Eyebrow>
        <h1 style={{ fontSize: 26, fontWeight: 700, letterSpacing: '-0.02em', margin: 0, lineHeight: 1.15 }}>Who's here today?</h1>
        <div style={{ fontFamily: "'Noto Sans TC', sans-serif", fontSize: 16, color: 'var(--fg-3)', marginTop: 4 }}>誰來了？</div>
      </div>

      {/* List */}
      <div style={{ flex: 1, overflowY: 'auto', padding: '20px 16px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12, padding: '0 4px' }}>
          <Eyebrow color="var(--brand-teal)">{rosterLabel}</Eyebrow>
          {roster.length > 1 && (
            <button
              onClick={() => setSelected(new Set(roster.map(m => m.id)))}
              style={{ fontSize: 12, fontWeight: 600, color: 'var(--brand-teal)', background: 'transparent', border: 'none', cursor: 'pointer' }}>
              Select all
            </button>
          )}
        </div>

        <Card padding={0}>
          {roster.map((m, i) => {
            const wasChecked = checkedInIds.has(m.id);
            const isSelected = selected.has(m.id);
            const cong = congList.find(s => s.id === m.congregation);
            return (
              <div key={m.id}
                onClick={() => !wasChecked && toggle(m.id)}
                style={{
                  display: 'flex', alignItems: 'center', gap: 14,
                  padding: '14px 18px',
                  borderBottom: i < roster.length - 1 ? '1px solid var(--border-subtle)' : 'none',
                  cursor: wasChecked ? 'default' : 'pointer',
                  background: isSelected && !wasChecked ? 'rgba(244,63,94,0.04)' : 'transparent',
                  opacity: wasChecked ? 0.6 : 1,
                }}>
                <Avatar member={m} size={44} />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 15, fontWeight: 700, letterSpacing: '-0.01em' }}>{m.en}</div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, color: 'var(--fg-3)', marginTop: 2 }}>
                    {m.zh && <><span style={{ fontFamily: "'Noto Sans TC', sans-serif" }}>{m.zh}</span><span>·</span></>}
                    <span>{cong ? `${cong.en} · ${cong.defaultTime}` : '—'}</span>
                  </div>
                </div>
                <div style={{
                  width: 28, height: 28, borderRadius: '50%',
                  background: wasChecked ? 'var(--brand-teal)' : isSelected ? 'var(--brand-coral)' : 'transparent',
                  border: wasChecked ? 'none' : isSelected ? 'none' : '2px solid var(--border-strong)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  transition: 'all 200ms var(--ease-out)',
                }}>
                  {(isSelected || wasChecked) && <Icon name="check" size={16} color="#fff" strokeWidth={3.5} />}
                </div>
              </div>
            );
          })}
        </Card>

        {/* Add other person */}
        <button style={{
          marginTop: 12, width: '100%',
          background: 'transparent', border: '1.5px dashed var(--border-strong)',
          borderRadius: 'var(--radius-xl)', padding: '14px',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          fontSize: 14, fontWeight: 600, color: 'var(--brand-navy)',
          cursor: 'pointer',
        }}>
          <Icon name="plus" size={16} /> Add someone with us · 加入新朋友
        </button>

        {/* Info */}
        <div style={{ marginTop: 20, padding: '14px 16px', background: 'var(--brand-warm)', borderRadius: 'var(--radius-lg)', display: 'flex', gap: 10 }}>
          <Icon name="heart" size={16} color="var(--brand-coral)" style={{ marginTop: 2, flexShrink: 0 }} />
          <div style={{ fontSize: 12.5, color: '#7c2d12', lineHeight: 1.45 }}>
            Children's Sunday School at 11:00 takes place upstairs. Drop-off opens 10 minutes early.
            <span style={{ display: 'block', fontFamily: "'Noto Sans TC', sans-serif", color: '#9a3412', marginTop: 2 }}>兒童主日學在樓上，11:00 開始；提前 10 分鐘可送到。</span>
          </div>
        </div>
      </div>

      {/* Sticky CTA */}
      <div style={{ padding: '12px 16px 28px', background: 'var(--bg-1)', borderTop: '1px solid var(--border-subtle)', boxShadow: '0 -10px 20px rgba(15,23,42,0.04)' }}>
        <Btn variant="primary" full size="lg" trailingIcon="arrow-right"
          disabled={selected.size === 0}
          onClick={() => onConfirm([...selected])}>
          Check in {selected.size} {selected.size === 1 ? 'person' : 'people'} · 確認簽到
        </Btn>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Screen 4: CONFIRMATION
// ─────────────────────────────────────────────────────────────
function ScreenConfirm({ family, members, justCheckedIds, onDone }) {
  const justChecked = members.filter(m => justCheckedIds.includes(m.id));
  const kids = justChecked.filter(m => m.age < 13);

  return (
    <div className="focused-screen" style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-2)' }}>
      {/* Top hero */}
      <div style={{
        padding: '70px 24px 40px', textAlign: 'center',
        background: 'linear-gradient(180deg, var(--brand-teal) 0%, #0a7569 100%)',
        color: '#fff', position: 'relative', overflow: 'hidden',
      }}>
        <div style={{
          position: 'absolute', inset: 0,
          backgroundImage: 'radial-gradient(circle at 30% 20%, rgba(255,255,255,0.15), transparent 50%), radial-gradient(circle at 70% 80%, rgba(255,255,255,0.1), transparent 50%)',
        }} />
        <div style={{ position: 'relative', zIndex: 2 }}>
          <div style={{
            width: 80, height: 80, borderRadius: '50%',
            background: 'rgba(255,255,255,0.18)', backdropFilter: 'blur(8px)',
            border: '1px solid rgba(255,255,255,0.3)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            margin: '0 auto 20px',
          }}>
            <Icon name="check" size={42} strokeWidth={3} color="#fff" />
          </div>
          <h1 style={{ fontSize: 32, fontWeight: 700, letterSpacing: '-0.02em', margin: 0, lineHeight: 1.1 }}>
            You're all set.
          </h1>
          <div style={{ fontFamily: "'Noto Sans TC', sans-serif", fontSize: 22, color: 'rgba(255,255,255,0.9)', marginTop: 8, fontWeight: 600 }}>
            簽到完成。
          </div>
          <p style={{ fontSize: 14, color: 'rgba(255,255,255,0.8)', marginTop: 14, maxWidth: 280, marginLeft: 'auto', marginRight: 'auto', lineHeight: 1.5 }}>
            Welcome, {family.en}. We're so glad you're here today.
          </p>
        </div>
      </div>

      {/* Summary card */}
      <div style={{ padding: '0 16px', marginTop: -20, position: 'relative', zIndex: 5 }}>
        <Card padding={0}>
          <div style={{ padding: 18 }}>
            <Eyebrow style={{ marginBottom: 10 }}>Checked in · 已簽到</Eyebrow>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              {justChecked.map(m => {
                const s = D.congregations.find(x => x.id === m.congregation);
                return (
                  <div key={m.id} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                    <Avatar member={m} size={36} ring ringColor="var(--brand-teal)" />
                    <div style={{ flex: 1 }}>
                      <div style={{ fontSize: 14, fontWeight: 700 }}>{m.en} <span style={{ fontWeight: 500, color: 'var(--fg-3)', fontFamily: "'Noto Sans TC', sans-serif" }}>· {m.zh}</span></div>
                      <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>{s ? `${s.en} · ${s.defaultTime}` : ''}</div>
                    </div>
                    <Icon name="check" size={18} color="var(--brand-teal)" strokeWidth={3} />
                  </div>
                );
              })}
            </div>
          </div>

          {/* Kids name-tag printout teaser */}
          {kids.length > 0 && (
            <div style={{
              borderTop: '1px solid var(--border-subtle)',
              padding: '14px 18px',
              background: 'var(--brand-warm)',
              display: 'flex', alignItems: 'center', gap: 12,
            }}>
              <div style={{ width: 36, height: 36, borderRadius: 8, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon name="sticker" size={18} color="var(--brand-coral)" />
              </div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 700, color: '#7c2d12' }}>Pick up name stickers at the kids' table</div>
                <div style={{ fontSize: 12, color: '#9a3412', fontFamily: "'Noto Sans TC', sans-serif" }}>請到兒童桌領取名牌貼紙</div>
              </div>
            </div>
          )}
        </Card>
      </div>

      {/* Verse for the day */}
      <div style={{ padding: '24px 24px 16px', textAlign: 'center', flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
        <Eyebrow style={{ marginBottom: 12 }}>Verse for today · 今日經文</Eyebrow>
        <div style={{
          fontFamily: "'Merriweather', serif", fontStyle: 'italic',
          fontSize: 18, color: 'var(--fg-2)', lineHeight: 1.45,
          maxWidth: 320, margin: '0 auto',
        }}>
          "Ask and it will be given to you; seek and you will find."
        </div>
        <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--fg-3)', marginTop: 10, letterSpacing: '0.05em' }}>
          MATTHEW 7:7 · 馬太福音 7:7
        </div>
      </div>

      {/* Bottom actions */}
      <div style={{ padding: '12px 16px 28px', background: 'var(--bg-1)', borderTop: '1px solid var(--border-subtle)' }}>
        <Btn variant="primary" full size="lg" onClick={onDone}>Done · 完成</Btn>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Screen 5: SETTINGS — change password, manage passkeys, sign out
// ─────────────────────────────────────────────────────────────
function ScreenSettings({ user, onBack, onLogout, onAddPasskey, onChangePassword }) {
  const [open, setOpen] = useState(null); // 'password' | 'passkey' | null
  const [current, setCurrent] = useState('');
  const [next, setNext] = useState('');
  const [confirm, setConfirm] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const [success, setSuccess] = useState(null);
  const supportsPasskey = !!(window.BHCAC_AUTH?.browserSupportsPasskeys?.());

  const submitPw = async (e) => {
    e.preventDefault();
    setError(null); setSuccess(null);
    if (next.length < 8) { setError('New password must be at least 8 characters.'); return; }
    if (next !== confirm) { setError('New passwords do not match.'); return; }
    setSubmitting(true);
    try {
      await onChangePassword({ currentPassword: current, newPassword: next });
      setSuccess('Password updated · 密碼已更新');
      setCurrent(''); setNext(''); setConfirm('');
      setOpen(null);
    } catch (err) {
      setError(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  const inputStyle = {
    width: '100%', boxSizing: 'border-box',
    padding: '12px 14px', borderRadius: 12,
    border: '1px solid var(--border-strong)',
    background: 'var(--bg-1)', fontSize: 15, fontFamily: 'Inter, sans-serif',
    outline: 'none',
  };

  return (
    <div className="focused-screen" style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-2)' }}>
      <div style={{ padding: '60px 20px 18px', background: 'var(--bg-1)', borderBottom: '1px solid var(--border-subtle)' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
          <CircleBtn icon="chevron-left" onClick={onBack} />
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg-3)' }}>Account · 帳戶</div>
          <div style={{ width: 40 }} />
        </div>
        <h1 style={{ fontSize: 24, fontWeight: 700, letterSpacing: '-0.02em', margin: 0 }}>{user.en}</h1>
        <div style={{ fontSize: 13, color: 'var(--fg-3)', marginTop: 4 }}>
          {user.email} {user.role === 'superadmin' && <Pill tone="coral" style={{ marginLeft: 8, fontSize: 9, padding: '2px 8px' }}>SUPERADMIN</Pill>}
        </div>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', padding: '18px 16px' }}>
        {success && (
          <div style={{ padding: '10px 14px', marginBottom: 14, background: 'rgba(13,148,136,0.1)', borderRadius: 10, color: 'var(--teal-700)', fontSize: 13, fontWeight: 600 }}>
            {success}
          </div>
        )}

        <Card padding={0} style={{ marginBottom: 12 }}>
          <button onClick={() => { setOpen(open === 'password' ? null : 'password'); setError(null); setSuccess(null); }}
            style={rowBtnStyle(open === 'password')}>
            <Icon name="key" size={18} color="var(--brand-navy)" />
            <div style={{ flex: 1, textAlign: 'left' }}>
              <div style={{ fontSize: 14, fontWeight: 600 }}>Change password · 更改密碼</div>
              <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>{user.hasPassword ? 'Update your sign-in password' : 'Set a sign-in password (you currently use passkey only)'}</div>
            </div>
            <Icon name={open === 'password' ? 'chevron-down' : 'chevron-right'} size={16} color="var(--fg-3)" />
          </button>
          {open === 'password' && (
            <form onSubmit={submitPw} style={{ padding: 16, borderTop: '1px solid var(--border-subtle)', display: 'flex', flexDirection: 'column', gap: 10 }}>
              {user.hasPassword && (
                <input style={inputStyle} type="password" placeholder="Current password · 現有密碼"
                  value={current} onChange={e => setCurrent(e.target.value)} required autoComplete="current-password" />
              )}
              <input style={inputStyle} type="password" placeholder="New password · 新密碼 (8+ characters)"
                value={next} onChange={e => setNext(e.target.value)} required autoComplete="new-password" minLength={8} />
              <input style={inputStyle} type="password" placeholder="Confirm new password · 確認新密碼"
                value={confirm} onChange={e => setConfirm(e.target.value)} required autoComplete="new-password" />
              {error && (
                <div style={{ fontSize: 13, color: 'var(--coral-700)', background: 'var(--coral-100)', padding: '8px 12px', borderRadius: 8 }}>
                  {error}
                </div>
              )}
              <Btn variant="primary" type="submit" full size="md" disabled={submitting}>
                {submitting ? 'Updating…' : 'Update password · 儲存'}
              </Btn>
            </form>
          )}
        </Card>

        <Card padding={0} style={{ marginBottom: 12 }}>
          <div style={{ ...rowBtnStyle(false), cursor: 'default' }}>
            <Icon name="fingerprint" size={18} color="var(--brand-teal)" />
            <div style={{ flex: 1, textAlign: 'left' }}>
              <div style={{ fontSize: 14, fontWeight: 600 }}>Passkeys · 通行密鑰</div>
              <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>
                {user.passkeyCount > 0
                  ? `${user.passkeyCount} passkey${user.passkeyCount === 1 ? '' : 's'} registered on your devices`
                  : 'Skip passwords by adding a passkey to this device'}
              </div>
            </div>
            {supportsPasskey && (
              <button onClick={onAddPasskey} style={{
                padding: '6px 12px', borderRadius: 9999,
                background: 'var(--brand-teal)', color: '#fff',
                border: 'none', fontSize: 12, fontWeight: 700, cursor: 'pointer',
              }}>+ Add</button>
            )}
          </div>
        </Card>

        <button onClick={onLogout} style={{
          width: '100%', marginTop: 18, padding: '14px',
          background: 'var(--bg-1)', color: 'var(--coral-700)',
          border: '1px solid var(--coral-100)', borderRadius: 12,
          fontSize: 14, fontWeight: 700, cursor: 'pointer',
          fontFamily: 'Inter, sans-serif',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        }}>
          <Icon name="log-out" size={16} />
          Sign out · 登出
        </button>
      </div>
    </div>
  );
}

function rowBtnStyle(active) {
  return {
    width: '100%',
    display: 'flex', alignItems: 'center', gap: 12,
    padding: '14px 16px',
    background: 'transparent', border: 'none',
    fontFamily: 'inherit', cursor: 'pointer',
    color: 'var(--fg-1)',
  };
}

Object.assign(window, { ScreenWelcome, ScreenToday, ScreenCheckIn, ScreenConfirm, ScreenSettings, CircleBtn });
