const SJS_I18N = {
  en: {
    estLine: 'Est. 1954 · Dinajpur',
    schoolName: 'Saint Joseph School',
    reunion: 'Reunion 2026',
    date: 'Date',
    venue: 'Venue',
    secYou: 'Your Details',
    secYouHint: 'Tell us how to reach you and your batch — this is how we will print your badge and seat your batch table.',
    secFamily: 'Family & Guests',
    secFamilyHint: 'Add anyone joining you. Each guest needs a seat, plate, and welcome kit, so please count carefully — including small children, in-laws, drivers, or support staff who will be on the campus with you.',
    secPayment: 'Payment',
    secPaymentHint: 'Pay the exact total shown on the right via bKash, Nagad, or bank transfer. Then enter the transaction reference so the organizers can verify your seat.',
    fullName: 'Full Name',
    fullNamePh: 'Name on your badge',
    mobile: 'Mobile',
    email: 'Email',
    sscYear: 'SSC Year',
    sscHintNoYear: 'Determines your batch fee',
    sscHintGroup: 'Fee group',
    profession: 'Profession',
    city: 'Current City',
    cityPh: 'Dhaka, Toronto, Riyadh…',
    spouse: 'Spouse',
    children: 'Children',
    family: 'Family / Guests',
    driver: 'Driver',
    support: 'Support Staff',
    yes: 'Yes',
    no: 'No',
    payIntro: 'Pay the exact total, then enter your transaction details below.',
    bkashLabel: 'bKash',
    nagadLabel: 'Nagad',
    bankLabel: 'Bank Transfer',
    personal: 'Personal',
    bankName: 'Bank',
    bankBranch: 'Branch',
    bankAcctName: 'Account Name',
    bankAcctNo: 'Account No.',
    bankRouting: 'Routing',
    select: 'Select',
    sender: 'Sender Number',
    txn: 'Transaction ID',
    amountPaid: 'Amount Paid',
    notes: 'Notes',
    yourTotal: 'Your Total',
    enterYear: 'Enter your SSC year',
    breakdownEmpty: 'Enter your SSC year to see the live total.',
    submit: 'Submit Registration',
    submitShort: 'Submit',
    submitting: 'Submitting…',
    savingServer: 'Saving to server + your browser.',
    savingLocal: 'Saving to your browser.',
    successTitle: 'Thank you — registered.',
    idLabel: 'ID',
    totalLabel: 'Total',
    errName: 'Please fill in your name, mobile and SSC year.',
    errPay: 'Please complete the payment section.',
    errAmount: (t) => `Amount paid must be exactly ৳${t}.`,
    errMobile: 'Mobile must be 11 digits starting with 01 (e.g. 01712345678).',
    errSender: 'Sender number must be 11 digits starting with 01.',
    errYear: 'SSC year must be between 1950 and 2027.',
    errEmail: 'Email address looks invalid.',
    errTxn: 'Transaction ID looks too short — please re-check.',
    errCount: 'Counts must be whole numbers between 0 and 20.',
    errServer: (reason) => `The server rejected this submission (${reason}). Please review your details and try again.`,
    motto: '“Once a Josephite, always a Josephite.”',
    showBreakdown: 'Show breakdown',
    hideBreakdown: 'Hide breakdown',
    footer: 'Crafted by',
  },
  bn: {
    estLine: '১৯৫৪ সাল · দিনাজপুর',
    schoolName: 'সেন্ট জোসেফ স্কুল',
    reunion: 'পুনর্মিলনী ২০২৬',
    date: 'তারিখ',
    venue: 'স্থান',
    secYou: 'আপনার তথ্য',
    secYouHint: 'আপনার সাথে যোগাযোগ ও ব্যাচের তথ্য দিন — ব্যাজ ও ব্যাচ টেবিলের জন্য এটি ব্যবহৃত হবে।',
    secFamily: 'পরিবার ও অতিথি',
    secFamilyHint: 'আপনার সঙ্গে আসছেন এমন সবাইকে যোগ করুন। প্রতিটি অতিথির জন্য আসন, খাবার ও ওয়েলকাম কিট প্রয়োজন — তাই ছোট শিশু, পরিবারের সদস্য, ড্রাইভার বা সহকারী যাঁরা স্কুলে প্রবেশ করবেন, সবাইকে গণনা করুন।',
    secPayment: 'পেমেন্ট',
    secPaymentHint: 'ডান পাশে দেখানো সঠিক পরিমাণ বিকাশ, নগদ বা ব্যাংক ট্রান্সফারে পরিশোধ করুন। তারপর ট্রানজেকশন আইডি দিন যাতে আয়োজকরা আপনার আসন নিশ্চিত করতে পারেন।',
    fullName: 'পূর্ণ নাম',
    fullNamePh: 'ব্যাজে যেভাবে দেখাতে চান',
    mobile: 'মোবাইল নম্বর',
    email: 'ইমেইল',
    sscYear: 'এসএসসি বছর',
    sscHintNoYear: 'ব্যাচ ফি নির্ধারণে ব্যবহৃত হবে',
    sscHintGroup: 'ব্যাচ',
    profession: 'পেশা',
    city: 'বর্তমান শহর',
    cityPh: 'ঢাকা, টরন্টো, রিয়াদ…',
    spouse: 'স্বামী/স্ত্রী',
    children: 'সন্তান',
    family: 'অতিথি',
    driver: 'ড্রাইভার',
    support: 'সহকারী',
    yes: 'হ্যাঁ',
    no: 'না',
    payIntro: 'সঠিক টাকা পরিশোধ করে নিচে ট্রানজেকশন তথ্য দিন।',
    method: 'পেমেন্ট মাধ্যম',
    select: 'নির্বাচন করুন',
    sender: 'প্রেরকের নম্বর',
    txn: 'ট্রানজেকশন আইডি',
    amountPaid: 'প্রদেয় টাকা',
    notes: 'মন্তব্য',
    bkashLabel: 'বিকাশ',
    nagadLabel: 'নগদ',
    bankLabel: 'ব্যাংক ট্রান্সফার',
    personal: 'ব্যক্তিগত',
    bankName: 'ব্যাংক',
    bankBranch: 'শাখা',
    bankAcctName: 'একাউন্ট নাম',
    bankAcctNo: 'একাউন্ট নম্বর',
    bankRouting: 'রাউটিং',
    yourTotal: 'মোট টাকা',
    enterYear: 'এসএসসি বছর দিন',
    breakdownEmpty: 'লাইভ মোট দেখতে এসএসসি বছর দিন।',
    submit: 'রেজিস্ট্রেশন জমা দিন',
    submitShort: 'জমা দিন',
    submitting: 'জমা হচ্ছে…',
    savingServer: 'সার্ভার ও ব্রাউজারে সংরক্ষণ হচ্ছে।',
    savingLocal: 'আপনার ব্রাউজারে সংরক্ষণ হচ্ছে।',
    successTitle: 'ধন্যবাদ — রেজিস্ট্রেশন সম্পন্ন।',
    idLabel: 'আইডি',
    totalLabel: 'মোট',
    errName: 'দয়া করে নাম, মোবাইল ও এসএসসি বছর পূরণ করুন।',
    errPay: 'দয়া করে পেমেন্ট তথ্য পূরণ করুন।',
    errAmount: (t) => `প্রদেয় টাকা ঠিক ৳${t} হতে হবে।`,
    errMobile: 'মোবাইল নম্বর ০১ দিয়ে শুরু হয়ে ১১ অঙ্কের হতে হবে (যেমন ০১৭১২৩৪৫৬৭৮)।',
    errSender: 'প্রেরকের নম্বর ০১ দিয়ে শুরু হয়ে ১১ অঙ্কের হতে হবে।',
    errYear: 'এসএসসি বছর ১৯৫০ থেকে ২০২৭ এর মধ্যে হতে হবে।',
    errEmail: 'ইমেইল ঠিকানা সঠিক নয়।',
    errTxn: 'ট্রানজেকশন আইডি অনেক ছোট — আবার পরীক্ষা করুন।',
    errCount: 'সংখ্যা ০ থেকে ২০ এর মধ্যে পূর্ণসংখ্যা হতে হবে।',
    errServer: (reason) => `সার্ভার এই রেজিস্ট্রেশন গ্রহণ করেনি (${reason})। তথ্য পরীক্ষা করে আবার চেষ্টা করুন।`,
    motto: '“একবার জোসেফাইট, চিরকাল জোসেফাইট।”',
    showBreakdown: 'বিস্তারিত দেখুন',
    hideBreakdown: 'লুকান',
    footer: 'ডিজাইন',
  },
};

function RegistrationForm({ tweaks, setTweak }) {
  const accent = tweaks?.accent || '#7a1f1f';
  const gold = tweaks?.gold || '#b8893a';
  const saveEndpoint = tweaks?.saveEndpoint || '';
  const saveSecret = tweaks?.saveSecret || '';
  const dark = !!tweaks?.dark;
  const xl = tweaks?.xlType !== false;
  const fs = xl ? 1 : 0.9;
  const lang = tweaks?.lang === 'bn' ? 'bn' : 'en';
  const t = SJS_I18N[lang];
  const isBn = lang === 'bn';

  const headFont = isBn ? "'Noto Serif Bengali', serif" : "'Cormorant Garamond', serif";
  const bodyFont = isBn ? "'Noto Serif Bengali', 'Inter', sans-serif" : "'Inter', system-ui, sans-serif";

  const T = dark
    ? { card:'#241410', cardAlt:'#2e1a14', ink:'#f4ead4', inkSoft:'#d9c79a', muted:'#a08866', line:'#3a221b', inputBg:'#1a0e0a', inputBorder:'#5a3d2a', successBg:'#1f2d1a', errorBg:'#3a1410' }
    : { card:'#fbf6ec', cardAlt:'#fff', ink:'#2a1810', inkSoft:'#5a3d2a', muted:'#8a6a4a', line:'#e8dcc4', inputBg:'#fff', inputBorder:'#d9c79a', successBg:'#fff', errorBg:'#fdeaea' };

  const inp = {
    width: '100%', boxSizing: 'border-box', padding: `${14*fs}px ${14*fs}px`,
    background: T.inputBg, border: `1.5px solid ${T.inputBorder}`, borderRadius: 4,
    fontSize: 17 * fs, fontFamily: bodyFont, color: T.ink, outline: 'none', minHeight: 48,
  };

  const [data, setData] = React.useState(emptyForm());
  const [submitted, setSubmitted] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [errorField, setErrorField] = React.useState(null);
  const [busy, setBusy] = React.useState(false);

  const setErr = (field, msg) => {
    setError(msg);
    setErrorField(field);
    if (typeof window !== 'undefined') window.scrollTo({ top: 0, behavior: 'smooth' });
  };
  const clearErr = () => { setError(null); setErrorField(null); };

  const set = (k) => (e) => {
    setData({ ...data, [k]: e.target.value });
    if (errorField === k) clearErr();
  };
  const calc = calcTotal(data);

  const inpErr = { ...inp, borderColor: '#c53030', boxShadow: '0 0 0 3px rgba(197,48,48,0.18)' };
  const inpFor = (k) => (errorField === k ? inpErr : inp);

  const REASON_FIELD = {
    missing_name: 'fullName',
    name_too_long: 'fullName',
    invalid_mobile: 'mobile',
    invalid_ssc_year: 'sscYear',
    invalid_email: 'email',
    missing_payment_method: 'paymentMethod',
    invalid_payment_method: 'paymentMethod',
    invalid_transaction_id: 'transactionId',
    invalid_sender_number: 'senderNumber',
    total_mismatch: 'amountPaid',
    amount_mismatch: 'amountPaid',
  };

  async function submit(e) {
    e.preventDefault();
    clearErr();
    if (!data.fullName) { setErr('fullName', t.errName); return; }
    if (!data.mobile) { setErr('mobile', t.errName); return; }
    if (!data.sscYear) { setErr('sscYear', t.errName); return; }
    const yr = Number(data.sscYear);
    if (!Number.isInteger(yr) || yr < 1950 || yr > 2027) { setErr('sscYear', t.errYear); return; }
    const mobileNorm = String(data.mobile).replace(/[\s-]/g, '');
    if (!/^01[0-9]{9}$/.test(mobileNorm)) { setErr('mobile', t.errMobile); return; }
    if (data.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) { setErr('email', t.errEmail); return; }
    for (const k of ['childCount', 'familyMemberCount', 'supportStaffCount']) {
      const n = Number(data[k] || 0);
      if (!Number.isInteger(n) || n < 0 || n > 20) { setErr(k, t.errCount); return; }
    }
    if (!data.paymentMethod) { setErr('paymentMethod', t.errPay); return; }
    if (!data.transactionId) { setErr('transactionId', t.errPay); return; }
    if (!data.amountPaid) { setErr('amountPaid', t.errPay); return; }
    const senderNorm = String(data.senderNumber || '').replace(/[\s-]/g, '');
    if (!/^01[0-9]{9}$/.test(senderNorm)) { setErr('senderNumber', t.errSender); return; }
    if (String(data.transactionId).trim().length < 4) { setErr('transactionId', t.errTxn); return; }
    if (Number(data.amountPaid) !== calc.total) { setErr('amountPaid', t.errAmount(calc.total)); return; }

    const reg = { registrationId: makeRegId(), submittedAt: new Date().toISOString(), ...data, total: calc.total, status: 'Payment Submitted — pending verification' };
    setBusy(true);
    if (saveEndpoint) {
      const result = await submitToEndpoint(reg, saveEndpoint, saveSecret);
      if (result.ok) {
        reg.status = result.duplicate
          ? 'Already on server — pending verification'
          : 'Submitted to server — pending verification';
        saveSubmission({ ...reg, syncedAt: new Date().toISOString() });
      } else if (result.reason === 'network_error') {
        reg.status = 'Saved locally (server unreachable) — will retry automatically';
        saveSubmission(reg);
      } else {
        setBusy(false);
        setErr(REASON_FIELD[result.reason] || null, t.errServer(result.reason || 'unknown'));
        return;
      }
    } else {
      saveSubmission(reg);
    }
    setBusy(false);
    setSubmitted(reg);
    setData(emptyForm());
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }

  function Section({ label, hint }) {
    return (
      <div style={{ margin: `${36*fs}px 0 ${18*fs}px` }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <span style={{ height: 1, flex: 1, background: `linear-gradient(to right, transparent, ${gold})` }} />
          <span style={{ fontFamily: headFont, fontStyle: isBn ? 'normal' : 'italic', fontSize: 22*fs, color: dark ? gold : accent, letterSpacing: '0.04em' }}>
            {label}
          </span>
          <span style={{ height: 1, flex: 1, background: `linear-gradient(to left, transparent, ${gold})` }} />
        </div>
        {hint && (
          <div style={{ marginTop: 10, fontSize: 14*fs, color: T.muted, fontStyle: 'italic', lineHeight: 1.55, textAlign: 'center', maxWidth: 640, marginLeft: 'auto', marginRight: 'auto', fontFamily: bodyFont }}>
            {hint}
          </div>
        )}
      </div>
    );
  }

  function Field({ label, hint, required, error, children, span = 1 }) {
    const labelColor = error ? '#c53030' : (dark ? gold : accent);
    return (
      <div className="sjs-field" style={{ ['--span']: span }}>
        <label style={{ display: 'block', marginBottom: 8 }}>
          <span style={{ fontSize: 14*fs, letterSpacing: isBn ? 0 : '0.12em', textTransform: isBn ? 'none' : 'uppercase', color: labelColor, fontWeight: 700, fontFamily: bodyFont }}>
            {label}{required && <span> *</span>}
          </span>
        </label>
        {children}
        {hint && <div style={{ fontSize: 13*fs, color: T.muted, marginTop: 6, fontStyle: 'italic', fontFamily: bodyFont }}>{hint}</div>}
      </div>
    );
  }

  return (
    <div className="sjs-shell" style={{ background: T.card, color: T.ink, fontFamily: bodyFont, border: `1px solid ${T.line}`, boxShadow: dark ? 'none' : '0 1px 0 #f3e9d2 inset, 0 30px 60px -30px rgba(74,15,15,0.25)', width: '100%', maxWidth: 1040, margin: '0 auto' }}>
      <style>{`
        .sjs-field { grid-column: span var(--span); }
        .sjs-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
        .sjs-grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 18px; }
        .sjs-form { padding: 28px 40px 40px; display: grid; grid-template-columns: 1fr 360px; gap: 36px; }
        .sjs-aside-desktop { display: block; }
        .sjs-mobile-bar { display: none; }
        .sjs-header-meta { display: flex; gap: 36px; }
        @media (max-width: 820px) {
          .sjs-form { grid-template-columns: 1fr !important; padding: 20px 18px 130px; gap: 0; }
          .sjs-grid-2, .sjs-grid-3 { grid-template-columns: 1fr; gap: 14px; }
          .sjs-field { grid-column: span 1 !important; }
          .sjs-aside-desktop { display: none; }
          .sjs-mobile-bar { display: flex; }
          .sjs-header-meta { flex-direction: column; gap: 12px; }
          .sjs-header-pad { padding: 22px 20px 24px !important; }
          .sjs-footer-credit { padding-bottom: 130px !important; }
        }
      `}</style>

      <div className="sjs-header-pad" style={{ background: `linear-gradient(180deg, ${accent} 0%, #4a0f0f 100%)`, color: '#fbf6ec', padding: '28px 40px 30px', borderBottom: `4px double ${gold}` }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
          <div style={{ background: '#fbf6ec', padding: 6, borderRadius: '50%', border: `2px solid ${gold}`, flexShrink: 0 }}>
            <SJSCrest size={64} />
          </div>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div style={{ fontSize: 12, letterSpacing: isBn ? 0 : '0.32em', textTransform: isBn ? 'none' : 'uppercase', color: gold, fontWeight: 600, fontFamily: bodyFont }}>
              {t.estLine}
            </div>
            <div style={{ fontFamily: headFont, fontSize: (isBn ? 28 : 32)*fs, lineHeight: 1.1, marginTop: 4, fontWeight: 600 }}>
              {t.schoolName}
            </div>
            <div style={{ fontFamily: headFont, fontStyle: isBn ? 'normal' : 'italic', fontSize: 20*fs, color: gold, marginTop: 6 }}>
              {t.reunion}
            </div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, flexShrink: 0 }}>
            <button type="button" onClick={() => setTweak && setTweak('lang', 'en')} style={langBtnStyle(lang === 'en', gold)}>
              <FlagUK /> EN
            </button>
            <button type="button" onClick={() => setTweak && setTweak('lang', 'bn')} style={langBtnStyle(lang === 'bn', gold)}>
              <FlagBD /> বাংলা
            </button>
          </div>
        </div>
        <div className="sjs-header-meta" style={{ marginTop: 18, fontSize: 15*fs, color: '#f3e6cc', borderTop: `1px solid ${gold}40`, paddingTop: 14 }}>
          <div>
            <div style={{ color: gold, letterSpacing: isBn ? 0 : '0.14em', fontSize: 12, textTransform: isBn ? 'none' : 'uppercase', fontFamily: bodyFont }}>{t.date}</div>
            <div style={{ marginTop: 2 }}>{SJS_CONFIG.EVENT_DATE}</div>
          </div>
          <div>
            <div style={{ color: gold, letterSpacing: isBn ? 0 : '0.14em', fontSize: 12, textTransform: isBn ? 'none' : 'uppercase', fontFamily: bodyFont }}>{t.venue}</div>
            <div style={{ marginTop: 2 }}>{SJS_CONFIG.EVENT_VENUE}</div>
          </div>
        </div>
      </div>

      <form onSubmit={submit} className="sjs-form">
        <div aria-hidden="true" style={{ position: 'absolute', left: '-9999px', top: 'auto', width: 1, height: 1, overflow: 'hidden' }}>
          <label htmlFor="sjs-confirm-url">Leave this field empty</label>
          <input
            id="sjs-confirm-url"
            type="text"
            name="confirm_url"
            tabIndex={-1}
            autoComplete="off"
            value={data.confirm_url || ''}
            onChange={set('confirm_url')}
          />
        </div>
        {submitted && (
          <div style={{ gridColumn: '1 / -1', padding: '20px 22px', background: T.successBg, border: `1px solid ${gold}`, borderLeft: `4px solid ${accent}`, color: T.ink, marginBottom: 20 }}>
            <div style={{ fontFamily: headFont, fontSize: 26*fs, color: dark ? gold : accent, fontWeight: 600 }}>{t.successTitle}</div>
            <div style={{ marginTop: 6, fontSize: 16*fs, color: T.inkSoft }}>
              {t.idLabel}: <strong style={{ fontFamily: 'ui-monospace, monospace' }}>{submitted.registrationId}</strong>
              <br />{t.totalLabel}: <strong>৳{submitted.total}</strong> · {submitted.status}
            </div>
          </div>
        )}
        {error && (
          <div style={{ gridColumn: '1 / -1', padding: '14px 18px', background: T.errorBg, border: `1px solid ${dark ? '#a04848' : '#c97171'}`, borderLeft: `4px solid ${accent}`, fontSize: 15*fs, color: dark ? '#f4ead4' : '#5a1414', marginBottom: 18 }}>
            {error}
          </div>
        )}

        <div>
          <Section label={t.secYou} hint={t.secYouHint} />
          <div className="sjs-grid-2">
            <Field label={t.fullName} required error={errorField === 'fullName'} span={2}>
              <input style={inpFor('fullName')} value={data.fullName} onChange={set('fullName')} placeholder={t.fullNamePh} />
            </Field>
            <Field label={t.mobile} required error={errorField === 'mobile'}>
              <input style={inpFor('mobile')} value={data.mobile} onChange={set('mobile')} placeholder="01XXX-XXXXXX" inputMode="tel" />
            </Field>
            <Field label={t.email} error={errorField === 'email'}>
              <input style={inpFor('email')} value={data.email} onChange={set('email')} type="email" inputMode="email" />
            </Field>
            <Field label={t.sscYear} required error={errorField === 'sscYear'} hint={calc.rule ? `${t.sscHintGroup} · ${calc.rule.label}` : t.sscHintNoYear}>
              <input style={inpFor('sscYear')} value={data.sscYear} onChange={set('sscYear')} type="number" min="1950" max="2027" inputMode="numeric" />
            </Field>
            <Field label={t.profession}>
              <input style={inp} value={data.profession} onChange={set('profession')} />
            </Field>
            <Field label={t.city} span={2}>
              <input style={inp} value={data.currentCity} onChange={set('currentCity')} placeholder={t.cityPh} />
            </Field>
          </div>

          <Section label={t.secFamily} hint={t.secFamilyHint} />
          <div className="sjs-grid-3">
            <Field label={t.spouse}>
              <select style={inp} value={data.spouse} onChange={set('spouse')}>
                <option value="No">{t.no}</option>
                <option value="Yes">{t.yes}</option>
              </select>
            </Field>
            <Field label={t.children} error={errorField === 'childCount'}>
              <input style={inpFor('childCount')} value={data.childCount} onChange={set('childCount')} type="number" min="0" max="20" inputMode="numeric" />
            </Field>
            <Field label={t.family} error={errorField === 'familyMemberCount'}>
              <input style={inpFor('familyMemberCount')} value={data.familyMemberCount} onChange={set('familyMemberCount')} type="number" min="0" max="20" inputMode="numeric" />
            </Field>
            <Field label={t.driver}>
              <select style={inp} value={data.driver} onChange={set('driver')}>
                <option value="No">{t.no}</option>
                <option value="Yes">{t.yes}</option>
              </select>
            </Field>
            <Field label={t.support} error={errorField === 'supportStaffCount'} span={2}>
              <input style={inpFor('supportStaffCount')} value={data.supportStaffCount} onChange={set('supportStaffCount')} type="number" min="0" max="20" inputMode="numeric" />
            </Field>
          </div>

          <Section label={t.secPayment} hint={t.secPaymentHint} />
          <div style={{ background: dark ? '#2e1a14' : '#fff7e6', border: `1px dashed ${gold}`, padding: '16px 18px', fontSize: 16*fs, color: T.inkSoft, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <span style={{ fontSize: 12, letterSpacing: isBn ? 0 : '0.14em', textTransform: isBn ? 'none' : 'uppercase', color: dark ? gold : accent, fontWeight: 700 }}>{t.bkashLabel}</span>
                <span style={{ fontSize: 10, letterSpacing: isBn ? 0 : '0.12em', textTransform: isBn ? 'none' : 'uppercase', padding: '2px 8px', border: `1px solid ${gold}`, color: T.muted, borderRadius: 999 }}>{t.personal}</span>
              </div>
              <div style={{ fontFamily: 'ui-monospace, monospace', fontSize: 18*fs, marginTop: 4 }}>{SJS_CONFIG.BKASH_NUMBER}</div>
            </div>
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <span style={{ fontSize: 12, letterSpacing: isBn ? 0 : '0.14em', textTransform: isBn ? 'none' : 'uppercase', color: dark ? gold : accent, fontWeight: 700 }}>{t.nagadLabel}</span>
                <span style={{ fontSize: 10, letterSpacing: isBn ? 0 : '0.12em', textTransform: isBn ? 'none' : 'uppercase', padding: '2px 8px', border: `1px solid ${gold}`, color: T.muted, borderRadius: 999 }}>{t.personal}</span>
              </div>
              <div style={{ fontFamily: 'ui-monospace, monospace', fontSize: 18*fs, marginTop: 4 }}>{SJS_CONFIG.NAGAD_NUMBER}</div>
            </div>
            <div style={{ gridColumn: '1 / -1', borderTop: `1px dashed ${gold}66`, paddingTop: 12, marginTop: 2 }}>
              <div style={{ fontSize: 12, letterSpacing: isBn ? 0 : '0.14em', textTransform: isBn ? 'none' : 'uppercase', color: dark ? gold : accent, fontWeight: 700, marginBottom: 6 }}>{t.bankLabel}</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '4px 18px', fontSize: 14*fs }}>
                <div><span style={{ color: T.muted }}>{t.bankName}: </span><strong>{SJS_CONFIG.BANK.name}</strong></div>
                <div><span style={{ color: T.muted }}>{t.bankBranch}: </span><strong>{SJS_CONFIG.BANK.branch}</strong></div>
                <div style={{ gridColumn: '1 / -1' }}><span style={{ color: T.muted }}>{t.bankAcctName}: </span><strong>{SJS_CONFIG.BANK.accountName}</strong></div>
                <div><span style={{ color: T.muted }}>{t.bankAcctNo}: </span><strong style={{ fontFamily: 'ui-monospace, monospace' }}>{SJS_CONFIG.BANK.accountNumber}</strong></div>
                <div><span style={{ color: T.muted }}>{t.bankRouting}: </span><strong style={{ fontFamily: 'ui-monospace, monospace' }}>{SJS_CONFIG.BANK.routing}</strong></div>
              </div>
            </div>
            <div style={{ gridColumn: '1 / -1', fontStyle: 'italic', color: T.muted, fontSize: 14*fs }}>{t.payIntro}</div>
          </div>

          <div className="sjs-grid-2" style={{ marginTop: 18 }}>
            <Field label={t.method} required error={errorField === 'paymentMethod'}>
              <select style={inpFor('paymentMethod')} value={data.paymentMethod} onChange={set('paymentMethod')}>
                <option value="">{t.select}</option>
                <option value="bKash">{t.bkashLabel}</option>
                <option value="Nagad">{t.nagadLabel}</option>
                <option value="Bank Transfer">{t.bankLabel}</option>
              </select>
            </Field>
            <Field label={t.sender} required error={errorField === 'senderNumber'}>
              <input style={inpFor('senderNumber')} value={data.senderNumber} onChange={set('senderNumber')} inputMode="tel" />
            </Field>
            <Field label={t.txn} required error={errorField === 'transactionId'}>
              <input style={{ ...inpFor('transactionId'), fontFamily: 'ui-monospace, monospace', textTransform: 'uppercase' }} value={data.transactionId} onChange={set('transactionId')} />
            </Field>
            <Field label={`${t.amountPaid} (৳${calc.total || '—'})`} required error={errorField === 'amountPaid'}>
              <input style={inpFor('amountPaid')} value={data.amountPaid} onChange={set('amountPaid')} type="number" placeholder={calc.total || ''} inputMode="numeric" />
            </Field>
            <Field label={t.notes} span={2}>
              <textarea style={{ ...inp, minHeight: 84, resize: 'vertical' }} value={data.notes} onChange={set('notes')} />
            </Field>
          </div>
        </div>

        <aside className="sjs-aside-desktop">
          <div style={{ position: 'sticky', top: 16, background: T.cardAlt, border: `1px solid ${gold}`, borderTop: `4px solid ${accent}`, padding: '22px 24px 24px' }}>
            <div style={{ fontSize: 13, letterSpacing: isBn ? 0 : '0.22em', textTransform: isBn ? 'none' : 'uppercase', color: dark ? gold : accent, fontWeight: 700 }}>{t.yourTotal}</div>
            <div style={{ fontFamily: headFont, fontSize: 56*fs, lineHeight: 1, color: dark ? gold : accent, fontWeight: 700, marginTop: 8 }}>
              ৳{calc.total.toLocaleString()}
            </div>
            <div style={{ fontFamily: bodyFont, fontSize: 15*fs, color: T.muted, marginTop: 4 }}>
              {calc.rule ? calc.rule.label : t.enterYear}
            </div>
            <div style={{ height: 1, background: `${gold}55`, margin: '18px 0' }} />
            {calc.rows.length === 0 && <div style={{ fontSize: 15*fs, color: T.muted, fontStyle: 'italic' }}>{t.breakdownEmpty}</div>}
            {calc.rows.map((r, i) => (
              <div key={i} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', fontSize: 15*fs, padding: '8px 0', color: T.inkSoft, borderBottom: `1px dotted ${T.line}` }}>
                <span>{r.label}</span>
                <span style={{ fontFamily: 'ui-monospace, monospace', whiteSpace: 'nowrap' }}>৳{r.amount.toLocaleString()}</span>
              </div>
            ))}
            <button type="submit" disabled={busy} style={submitBtnStyle(accent, gold, fs, busy, headFont)}>
              {busy ? t.submitting : t.submit}
            </button>
            <div style={{ marginTop: 14, fontSize: 12*fs, color: T.muted, fontStyle: 'italic', textAlign: 'center', lineHeight: 1.5 }}>
              {saveEndpoint ? t.savingServer : t.savingLocal}
            </div>
          </div>
        </aside>

        <div style={{ gridColumn: '1 / -1', marginTop: 28, textAlign: 'center', fontFamily: headFont, fontStyle: isBn ? 'normal' : 'italic', color: T.muted, fontSize: 16*fs }}>
          {t.motto}
        </div>
      </form>

      <div className="sjs-footer-credit" style={{ borderTop: `1px solid ${T.line}`, padding: '18px 24px', textAlign: 'center', fontSize: 13*fs, color: T.muted, fontFamily: bodyFont, background: T.cardAlt }}>
        {t.footer}{' '}
        <a href="https://asifkibria.com" target="_blank" rel="noopener noreferrer" style={{ color: dark ? gold : accent, textDecoration: 'none', fontWeight: 600, borderBottom: `1px dotted ${dark ? gold : accent}` }}>
          {isBn ? 'আসিফ কিবরিয়া' : 'Asif Kibria'}
        </a>
        <span style={{ margin: '0 8px', opacity: 0.5 }}>·</span>
        <span style={{ fontFamily: 'ui-monospace, monospace', fontSize: 12*fs }}>asifkibria.com</span>
      </div>

      <MobileTotalBar calc={calc} accent={accent} gold={gold} T={T} dark={dark} fs={fs} busy={busy} t={t} headFont={headFont} bodyFont={bodyFont} isBn={isBn}
        onSubmit={() => document.querySelector('.sjs-shell form').requestSubmit()} />
    </div>
  );
}

function langBtnStyle(active, gold) {
  return {
    background: active ? gold : 'transparent',
    color: active ? '#1a0e0a' : '#fbf6ec',
    border: `1px solid ${gold}`,
    borderRadius: 4,
    padding: '4px 10px',
    fontSize: 12,
    fontWeight: 700,
    cursor: 'pointer',
    fontFamily: 'inherit',
    minHeight: 28,
  };
}

function submitBtnStyle(accent, gold, fs, busy, headFont) {
  return {
    marginTop: 24, width: '100%', background: accent, color: '#fbf6ec', border: `1px solid ${gold}`,
    padding: '18px 22px', fontFamily: headFont, fontSize: 22 * fs, letterSpacing: '0.04em',
    cursor: busy ? 'wait' : 'pointer', boxShadow: `inset 0 0 0 3px ${accent}, inset 0 0 0 4px ${gold}`,
    opacity: busy ? 0.7 : 1, minHeight: 56, fontWeight: 600,
  };
}

function MobileTotalBar({ calc, accent, gold, T, dark, fs, busy, t, headFont, bodyFont, isBn, onSubmit }) {
  const [open, setOpen] = React.useState(false);
  return (
    <div className="sjs-mobile-bar" style={{ position: 'fixed', left: 0, right: 0, bottom: 0, zIndex: 50, background: T.card, borderTop: `3px solid ${accent}`, boxShadow: '0 -8px 24px -8px rgba(0,0,0,0.25)', flexDirection: 'column' }}>
      {open && (
        <div style={{ padding: '14px 16px', borderBottom: `1px solid ${T.line}`, maxHeight: '40vh', overflow: 'auto' }}>
          {calc.rows.length === 0 && <div style={{ fontSize: 14*fs, color: T.muted, fontStyle: 'italic' }}>{t.breakdownEmpty}</div>}
          {calc.rows.map((r, i) => (
            <div key={i} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 15*fs, padding: '6px 0', color: T.inkSoft }}>
              <span>{r.label}</span>
              <span style={{ fontFamily: 'ui-monospace, monospace' }}>৳{r.amount.toLocaleString()}</span>
            </div>
          ))}
        </div>
      )}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px' }}>
        <button type="button" onClick={() => setOpen(!open)} aria-label={open ? t.hideBreakdown : t.showBreakdown}
          style={{ background: 'transparent', border: `1px solid ${T.line}`, borderRadius: 4, padding: '8px 10px', cursor: 'pointer', color: T.ink, minHeight: 48, minWidth: 48, fontSize: 18 }}>
          {open ? '▾' : '▴'}
        </button>
        <div style={{ flex: 1, lineHeight: 1.1 }}>
          <div style={{ fontSize: 11, letterSpacing: isBn ? 0 : '0.18em', textTransform: isBn ? 'none' : 'uppercase', color: dark ? gold : accent, fontWeight: 700, fontFamily: bodyFont }}>{t.totalLabel}</div>
          <div style={{ fontFamily: headFont, fontSize: 30*fs, color: dark ? gold : accent, fontWeight: 700 }}>৳{calc.total.toLocaleString()}</div>
        </div>
        <button type="button" onClick={onSubmit} disabled={busy}
          style={{ background: accent, color: '#fbf6ec', border: `1px solid ${gold}`, padding: '14px 18px', fontFamily: headFont, fontSize: 18*fs, letterSpacing: '0.04em', borderRadius: 4, minHeight: 52, cursor: busy ? 'wait' : 'pointer', opacity: busy ? 0.7 : 1, fontWeight: 600 }}>
          {busy ? '…' : t.submitShort}
        </button>
      </div>
    </div>
  );
}

window.RegistrationForm = RegistrationForm;

function FlagUK() {
  return (
    <svg width="18" height="12" viewBox="0 0 60 40" style={{ verticalAlign: 'middle', marginRight: 4, border: '0.5px solid rgba(0,0,0,0.2)' }}>
      <rect width="60" height="40" fill="#012169"/>
      <path d="M0,0 L60,40 M60,0 L0,40" stroke="#fff" strokeWidth="6"/>
      <path d="M0,0 L60,40 M60,0 L0,40" stroke="#C8102E" strokeWidth="3" clipPath="url(#cl)"/>
      <path d="M30,0 v40 M0,20 h60" stroke="#fff" strokeWidth="10"/>
      <path d="M30,0 v40 M0,20 h60" stroke="#C8102E" strokeWidth="6"/>
    </svg>
  );
}
function FlagBD() {
  return (
    <svg width="18" height="12" viewBox="0 0 60 40" style={{ verticalAlign: 'middle', marginRight: 4, border: '0.5px solid rgba(0,0,0,0.2)' }}>
      <rect width="60" height="40" fill="#006a4e"/>
      <circle cx="27" cy="20" r="11" fill="#f42a41"/>
    </svg>
  );
}
window.FlagUK = FlagUK;
window.FlagBD = FlagBD;
