// setup.jsx — Page 3: Consultation Setup with sidebar wizard
// Sub-steps: 1) Welcome, 2) Video onboarding, 3) Detailed intake form, 4) Booking calendar

function SetupPage({ navigate, formData, setFormData, intakeData, setIntakeData, booking, setBooking, tweaks, hasBooked }) {
  const [step, setStep] = React.useState(1);
  const [completed, setCompleted] = React.useState({ 1: false, 2: false, 3: false, 4: false });
  // Track which steps have ever been visited so we can keep them mounted
  // (display:none instead of unmount) — prevents re-fetching API on tab switch.
  const [mounted, setMounted] = React.useState({ 1: true });

  const markDone = (n) => setCompleted((c) => ({ ...c, [n]: true }));
  const go = (n) => {
    setMounted(m => ({ ...m, [n]: true }));
    setStep(n);
  };

  const STEPS = [
    { n: 1, title: "Введение", sub: "О консультации и процессе" },
    { n: 2, title: "Инструкция", sub: "Видео-разбор от Дениса · 17 глав" },
    { n: 3, title: "Анкета", sub: "Расскажите о вашей ситуации" },
    { n: 4, title: "Бронирование", sub: "Выберите удобное время" },
  ];

  return (
    <div className="setup-wrap">
      <aside className="sidebar">
        <div className="sb-logo">
          <Logo />
        </div>

        <ul className="sb-steps">
          {STEPS.map((s) => (
            <li key={s.n}
                className={`sb-step ${step === s.n ? "active" : ""} ${completed[s.n] ? "done" : ""}`}
                onClick={() => go(s.n)}>
              <div className="n">{s.n}</div>
              <div>
                <b>{s.title}</b>
                <small>{s.sub}</small>
              </div>
            </li>
          ))}
        </ul>

        <div className="sb-help">
          <b>Нужна помощь?</b>
          Напишите нам в <a href="https://t.me/kiwieducation" target="_blank" rel="noopener noreferrer">Telegram</a> — ответим как можно скорее.
        </div>
      </aside>

      <section className="setup-content">
        <div className="muted" style={{fontSize:13,fontWeight:600,letterSpacing:".06em",textTransform:"uppercase",color:"var(--brand)"}}>Шаг {step} из 4</div>

        {mounted[1] && <div style={{display: step === 1 ? '' : 'none'}}>
          <SetupWelcome onNext={() => { markDone(1); go(2); }} formData={formData}/>
        </div>}
        {mounted[2] && <div style={{display: step === 2 ? '' : 'none'}}>
          <window.SetupInstruction onNext={() => { markDone(2); go(3); }} onBack={() => go(1)}/>
        </div>}
        {mounted[3] && <div style={{display: step === 3 ? '' : 'none'}}>
          <SetupIntake intakeData={intakeData} setIntakeData={setIntakeData}
                       hasBooked={hasBooked}
                       onNext={() => { markDone(3); go(4); }} onBack={() => go(2)}/>
        </div>}
        {mounted[4] && <div style={{display: step === 4 ? '' : 'none'}}>
          <SetupBooking booking={booking} setBooking={setBooking}
                        onBook={() => { markDone(4); navigate("confirmation"); }}
                        onBack={() => go(3)} formData={formData} intakeData={intakeData}/>
        </div>}
      </section>
    </div>
  );
}

/* -------- Step 1: Welcome -------- */
const WELCOME_ICON_MAP = {
  Clock: Icon.Clock, Calendar: Icon.Calendar, Video: Icon.Video,
  Doc: Icon.Doc, User: Icon.User, Upload: Icon.Upload,
  Shield: Icon.Shield, Globe: Icon.Globe, Help: Icon.Help,
  Lock: Icon.Lock, Check: Icon.Check, Plane: Icon.Plane,
};
const WELCOME_FALLBACK_ICONS = [Icon.Clock, Icon.Help, Icon.Doc, Icon.Shield];

function SetupWelcome({ onNext, formData }) {
  const [content, setContent] = React.useState(null);

  React.useEffect(() => {
    fetch("/api/welcome")
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d) setContent(d); })
      .catch(() => {});
  }, []);

  const heading    = content?.heading     ?? "Добро пожаловать";
  const lead       = content?.lead        ?? "";
  const features   = content?.features   ?? [];
  const whyEnabled = content?.why_enabled ?? true;
  const whyTitle   = content?.why_title   ?? "Почему это важно?";
  const whyBody    = content?.why_body    ?? "";

  if (!content) return (
    <div style={{display:"flex",justifyContent:"center",alignItems:"center",minHeight:320}}>
      <svg width="40" height="40" viewBox="0 0 40 40" fill="none"
           style={{animation:"spin 0.8s linear infinite",opacity:.4}}>
        <circle cx="20" cy="20" r="16" stroke="#6366f1" strokeWidth="4"
                strokeDasharray="60 40" strokeLinecap="round"/>
      </svg>
    </div>
  );

  return (
    <div className="anim-in">
      <h1 className="h1 mt-16">{heading}!</h1>
      <p className="lead mt-16" style={{maxWidth:620}}>{lead}</p>

      <div className="feat mt-32" style={{maxWidth:780}}>
        {features.map((f, i) => {
          const Ico = WELCOME_ICON_MAP[f.icon] ?? WELCOME_FALLBACK_ICONS[i % WELCOME_FALLBACK_ICONS.length];
          return (
            <div key={i} className="feat-item">
              <div className="fi-ico"><Ico /></div>
              <div><b>{f.title}</b><p>{f.body}</p></div>
            </div>
          );
        })}
      </div>

      {whyEnabled && (
        <div className="card card-pad mt-32" style={{maxWidth:780,background:"var(--brand-soft)",border:"1px solid color-mix(in srgb, var(--brand) 18%, transparent)"}}>
          <div className="hstack gap-12" style={{alignItems:"flex-start"}}>
            <div style={{width:32,height:32,borderRadius:"50%",background:"#fff",display:"grid",placeItems:"center",color:"var(--brand)",flexShrink:0}}>
              <Icon.Help style={{width:18,height:18}}/>
            </div>
            <div>
              <b style={{display:"block",color:"var(--brand-deep)",marginBottom:4,fontSize:15}}>{whyTitle}</b>
              <div style={{color:"var(--brand-deep)",fontSize:14.5,lineHeight:1.55,opacity:.85}}>{whyBody}</div>
            </div>
          </div>
        </div>
      )}

      <div className="hstack mt-32" style={{gap:12,maxWidth:780}}>
        <button className="btn btn-primary btn-lg" onClick={onNext}>
          Начать <Icon.Arrow style={{width:16,height:16}}/>
        </button>
      </div>
    </div>
  );
}

/* -------- Step 2: Video -------- */
const VIDEO_LIBRARY = [
  { t: "Знакомство: как проходит консультация", d: "3:42", x: "Короткое введение в формат: что мы обсудим, как лучше подготовиться, какие материалы будут полезны. Этот ролик стоит посмотреть в первую очередь — он задаёт контекст для всех остальных." },
  { t: "Какие вопросы подготовить заранее", d: "4:15", x: "Чек-лист вопросов, которые помогут вам получить максимум от консультации. Чем точнее вы сформулируете свои сомнения, тем конкретнее будут наши рекомендации." },
  { t: "Документы и материалы, которые могут понадобиться", d: "5:08", x: "Список документов, которые стоит подготовить: дипломы, сертификаты языка, опыт работы, рекомендации. Расскажем, что обязательно, а что — желательно." },
  { t: "Типы виз: обзор основных категорий", d: "8:21", x: "Рабочая, учебная, партнёрская, инвесторская, по таланту, гуманитарная. Сильные и слабые стороны каждой, кому какая подходит." },
  { t: "Skilled Migrant Category: как набрать баллы", d: "9:54", x: "Подробный разбор балльной системы: возраст, образование, опыт, английский, предложение о работе. Реальные примеры успешных и неуспешных профилей." },
  { t: "Work Visa: как найти работодателя", d: "7:33", x: "Стратегии поиска работы из-за границы. Какие компании готовы спонсировать визу, как составить резюме под местный рынок, на что обращают внимание рекрутёры." },
  { t: "Study Pathway: учёба как путь к иммиграции", d: "6:47", x: "Какие специальности и уровни образования открывают дорогу к ПМЖ. Стоимость, сроки, требования к английскому. Когда учёба — это инвестиция, а когда — пустая трата денег." },
  { t: "Партнёрская виза: что важно знать", d: "5:29", x: "Документы, доказательства отношений, частые отказы. Разница между супружеской и de facto визой. Что делать, если отношения нестандартные." },
  { t: "Бизнес и инвестиции: путь предпринимателя", d: "8:02", x: "Entrepreneur Work Visa, Investor Visa, требования к капиталу и бизнес-плану. Реальные пороги входа и сроки рассмотрения." },
  { t: "Английский язык: уровень и сертификаты", d: "5:51", x: "IELTS, PTE, TOEFL — какой сдавать, на какой балл целиться. Где готовиться, сколько это стоит, можно ли обойти этот пункт." },
  { t: "Финансовая подготовка к переезду", d: "6:38", x: "Минимальный бюджет, подушка безопасности, перевод денег между странами. Налоговые нюансы: где платить, как избежать двойного налогообложения." },
  { t: "Переезд с семьёй: что учесть", d: "7:14", x: "Визы для супруга и детей, школы, страховка, аренда жилья на семью. Разница между переездом одного человека и переездом семьи." },
  { t: "Медицина и страхование", d: "4:55", x: "Медосмотр для визы, какие требования, у кого могут быть проблемы. Страховка на период переезда и после." },
  { t: "Жизнь после переезда: первые месяцы", d: "9:11", x: "IRD-номер, банк, аренда, водительские права, симка. Что делать в первые две недели — пошаговый план." },
  { t: "Поиск работы на месте", d: "8:27", x: "Локальные сайты, рекрутёры, networking. Как переписать резюме и LinkedIn под местный рынок. Чего ждать на интервью и какие зарплаты реалистичны." },
  { t: "Частые ошибки кандидатов", d: "6:03", x: "Топ-15 ошибок, которые мы видим у клиентов: от плохо оформленных документов до неправильного выбора визы. Как их избежать." },
  { t: "Что делать после консультации", d: "4:22", x: "Как использовать наши рекомендации, в каком порядке начинать действовать, когда возвращаться для повторной консультации." },
];

function SetupVideo({ onNext, onBack }) {
  const [openVideos, setOpenVideos] = React.useState({}); // id -> true
  const [playingId, setPlayingId] = React.useState(null);
  const [openFaq, setOpenFaq] = React.useState(-1);

  const toggle = (i) => setOpenVideos((o) => ({ ...o, [i]: !o[i] }));

  const FAQ = [
    { q: "Обязательно ли смотреть все 17 видео?", a: "Нет, но мы рекомендуем посмотреть хотя бы первые 5 — они дают общую картину. Остальные стоит выбирать по вашей ситуации (тип визы, семейное положение, профессия)." },
    { q: "Сколько длится консультация?", a: "Стандартная консультация — 60 минут. При необходимости мы можем продлить разговор — предупредим заранее." },
    { q: "На каком языке проводится консультация?", a: "На русском или английском — на ваш выбор. Возможен смешанный формат." },
    { q: "Получу ли я запись консультации?", a: "Да, после консультации мы отправим запись и резюме с планом действий на email." },
    { q: "Что если я не смогу подключиться вовремя?", a: "Можем перенести консультацию один раз бесплатно, если вы предупредите за 24 часа." },
  ];

  const watchedCount = Object.values(openVideos).filter(Boolean).length;

  return (
    <div className="anim-in">
      <h1 className="h1 mt-16">Видео-материалы</h1>
      <p className="lead mt-16" style={{maxWidth:620}}>
        17 коротких видео по ключевым темам иммиграции. Посмотрите те, что относятся к вашей ситуации — это сильно ускорит консультацию.
      </p>

      <div className="hstack gap-12 mt-16" style={{maxWidth:780,padding:"12px 16px",background:"var(--brand-soft)",borderRadius:10,color:"var(--brand-deep)",fontSize:13.5,lineHeight:1.5}}>
        <Icon.Help style={{width:18,height:18,color:"var(--brand)",flexShrink:0}}/>
        <span>Не обязательно смотреть все. Минимум — первые 5 для общего контекста, затем выбирайте по теме.</span>
      </div>

      <div className="mt-32" style={{maxWidth:780}}>
        <div className="hstack" style={{justifyContent:"space-between",marginBottom:14}}>
          <h3 className="h3">Все материалы</h3>
          <div className="muted" style={{fontSize:13}}>
            <b style={{color:"var(--ink)"}}>{watchedCount}</b> из {VIDEO_LIBRARY.length} открыто
          </div>
        </div>

        <div className="stack gap-10">
          {VIDEO_LIBRARY.map((v, i) => {
            const isOpen = !!openVideos[i];
            return (
              <div key={i} className={`vid-item ${isOpen?"open":""}`}>
                <button className="vid-head" onClick={()=>toggle(i)}>
                  <div className="vid-num">{String(i+1).padStart(2,"0")}</div>
                  <div className="vid-titles">
                    <b>{v.t}</b>
                    <small><Icon.Video style={{width:12,height:12,display:"inline",verticalAlign:"-1px",marginRight:4,opacity:.6}}/>{v.d}</small>
                  </div>
                  <div className="vid-chev">
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                      <polyline points="6 9 12 15 18 9"/>
                    </svg>
                  </div>
                </button>

                {isOpen && (
                  <div className="vid-body anim-in">
                    <div className="vid-player" onClick={(e) => { e.stopPropagation(); setPlayingId(playingId===i?null:i); }}>
                      {playingId === i ? (
                        <div style={{position:"absolute",inset:0,display:"grid",placeItems:"center",color:"#fff",gap:10,flexDirection:"column"}}>
                          <Spinner/>
                          <span style={{fontSize:13,opacity:.7}}>Здесь будет встроенное видео</span>
                        </div>
                      ) : (
                        <>
                          <div className="vid-play-btn"/>
                          <div className="vid-duration">{v.d}</div>
                        </>
                      )}
                    </div>
                    <div className="vid-desc">{v.x}</div>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>

      <div className="mt-32" style={{maxWidth:780}}>
        <h3 className="h3" style={{marginBottom:16}}>Частые вопросы</h3>
        <div className="stack gap-12">
          {FAQ.map((f, i) => (
            <div key={i} className={`faq-item ${openFaq===i?"open":""}`}>
              <div className="faq-q" onClick={() => setOpenFaq(openFaq===i?-1:i)}>
                <span>{f.q}</span>
                <span className="pm"><Icon.Plus style={{width:12,height:12}}/></span>
              </div>
              {openFaq===i && <div className="faq-a">{f.a}</div>}
            </div>
          ))}
        </div>
      </div>

      <div className="hstack mt-32" style={{gap:12,maxWidth:780,justifyContent:"space-between"}}>
        <button className="btn btn-ghost" onClick={onBack}><Icon.ArrowLeft style={{width:14,height:14}}/> Назад</button>
        <button className="btn btn-primary btn-lg" onClick={onNext}>
          Перейти к анкете <Icon.Arrow style={{width:16,height:16}}/>
        </button>
      </div>

      <style>{`
        .vid-item{border:1px solid var(--line);border-radius:12px;background:#fff;overflow:hidden;transition:box-shadow .15s, border-color .15s}
        .vid-item.open{box-shadow:var(--shadow-md);border-color:color-mix(in srgb, var(--brand) 25%, var(--line))}
        .vid-head{display:flex;align-items:center;gap:14px;padding:14px 16px;width:100%;background:transparent;border:0;cursor:pointer;text-align:left;font-family:inherit;transition:background .12s}
        .vid-head:hover{background:var(--bg-tint)}
        .vid-num{flex-shrink:0;width:34px;height:34px;border-radius:8px;background:var(--brand-soft);color:var(--brand-deep);display:grid;place-items:center;font-size:12.5px;font-weight:700;letter-spacing:.02em;font-variant-numeric:tabular-nums}
        .vid-item.open .vid-num{background:var(--brand);color:#fff}
        .vid-titles{flex:1;min-width:0}
        .vid-titles b{display:block;font-size:14.5px;font-weight:600;color:var(--ink);line-height:1.35;letter-spacing:-.005em}
        .vid-titles small{display:block;font-size:12.5px;color:var(--ink-3);margin-top:3px;font-weight:500}
        .vid-chev{flex-shrink:0;color:var(--ink-3);transition:transform .2s}
        .vid-item.open .vid-chev{transform:rotate(180deg);color:var(--brand)}
        .vid-body{padding:0 16px 18px;display:grid;grid-template-columns:240px 1fr;gap:18px;align-items:start}
        @media (max-width:640px){.vid-body{grid-template-columns:1fr}}
        .vid-player{position:relative;aspect-ratio:16/9;border-radius:10px;overflow:hidden;background:linear-gradient(135deg,#1e293b 0%,#0f172a 100%);cursor:pointer;display:grid;place-items:center}
        .vid-player::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at center, color-mix(in srgb, var(--brand) 25%, transparent), transparent 60%)}
        .vid-play-btn{width:46px;height:46px;border-radius:50%;background:rgba(255,255,255,.95);position:relative;z-index:1;box-shadow:0 4px 14px rgba(0,0,0,.3);transition:transform .2s;display:grid;place-items:center}
        .vid-play-btn::before{content:"";width:0;height:0;border-left:12px solid var(--brand);border-top:7px solid transparent;border-bottom:7px solid transparent;margin-left:3px}
        .vid-player:hover .vid-play-btn{transform:scale(1.08)}
        .vid-duration{position:absolute;bottom:8px;right:8px;z-index:1;background:rgba(0,0,0,.7);color:#fff;font-size:11px;padding:2px 6px;border-radius:4px;font-weight:600;font-variant-numeric:tabular-nums}
        .vid-desc{font-size:14px;color:var(--ink-2);line-height:1.6;padding-top:6px}
      `}</style>
    </div>
  );
}

/* -------- Step 3: Intake form (multi-section) -------- */
const ENGLISH_LEVELS = ["A1 — Beginner","A2 — Elementary","B1 — Intermediate","B2 — Upper-Intermediate","C1 — Advanced","C2 — Proficiency / Native"];
const EDU_LEVELS = ["Среднее","Среднее специальное","Незаконченное высшее","Бакалавр","Специалист","Магистр","PhD / Кандидат наук"];

function PersonBlock({ prefix, data, update, optional }) {
  const v = (k) => data[`${prefix}_${k}`] || "";
  const set = (k, val) => update(`${prefix}_${k}`, val);
  return (
    <div className="form-grid">
      <div className="row-2">
        <Field label="Имя"><input className="input" placeholder="Имя и фамилия" value={v("name")} onChange={(e)=>set("name",e.target.value)}/></Field>
        <Field label="Возраст (полных лет)"><input className="input" type="number" min="0" max="99" placeholder="35" value={v("age")} onChange={(e)=>set("age",e.target.value)}/></Field>
      </div>
      <div className="row-2">
        <Field label="Образование — уровень" hint="Неоконченное укажите тоже">
          <select className="select" value={v("eduLevel")} onChange={(e)=>set("eduLevel",e.target.value)}>
            <option value="">Выберите</option>
            {EDU_LEVELS.map(o => <option key={o}>{o}</option>)}
          </select>
        </Field>
        <Field label="Средний балл" hint="По главному из имеющихся образований">
          <input className="input" placeholder="Например: 4.7 или 85%" value={v("gpa")} onChange={(e)=>set("gpa",e.target.value)}/>
        </Field>
      </div>
      <Field label="Специальность" hint="Что изучали или изучаете">
        <input className="input" placeholder="Например: Информатика и вычислительная техника" value={v("major")} onChange={(e)=>set("major",e.target.value)}/>
      </Field>
      <Field label="Опыт работы" hint="Основной, наиболее значимый">
        <textarea className="textarea" placeholder="Должность, индустрия, сколько лет, что делали"
                  value={v("experience")} onChange={(e)=>set("experience",e.target.value)}/>
      </Field>
      <Field label="Уровень английского">
        <div className="chip-group">
          {ENGLISH_LEVELS.map(o => (
            <button key={o} type="button" className={`chip ${v("english")===o?"sel":""}`} onClick={()=>set("english",o)}>{o}</button>
          ))}
        </div>
      </Field>
    </div>
  );
}

const _PERSON_FIELDS = (prefix) => [
  { key: `${prefix}_name`,       label: "Имя",                  type: "text",     hint: null,                                    placeholder: "Имя и фамилия",                                   options: null,         optional: false, half: true  },
  { key: `${prefix}_age`,        label: "Возраст (полных лет)",  type: "number",   hint: null,                                    placeholder: "35",                                              options: null,         optional: false, half: true  },
  { key: `${prefix}_eduLevel`,   label: "Образование — уровень", type: "select",   hint: "Неоконченное укажите тоже",             placeholder: null,                                              options: EDU_LEVELS,   optional: false, half: true  },
  { key: `${prefix}_gpa`,        label: "Средний балл",          type: "text",     hint: "По главному из имеющихся образований",  placeholder: "Например: 4.7 или 85%",                          options: null,         optional: false, half: true  },
  { key: `${prefix}_major`,      label: "Специальность",         type: "text",     hint: "Что изучали или изучаете",              placeholder: "Например: Информатика и вычислительная техника", options: null,         optional: false, half: false },
  { key: `${prefix}_experience`, label: "Опыт работы",           type: "textarea", hint: "Основной, наиболее значимый",           placeholder: "Должность, индустрия, сколько лет, что делали",  options: null,         optional: false, half: false },
  { key: `${prefix}_english`,    label: "Уровень английского",   type: "chips",    hint: null,                                    placeholder: null,                                              options: ENGLISH_LEVELS, optional: false, half: false },
];

const FALLBACK_SECTIONS = [
  {
    key: "main",
    title: "Основной заявитель",
    description: "Тот, кто планирует учиться или работать в Новой Зеландии.",
    fields: _PERSON_FIELDS("main"),
  },
  {
    key: "partner",
    title: "Партнёр",
    description: "Супруг или супруга, если планируете переезжать вместе.",
    fields: [
      { key: "hasPartner", label: "Едете с партнёром?", type: "partner_toggle", hint: null, placeholder: null, options: null, optional: false, half: false },
      ..._PERSON_FIELDS("partner"),
    ],
  },
  {
    key: "other",
    title: "Прочее",
    description: null,
    fields: [
      { key: "kids",     label: "Количество и возраст детей",                  type: "text",     hint: "Если детей нет — оставьте пустым", placeholder: "Например: двое, 6 и 9 лет",                      options: null, optional: true,  half: false },
      { key: "pets",     label: "Наличие и вид домашних животных",             type: "text",     hint: null,                               placeholder: "Например: кошка, или собака средней породы",     options: null, optional: true,  half: false },
      { key: "refusals", label: "Отказы в визах",                              type: "textarea", hint: "Укажите страны и типы виз",         placeholder: "Если отказов не было — оставьте пустым",         options: null, optional: true,  half: false },
      { key: "arrival",  label: "Когда планируете оказаться в Новой Зеландии", type: "text",     hint: null,                               placeholder: "Например: осень 2026, февральский интейк 2027",  options: null, optional: false, half: false },
    ],
  },
  {
    key: "cv",
    title: "Резюме",
    description: "Прикрепите резюме, если есть. На любом языке — мы разберёмся.",
    fields: [
      { key: "cv", label: "Резюме", type: "file", hint: null, placeholder: null, options: null, optional: true, half: false },
    ],
  },
  {
    key: "questions",
    title: "Вопросы к консультации",
    description: "Что вы хотите обсудить с Денисом? Чем конкретнее — тем полезнее.",
    fields: [
      { key: "questions", label: "Ваши вопросы", type: "textarea", hint: null,
        placeholder: "Например:\n1. Какая программа лучше под мою специальность?\n2. Реально ли с моим опытом найти работу в первые 6 месяцев?\n3. Что с переводом денег и оплатой обучения в моей ситуации?",
        options: null, optional: false, half: false },
      { key: "_note_booking", label: "После сохранения анкеты вы сможете выбрать удобное время для консультации.", type: "note", hint: null, placeholder: null, options: null, optional: false, half: false },
    ],
  },
];

function IntakeSectionFields({ section, intakeData, update, disabled }) {
  const hasPartner = !!intakeData.hasPartner;
  const hasToggle = section.fields.some(f => f.type === "partner_toggle");
  const noop = () => {};

  function renderField(field) {
    if (field.type === "partner_toggle") {
      return (
        <div key={field.key} className="hstack gap-8" style={{marginBottom:18}}>
          <button type="button" className={`chip ${!hasPartner?"sel":""}`} onClick={disabled?noop:()=>update("hasPartner",false)} disabled={disabled}>Еду один / одна</button>
          <button type="button" className={`chip ${hasPartner?"sel":""}`} onClick={disabled?noop:()=>update("hasPartner",true)} disabled={disabled}>Еду с партнёром</button>
        </div>
      );
    }
    if (field.type === "select") {
      return (
        <Field key={field.key} label={field.label} hint={field.hint||undefined} optional={!!field.optional}>
          <select className="select" value={intakeData[field.key]||""} onChange={disabled?noop:(e)=>update(field.key,e.target.value)} disabled={disabled}>
            <option value="">Выберите</option>
            {(field.options||[]).map(o => <option key={o}>{o}</option>)}
          </select>
        </Field>
      );
    }
    if (field.type === "chips") {
      return (
        <Field key={field.key} label={field.label} hint={field.hint||undefined} optional={!!field.optional}>
          <div className="chip-group">
            {(field.options||[]).map(o => (
              <button key={o} type="button" className={`chip ${intakeData[field.key]===o?"sel":""}`} onClick={disabled?noop:()=>update(field.key,o)} disabled={disabled}>{o}</button>
            ))}
          </div>
        </Field>
      );
    }
    if (field.type === "file") {
      return <FileUpload key={field.key} value={intakeData[field.key]} disabled={disabled} onChange={disabled?noop:(v)=>update(field.key,v)}/>;
    }
    if (field.type === "note") {
      return <ReassureNote key={field.key}>{field.label}</ReassureNote>;
    }
    if (field.type === "textarea") {
      return (
        <Field key={field.key} label={field.label} hint={field.hint||undefined} optional={!!field.optional}>
          <textarea className="textarea"
                    style={field.key==="questions"?{minHeight:180}:{}}
                    placeholder={field.placeholder||""}
                    value={intakeData[field.key]||""}
                    onChange={disabled?noop:(e)=>update(field.key,e.target.value)}
                    readOnly={disabled}/>
        </Field>
      );
    }
    return (
      <Field key={field.key} label={field.label} hint={field.hint||undefined} optional={!!field.optional}>
        <input className="input"
               type={field.type==="number"?"number":"text"}
               placeholder={field.placeholder||""}
               value={intakeData[field.key]||""}
               onChange={disabled?noop:(e)=>update(field.key,e.target.value)}
               readOnly={disabled}/>
      </Field>
    );
  }

  function renderGrouped(fields) {
    const out = [];
    let i = 0;
    while (i < fields.length) {
      if (fields[i].half && fields[i+1]?.half) {
        out.push(<div key={i} className="row-2">{renderField(fields[i])}{renderField(fields[i+1])}</div>);
        i += 2;
      } else {
        out.push(renderField(fields[i]));
        i++;
      }
    }
    return out;
  }

  if (hasToggle) {
    const toggleField = section.fields.find(f => f.type === "partner_toggle");
    const bodyFields  = section.fields.filter(f => f.type !== "partner_toggle");
    return (
      <>
        <h3 className="h3" style={{marginBottom:6}}>{section.title}</h3>
        {section.description && (
          <p className="muted" style={{margin:"0 0 18px",fontSize:13.5}}>{section.description}</p>
        )}
        {renderField(toggleField)}
        {hasPartner ? (
          <div className="form-grid">{renderGrouped(bodyFields)}</div>
        ) : (
          <div className="muted" style={{padding:"20px 18px",border:"1px dashed var(--line)",borderRadius:10,fontSize:13.5,lineHeight:1.55}}>
            Если планы изменятся — можно вернуться и заполнить блок партнёра позже.
          </div>
        )}
      </>
    );
  }

  return (
    <div className="form-grid">
      <h3 className="h3">{section.title}</h3>
      {section.description && (
        <p className="muted" style={{margin:0}}>{section.description}</p>
      )}
      {renderGrouped(section.fields)}
    </div>
  );
}

function SetupIntake({ intakeData, setIntakeData, hasBooked, onNext, onBack }) {
  const [section, setSection] = React.useState(0);
  const [sections, setSections] = React.useState(FALLBACK_SECTIONS);
  const [saving, setSaving] = React.useState(false);
  const [saveError, setSaveError] = React.useState(false);

  React.useEffect(() => {
    fetch("/api/intake/sections")
      .then(r => r.ok ? r.json() : null)
      .then(data => { if (Array.isArray(data) && data.length > 0) setSections(data); })
      .catch(() => {});
  }, []);

  // Load saved answers on mount
  React.useEffect(() => {
    const token = localStorage.getItem("kiwi_session_token");
    if (!token) return;
    fetch("/api/customer/anketa", { headers: { Authorization: `Bearer ${token}` } })
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d && d.data && Object.keys(d.data).length > 0) setIntakeData(d.data); })
      .catch(() => {});
  }, []);

  const update = (k, v) => setIntakeData((d) => ({ ...d, [k]: v }));

  const saveAnketa = async () => {
    const token = localStorage.getItem("kiwi_session_token");
    if (!token) return true; // no session — skip silently
    setSaving(true);
    setSaveError(false);
    try {
      const res = await fetch("/api/customer/anketa", {
        method: "PUT",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
        body: JSON.stringify({ data: intakeData }),
      });
      if (!res.ok) { setSaveError(true); setSaving(false); return false; }
    } catch { setSaveError(true); setSaving(false); return false; }
    setSaving(false);
    return true;
  };

  const nextSection = async () => {
    if (section < sections.length - 1) {
      setSection(section + 1);
    } else {
      const ok = await saveAnketa();
      if (ok) onNext();
    }
  };
  const prevSection = () => {
    if (section > 0) setSection(section - 1);
    else onBack();
  };

  const locked = !!hasBooked;

  return (
    <div className="anim-in">
      <h1 className="h1 mt-16">Анкета</h1>
      <p className="lead mt-16" style={{maxWidth:620}}>
        Расскажите о себе чуть больше — это поможет нам подробнее подготовиться к консультации и дать более персонализированные советы.
      </p>

      {locked && (
        <div style={{
          display:"flex", alignItems:"flex-start", gap:12,
          padding:"14px 18px", borderRadius:10, marginTop:20, maxWidth:780,
          background:"#fef9ec", border:"1.5px solid #f5d76e",
        }}>
          <span style={{fontSize:20, lineHeight:1}}>🔒</span>
          <div>
            <div style={{fontWeight:700, fontSize:14, color:"#92400e"}}>Анкета заблокирована</div>
            <div style={{fontSize:13, color:"#78350f", marginTop:3}}>
              После бронирования изменять анкету невозможно. Если есть вопросы — свяжитесь с консультантом.
            </div>
          </div>
        </div>
      )}

      {/* Section tabs */}
      <div className="mt-24" style={{maxWidth:780,overflow:"auto",paddingBottom:8}}>
        <div className="hstack gap-8" style={{flexWrap:"nowrap"}}>
          {sections.map((s, i) => (
            <button key={i} className="chip"
                    style={{flexShrink:0, background: i===section?"var(--brand)":(i<section?"var(--brand-soft)":"#fff"), color: i===section?"#fff":(i<section?"var(--brand-deep)":"var(--ink-3)"), borderColor: i===section?"var(--brand)":"var(--line)"}}
                    onClick={() => setSection(i)}>
              <span style={{fontSize:11,fontWeight:700,opacity:.8}}>{i+1}</span> {s.title}
            </button>
          ))}
        </div>
      </div>

      <div className="card card-pad mt-24 anim-in" style={{maxWidth:780}} key={section}>
        <IntakeSectionFields section={sections[section]} intakeData={intakeData} update={update} disabled={locked}/>

        <div className="hstack mt-24" style={{gap:12,justifyContent:"space-between"}}>
          <button className="btn btn-ghost" onClick={prevSection}>
            <Icon.ArrowLeft style={{width:14,height:14}}/> Назад
          </button>
          <div style={{display:"flex",alignItems:"center",gap:12}}>
            {saveError && <span style={{fontSize:13,color:"#dc2626"}}>Ошибка сохранения</span>}
            <div className="muted" style={{fontSize:13}}>{section + 1} из {sections.length}</div>
          </div>
          {!locked && (
            <button className="btn btn-primary" onClick={nextSection} disabled={saving}>
              {saving ? "Сохранение…" : (section < sections.length - 1 ? "Далее" : "К бронированию")}
              {!saving && <Icon.Arrow style={{width:16,height:16}}/>}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

function FileUpload({ value, onChange, disabled }) {
  const inputRef = React.useRef(null);
  const [uploading, setUploading] = React.useState(false);
  const [uploadError, setUploadError] = React.useState("");

  const handleFile = async (f) => {
    if (!f) return;
    setUploadError("");
    setUploading(true);
    try {
      const token = localStorage.getItem("kiwi_session_token");
      const fd = new FormData();
      fd.append("file", f);
      const res = await fetch("/api/customer/resume", {
        method: "POST",
        headers: token ? { Authorization: `Bearer ${token}` } : {},
        body: fd,
      });
      if (!res.ok) {
        const err = await res.json().catch(() => ({}));
        setUploadError(err.detail || "Ошибка загрузки");
        return;
      }
      const data = await res.json();
      onChange({ name: data.filename, size: data.size, fileId: data.fileId });
    } catch {
      setUploadError("Ошибка сети");
    } finally {
      setUploading(false);
    }
  };

  if (value && value.fileId) {
    return (
      <div className="upload has-file">
        <div className="up-ico"><Icon.Doc style={{width:18,height:18}}/></div>
        <div className="grow">
          <b style={{fontSize:14,color:"var(--ink)"}}>{value.name}</b>
          <div className="muted" style={{fontSize:12.5,marginTop:2}}>{(value.size/1024).toFixed(0)} KB · загружено</div>
        </div>
        {!disabled && (
          <button className="btn btn-ghost" style={{height:36,fontSize:13}} onClick={() => onChange(null)}>Удалить</button>
        )}
      </div>
    );
  }

  return (
    <div>
      <div className="upload" style={{opacity: disabled || uploading ? 0.5 : 1, cursor: disabled ? "default" : "pointer", pointerEvents: disabled ? "none" : "auto"}}
           onClick={() => !uploading && !disabled && inputRef.current?.click()}>
        <input ref={inputRef} type="file" hidden accept=".pdf,.doc,.docx" disabled={disabled}
               onChange={(e) => { const f = e.target.files?.[0]; if (f) handleFile(f); e.target.value = ""; }}/>
        <div className="up-ico">
          {uploading ? <Spinner/> : <Icon.Upload style={{width:18,height:18}}/>}
        </div>
        <div style={{marginTop:10,fontSize:14.5,fontWeight:600,color:"var(--ink)"}}>
          {uploading ? "Загружаем…" : "Перетащите файл сюда или нажмите, чтобы выбрать"}
        </div>
        <div className="muted" style={{marginTop:4,fontSize:12.5}}>PDF, DOC, DOCX · до 10 МБ</div>
      </div>
      {uploadError && <div style={{fontSize:13,color:"#dc2626",marginTop:6}}>{uploadError}</div>}
    </div>
  );
}

const TIMEZONES = [
  { iana: "Pacific/Honolulu",               label: "Hawaii Time" },
  { iana: "America/Anchorage",              label: "Alaska Time" },
  { iana: "America/Los_Angeles",            label: "Pacific Time – US & Canada" },
  { iana: "America/Denver",                 label: "Mountain Time – US & Canada" },
  { iana: "America/Chicago",                label: "Central Time – US & Canada" },
  { iana: "America/New_York",               label: "Eastern Time – US & Canada" },
  { iana: "America/Halifax",                label: "Atlantic Time – Canada" },
  { iana: "America/Sao_Paulo",              label: "Brasilia" },
  { iana: "America/Argentina/Buenos_Aires", label: "Buenos Aires" },
  { iana: "Europe/London",                  label: "London" },
  { iana: "Europe/Paris",                   label: "Central European Time" },
  { iana: "Europe/Kyiv",                    label: "Eastern European Time" },
  { iana: "Europe/Moscow",                  label: "Moscow" },
  { iana: "Asia/Dubai",                     label: "Gulf Standard Time" },
  { iana: "Asia/Karachi",                   label: "Pakistan Standard Time" },
  { iana: "Asia/Kolkata",                   label: "India Standard Time" },
  { iana: "Asia/Bangkok",                   label: "Indochina Time" },
  { iana: "Asia/Singapore",                 label: "Singapore Time" },
  { iana: "Asia/Shanghai",                  label: "China Standard Time" },
  { iana: "Asia/Tokyo",                     label: "Japan Standard Time" },
  { iana: "Australia/Sydney",               label: "Australian Eastern Time" },
  { iana: "Pacific/Auckland",               label: "New Zealand Time" },
];

function TimezonePicker({ timezone, onChange }) {
  const [open, setOpen] = React.useState(false);
  const [search, setSearch] = React.useState("");
  const ref = React.useRef(null);

  React.useEffect(() => {
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, [open]);

  const entry = TIMEZONES.find(t => t.iana === timezone) || { iana: timezone, label: timezone };
  const currentTime = new Date().toLocaleTimeString("en-US", {
    timeZone: timezone, hour: "numeric", minute: "2-digit", hour12: true,
  });
  const filtered = TIMEZONES.filter(t =>
    t.label.toLowerCase().includes(search.toLowerCase()) ||
    t.iana.toLowerCase().includes(search.toLowerCase())
  );

  return (
    <div ref={ref} style={{position:"relative",display:"inline-flex"}}>
      <button
        className="btn btn-ghost"
        style={{fontSize:12.5,padding:"5px 10px",height:"auto",gap:5,color:"var(--ink-2)",fontWeight:400}}
        onClick={() => { setOpen(o => !o); setSearch(""); }}
      >
        <Icon.Globe style={{width:13,height:13,flexShrink:0,opacity:.7}}/>
        <span>{entry.label}</span>
        <span style={{opacity:.55}}>({currentTime})</span>
      </button>

      {open && (
        <div style={{
          position:"absolute",bottom:"calc(100% + 6px)",left:0,zIndex:200,
          background:"#fff",border:"1px solid var(--line)",borderRadius:10,
          boxShadow:"0 8px 32px rgba(0,0,0,.13)",width:270,
        }}>
          <div style={{padding:"10px 12px",borderBottom:"1px solid var(--line)"}}>
            <input autoFocus value={search} onChange={e => setSearch(e.target.value)}
              placeholder="Поиск таймзоны…"
              style={{width:"100%",border:"1px solid var(--line)",borderRadius:6,
                padding:"6px 10px",fontSize:13,outline:"none",boxSizing:"border-box"}}/>
          </div>
          <div style={{maxHeight:220,overflowY:"auto"}}>
            {filtered.map(t => (
              <button key={t.iana} onClick={() => { onChange(t.iana); setOpen(false); }}
                style={{display:"block",width:"100%",textAlign:"left",padding:"9px 14px",
                  fontSize:13,background: t.iana===timezone ? "var(--brand-soft)" : "none",
                  color: t.iana===timezone ? "var(--brand)" : "var(--ink)",
                  fontWeight: t.iana===timezone ? 600 : 400,
                  border:0,cursor:"pointer"}}>
                {t.label}
              </button>
            ))}
            {filtered.length === 0 && (
              <div style={{padding:"14px",color:"var(--ink-3)",fontSize:13,textAlign:"center"}}>Не найдено</div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

/* -------- Step 4: Booking calendar (Calendly API + custom UI) -------- */
function SetupBooking({ booking, setBooking, onBook, onBack, formData, intakeData }) {
  const [month, setMonth] = React.useState(() => new Date());
  const [rawSlots, setRawSlots] = React.useState(null);  // flat [{startTime, schedulingUrl}]
  const [slotsError, setSlotsError] = React.useState(false);
  const [confirming, setConfirming] = React.useState(false);
  const [timezone, setTimezone] = React.useState(
    () => Intl.DateTimeFormat().resolvedOptions().timeZone
  );

  const selectedDate = booking.date;
  const selectedTime = booking.time;

  const monthKey = `${month.getFullYear()}-${String(month.getMonth() + 1).padStart(2, "0")}`;

  React.useEffect(() => {
    setRawSlots(null);
    setSlotsError(false);
    setBooking(b => ({ ...b, date: null, time: null }));
    fetch(`/api/calendly/slots?month=${monthKey}`)
      .then(r => { if (!r.ok) throw new Error(); return r.json(); })
      .then(data => setRawSlots(data))
      .catch(() => { setRawSlots([]); setSlotsError(true); });
  }, [monthKey]);

  // Regroup when timezone changes — date/time display must stay consistent
  const slots = React.useMemo(() => {
    if (!rawSlots) return null;
    const grouped = {};
    for (const slot of rawSlots) {
      const key = new Date(slot.startTime).toLocaleDateString("sv", { timeZone: timezone });
      (grouped[key] = grouped[key] || []).push(slot);
    }
    return grouped;
  }, [rawSlots, timezone]);

  // Clear selection when timezone changes so stale date/time keys don't linger
  React.useEffect(() => {
    setBooking(b => ({ ...b, date: null, time: null }));
  }, [timezone]);

  React.useEffect(() => {
    const onMessage = (e) => {
      if (e.data?.event !== "calendly.event_scheduled") return;
      const p = e.data.payload;
      setBooking(b => ({
        ...b,
        startTime: p.event?.start_time,
        inviteeName: p.invitee?.name,
        inviteeEmail: p.invitee?.email,
        eventUri: p.event?.uri,
      }));
      const name = formData.customerName || p.invitee?.name || formData.email || "";
      const email = formData.email || p.invitee?.email || "";
      if (email) {
        fetch("/api/application", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ name, email, destination: formData.destination || "" }),
        }).catch(() => {});
      }

      // Record booking on backend (locks anketa)
      const sessionToken = localStorage.getItem("kiwi_session_token");
      const doBook = () => setTimeout(onBook, 400);
      if (sessionToken) {
        fetch("/api/customer/booking", {
          method: "POST",
          headers: { "Content-Type": "application/json", Authorization: `Bearer ${sessionToken}` },
          body: JSON.stringify({
            calendly_event_uri: p.event?.uri || null,
            scheduled_at: p.event?.start_time || null,
          }),
        }).catch(() => {}).finally(doBook);
      } else {
        doBook();
      }
    };
    window.addEventListener("message", onMessage);
    return () => window.removeEventListener("message", onMessage);
  }, []);

  const monthName = month.toLocaleString("ru-RU", { month: "long", year: "numeric" });

  const firstDay = new Date(month.getFullYear(), month.getMonth(), 1);
  let startWeekday = firstDay.getDay();
  startWeekday = startWeekday === 0 ? 6 : startWeekday - 1;
  const daysInMonth = new Date(month.getFullYear(), month.getMonth() + 1, 0).getDate();
  const days = [];
  for (let i = 0; i < startWeekday; i++) days.push(null);
  for (let i = 1; i <= daysInMonth; i++) days.push(i);
  while (days.length % 7 !== 0) days.push(null);

  const fmtKey = (d) =>
    `${month.getFullYear()}-${String(month.getMonth()+1).padStart(2,"0")}-${String(d).padStart(2,"0")}`;

  const todayKey = new Date().toLocaleDateString("sv", { timeZone: timezone });

  const isAvailable = (d) => {
    if (!d || !slots) return false;
    return fmtKey(d) >= todayKey && !!(slots[fmtKey(d)]?.length);
  };
  const isToday = (d) => !!d && fmtKey(d) === todayKey;

  const goPrev = () => setMonth(new Date(month.getFullYear(), month.getMonth() - 1, 1));
  const goNext = () => setMonth(new Date(month.getFullYear(), month.getMonth() + 1, 1));

  const slotsForDate = selectedDate ? (slots?.[fmtKey(selectedDate)] || []) : [];

  const formatDate = (d) =>
    new Date(month.getFullYear(), month.getMonth(), d)
      .toLocaleDateString("ru-RU", { day: "numeric", month: "long", weekday: "long" });

  const fmtTime = (isoStr) =>
    new Date(isoStr).toLocaleTimeString("ru-RU", { timeZone: timezone, hour: "2-digit", minute: "2-digit" });

  const loadCalendlyAndOpen = (schedulingUrl) => {
    const open = () => {
      const url = new URL(schedulingUrl);
      const fullName = intakeData?.main_name || [formData?.firstName, formData?.lastName].filter(Boolean).join(" ");
      if (fullName) url.searchParams.set("name", fullName);
      if (formData?.email) url.searchParams.set("email", formData.email);
      url.searchParams.set("hide_gdpr_banner", "1");
      url.searchParams.set("hide_event_type_details", "1");
      window.Calendly.initPopupWidget({ url: url.toString() });
      setConfirming(false);
    };

    if (window.Calendly) { open(); return; }

    if (!document.getElementById("calendly-css")) {
      const link = document.createElement("link");
      link.id = "calendly-css";
      link.rel = "stylesheet";
      link.href = "https://assets.calendly.com/assets/external/widget.css";
      document.head.appendChild(link);
    }
    const s = document.createElement("script");
    s.src = "https://assets.calendly.com/assets/external/widget.js";
    s.onload = open;
    document.head.appendChild(s);
  };

  const handleConfirm = () => {
    const slot = slotsForDate.find(s => s.startTime === selectedTime);
    if (!slot) return;
    setConfirming(true);
    loadCalendlyAndOpen(slot.schedulingUrl);
  };

  return (
    <div className="anim-in">
      <h1 className="h1 mt-16">Выберите удобное время</h1>
      <p className="lead mt-16" style={{maxWidth:620}}>
        Консультация длится 45 минут и проходит онлайн. Ссылку пришлём на email.
      </p>

      {slotsError && (
        <div style={{marginTop:16,padding:"12px 16px",background:"#fff7ed",border:"1px solid #fed7aa",borderRadius:10,fontSize:13.5,color:"#9a3412"}}>
          Не удалось загрузить расписание. Попробуйте перезагрузить страницу.
        </div>
      )}

      <div className="card card-pad mt-32" style={{maxWidth:880, position:"relative"}}>
        {rawSlots === null && (
          <div style={{position:"absolute",inset:0,zIndex:10,borderRadius:"var(--radius)",
                       background:"rgba(255,255,255,0.85)",backdropFilter:"blur(3px)",
                       WebkitBackdropFilter:"blur(3px)",
                       display:"grid",placeItems:"center"}}>
            <div className="stack" style={{alignItems:"center",gap:12}}>
              <Spinner/>
              <span style={{fontSize:13.5,color:"var(--ink-2)",fontWeight:500}}>Загружаем доступное время…</span>
            </div>
          </div>
        )}
        <div style={{display:"grid",gridTemplateColumns:"1.3fr 1fr",gap:36}} className="book-grid">

          {/* Calendar */}
          <div>
            <div className="hstack" style={{justifyContent:"space-between",marginBottom:18}}>
              <button className="btn btn-ghost" style={{width:36,height:36,padding:0}} onClick={goPrev}>
                <Icon.ArrowLeft style={{width:16,height:16}}/>
              </button>
              <b style={{textTransform:"capitalize",fontSize:16,color:"var(--ink)"}}>{monthName}</b>
              <button className="btn btn-ghost" style={{width:36,height:36,padding:0}} onClick={goNext}>
                <Icon.Arrow style={{width:16,height:16}}/>
              </button>
            </div>

            <div className="cal-grid" style={{position:"relative"}}>
              {["Пн","Вт","Ср","Чт","Пт","Сб","Вс"].map((w) => (
                <div key={w} className="cal-hd">{w}</div>
              ))}
              {days.map((d, i) => {
                if (!d) return <div key={i}/>;
                const avail = isAvailable(d);
                return (
                  <div key={i}
                       className={`cal-day ${!avail?"disabled":""} ${selectedDate===d?"sel":""} ${isToday(d)?"today":""}`}
                       onClick={() => avail && setBooking(b => ({...b, date: d, time: null}))}>
                    {d}
                  </div>
                );
              })}
            </div>

            <div className="hstack gap-12 mt-24" style={{fontSize:12.5,color:"var(--ink-3)"}}>
              <span className="hstack gap-8"><span style={{width:10,height:10,borderRadius:3,background:"var(--brand)"}}/> Выбрано</span>
              <span className="hstack gap-8"><span style={{width:10,height:10,borderRadius:3,background:"#fff",border:"1px solid var(--brand)"}}/> Сегодня</span>
              <span className="hstack gap-8"><span style={{width:10,height:10,borderRadius:3,background:"#f1f3f7"}}/> Недоступно</span>
            </div>

            <div className="mt-16">
              <TimezonePicker timezone={timezone} onChange={setTimezone}/>
            </div>
          </div>

          {/* Times */}
          <div>
            <div className="muted" style={{fontSize:12,fontWeight:600,letterSpacing:".06em",textTransform:"uppercase",marginBottom:8}}>
              {selectedDate ? "Доступное время" : "Сначала выберите дату"}
            </div>
            <b style={{fontSize:15,color:"var(--ink)",display:"block",textTransform:"capitalize"}}>
              {selectedDate ? formatDate(selectedDate) : "—"}
            </b>

            {selectedDate ? (
              slotsForDate.length > 0 ? (
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:8,marginTop:18}}>
                  {slotsForDate.map((slot) => (
                    <button key={slot.startTime}
                            className={`slot ${selectedTime===slot.startTime?"sel":""}`}
                            onClick={() => setBooking(b => ({...b, time: slot.startTime}))}>
                      {fmtTime(slot.startTime)}
                    </button>
                  ))}
                </div>
              ) : (
                <div className="muted" style={{marginTop:18,padding:"24px 16px",border:"1px dashed var(--line)",borderRadius:10,textAlign:"center",fontSize:13.5}}>
                  Нет доступного времени
                </div>
              )
            ) : (
              <div className="muted" style={{marginTop:18,padding:"24px 16px",border:"1px dashed var(--line)",borderRadius:10,textAlign:"center",fontSize:13.5}}>
                Выберите день в календаре слева
              </div>
            )}

            <hr className="divider mt-24"/>

            <div className="mt-24">
              <div className="muted" style={{fontSize:12,fontWeight:600,letterSpacing:".06em",textTransform:"uppercase",marginBottom:10}}>Что выбрано</div>
              <div className="stack gap-8" style={{fontSize:14}}>
                <div className="hstack" style={{justifyContent:"space-between"}}>
                  <span className="muted">Дата</span>
                  <b style={{color:"var(--ink)",textTransform:"capitalize"}}>{selectedDate ? formatDate(selectedDate) : "—"}</b>
                </div>
                <div className="hstack" style={{justifyContent:"space-between"}}>
                  <span className="muted">Время</span>
                  <b style={{color:"var(--ink)"}}>{selectedTime ? fmtTime(selectedTime) : "—"}</b>
                </div>
                <div className="hstack" style={{justifyContent:"space-between"}}>
                  <span className="muted">Длительность</span>
                  <b style={{color:"var(--ink)"}}>45 минут</b>
                </div>
              </div>

              <button className="btn btn-primary btn-block btn-lg mt-24"
                      disabled={!selectedDate || !selectedTime || confirming}
                      onClick={handleConfirm}>
                {confirming
                  ? <span className="hstack gap-8"><Spinner/> Открываем…</span>
                  : <>Подтвердить бронирование <Icon.Arrow style={{width:16,height:16}}/></>}
              </button>
            </div>
          </div>
        </div>
      </div>

      <div className="hstack mt-24" style={{gap:12,maxWidth:880}}>
        <button className="btn btn-ghost" onClick={onBack}>
          <Icon.ArrowLeft style={{width:14,height:14}}/> Назад к анкете
        </button>
      </div>

      <style>{`@media (max-width:780px){.book-grid{grid-template-columns:1fr !important}}`}</style>
    </div>
  );
}

window.SetupPage = SetupPage;
