const { useState, useEffect, useRef } = React;

// ─────────────────────────────────── DATA ────────────────────────────────────

const EX = {
  crunches: { name:"Скручивания", emoji:"🔥", cat:"core", sets:3, reps:15, isTime:false, eqp:"Без инвентаря", steps:["Лягте на спину, согните колени, стопы на полу","Руки за голову (не тяните за шею) или скрестите на груди","На выдохе поднимите верхнюю часть туловища к коленям","Медленно опустите, сохраняя пресс в напряжении"], tip:"Не тяните за шею — между подбородком и грудью должно быть расстояние кулака", prog:"Нед. 3–4: держите бутылку 1.5л на груди при выполнении" },
  plank: { name:"Планка", emoji:"⚡", cat:"core", sets:3, reps:20, isTime:true, eqp:"Без инвентаря", steps:["Лягте лицом вниз, поднимитесь на предплечья","Локти строго под плечами, предплечья параллельны","Поднимите тело — прямая линия от головы до пяток","Напрягите пресс, дышите равномерно"], tip:"Не поднимайте и не опускайте таз. Смотрите в пол", prog:"Каждую неделю +5 сек. Цель через месяц — 45–60 сек" },
  russian_twist: { name:"Русские скручивания", emoji:"🔄", cat:"core", sets:3, reps:20, isTime:false, eqp:"Бутылка 1.5л", steps:["Сядьте на пол, согните колени, отклонитесь ~45°","Возьмите бутылку 1.5л двумя руками перед собой","Поворачивайте корпус вправо, касайтесь бутылкой пола","Повторите влево — это 1 повторение"], tip:"Для усложнения — поднимите стопы над полом", prog:"Нед. 3–4: переходите на бутылку 6л (6кг)" },
  bicycle: { name:"Велосипед", emoji:"🚴", cat:"core", sets:3, reps:15, isTime:false, eqp:"Без инвентаря", steps:["Лягте на спину, руки за голову","Оторвите стопы от пола, колени согнуты","Тяните правый локоть к левому колену, меняйте стороны","Выполняйте плавно и ритмично"], tip:"Медленнее = эффективнее. Почувствуйте работу косых мышц", prog:"Увеличивайте темп и кол-во повторений постепенно" },
  leg_raises: { name:"Подъём ног", emoji:"🔼", cat:"core", sets:3, reps:10, isTime:false, eqp:"Без инвентаря", steps:["Лягте на спину, руки под ягодицы (поддержка поясницы)","Поднимите прямые ноги до 90°","Медленно опустите — НЕ касайтесь пола","Поясница прижата к полу всё время"], tip:"Если тяжело — слегка сгибайте колени", prog:"Нед. 3–4: задержка 2 сек в верхней точке" },
  wall_pushups: { name:"Отжимания от стены", emoji:"🤝", cat:"arms", sets:3, reps:12, isTime:false, eqp:"Стена", steps:["Встаньте на расстоянии вытянутых рук от стены","Ладони на стене чуть шире плеч на уровне груди","Сгибайте руки, приближая грудь к стене","Выпрямите руки — вернитесь в исходное положение"], tip:"Тело прямое. Чем дальше от стены — тем сложнее", prog:"Нед. 3: переходите к отжиманиям с колен" },
  bottle_curls: { name:"Сгибание рук (бицепс)", emoji:"💪", cat:"arms", sets:3, reps:12, isTime:false, eqp:"2 бутылки по 1.5л", steps:["Встаньте прямо, бутылки в руках, ладони вперёд","Прижмите локти к туловищу — они не двигаются","Согните руки, поднимая бутылки к плечам","Медленно опустите — 2 сек вниз"], tip:"Не раскачивайте корпус — работают только руки", prog:"Нед. 3: 2 бутылки 1.5л в одной руке (3кг) → Нед. 5: бутылка 6л" },
  overhead_press: { name:"Жим над головой", emoji:"🏋️", cat:"arms", sets:3, reps:12, isTime:false, eqp:"2 бутылки по 1.5л", steps:["Сядьте или встаньте прямо, спина ровная","Бутылки на уровне плеч, локти согнуты под 90°","Выжмите бутылки вверх до выпрямления рук","Медленно опустите в исходное положение"], tip:"Не прогибайте поясницу при жиме вверх", prog:"Нед. 4: переходите на бутылки 6л (6кг)" },
  lateral_raises: { name:"Разведение в стороны", emoji:"✈️", cat:"arms", sets:3, reps:15, isTime:false, eqp:"2 бутылки по 1.5л", steps:["Встаньте прямо, бутылки вдоль тела","Немного согните локти (не выпрямляйте полностью)","Поднимите руки в стороны до уровня плеч","Медленно опустите — 2–3 сек вниз"], tip:"Медленный спуск важнее быстрого подъёма", prog:"Нед. 4: переходите на бутылки 6л" },
  tricep_dips: { name:"Обр. отжимания (трицепс)", emoji:"⬇️", cat:"arms", sets:3, reps:8, isTime:false, eqp:"Стул или диван", steps:["Сядьте на край стула, руки сбоку, пальцами вперёд","Выдвиньтесь вперёд — тело держат только руки","Согните руки в локтях, опуститесь вниз","Выпрямите руки — поднимитесь"], tip:"Начните с малой амплитудой. Не перегружайте запястья", prog:"Нед. 3: увеличьте до 12–15 повторений" },
  pushups_knee: { name:"Отжимания с колен", emoji:"🏆", cat:"chest", sets:3, reps:8, isTime:false, eqp:"Без инвентаря", steps:["Встаньте на четвереньки, опуститесь на колени","Руки чуть шире плеч, тело ровное от колен до головы","Согните руки — опустите грудь к полу","Выпрямите руки — вернитесь вверх"], tip:"Это нормальная стартовая точка! После 3×15 переходите к полным отжиманиям", prog:"3×15 уверенно с колен → полные отжимания" },
  backpack_row: { name:"Тяга рюкзака", emoji:"🎒", cat:"back", sets:3, reps:10, isTime:false, eqp:"Рюкзак + 2–3 бутылки 1.5л", steps:["Наклонитесь вперёд ~45°, спина прямая и ровная","Возьмите рюкзак двумя руками снизу","Тяните рюкзак к животу, сводя лопатки вместе","Медленно опустите"], tip:"Тяните локти назад и вверх, не просто вверх", prog:"Добавляйте по 1–2 бутылки в рюкзак каждые 2 нед." },
  chest_press: { name:"Жим лёжа с бутылками", emoji:"💠", cat:"chest", sets:3, reps:15, isTime:false, eqp:"2 бутылки по 1.5л", steps:["Лягте на спину","Бутылки в руках на уровне груди, локти в стороны","Выжмите бутылки вверх до выпрямления рук","Медленно опустите (2–3 сек вниз)"], tip:"Медленный опуск так же важен, как жим вверх", prog:"Нед. 4: переходите на бутылки 6л" },
  superman: { name:"Супермен (разгибание)", emoji:"🦸", cat:"back", sets:3, reps:12, isTime:false, eqp:"Без инвентаря", steps:["Лягте лицом вниз, руки вытянуты вперёд","Одновременно поднимите грудь, руки и голову от пола","Задержитесь 1–2 секунды в верхней точке","Медленно опустите"], tip:"Важно для здоровья спины и правильной осанки!", prog:"Увеличивайте время удержания до 3–4 сек" },
};

const W = {
  A: { id:"A", name:"Тренировка А", sub:"Пресс + Руки", color:"#6366f1", light:"#eef2ff", border:"#c7d2fe",
       core:["crunches","plank","russian_twist","bicycle","leg_raises"],
       main:["wall_pushups","bottle_curls","overhead_press","lateral_raises","tricep_dips"],
       mainLabel:"Руки и Плечи" },
  B: { id:"B", name:"Тренировка Б", sub:"Пресс + Грудь/Спина", color:"#0891b2", light:"#ecfeff", border:"#a5f3fc",
       core:["crunches","plank","russian_twist","bicycle","leg_raises"],
       main:["pushups_knee","backpack_row","chest_press","superman","lateral_raises"],
       mainLabel:"Грудь и Спина" },
};

const SCHED = [
  { d:"Пн", w:"A" }, { d:"Вт", w:null, l:"Отдых" }, { d:"Ср", w:"B" },
  { d:"Чт", w:null, l:"Отдых" }, { d:"Пт", w:"A" },
  { d:"Сб", w:null, l:"Прогулка" }, { d:"Вс", w:null, l:"Отдых" },
];

const TIPS = [
  { icon:"🍽️", title:"Питание — основа всего", body:"Упражнения сжигают ~250–400 ккал за тренировку. Правильное питание даёт эффект в 3–4 раза больше. Дефицит 500 ккал/день = -2 кг в месяц. Ешьте больше белка (мясо, яйца, творог, рыба) и меньше сахара и быстрых углеводов." },
  { icon:"🔥", title:"Локальное жиросжигание — миф", body:"Скручивания укрепляют мышцы живота, но жир уходит равномерно со всего тела — нельзя целенаправленно убрать жир только с живота. Пресс проявится, когда слой жира над ним станет тоньше от общего похудения." },
  { icon:"💧", title:"Вода ускоряет похудение", body:"Пейте 2–2.5л воды в день. Вода ускоряет метаболизм, снижает ложный голод и помогает выводить продукты жиросжигания. Простой приём: стакан воды перед каждым приёмом пищи." },
  { icon:"😴", title:"Сон — это тренировка", body:"7–9 часов сна критически важны. Во сне вырабатывается гормон роста (помогает жиросжиганию и восстановлению мышц). Недосып повышает кортизол и аппетит — прогресс замедляется в 2 раза." },
  { icon:"📈", title:"Прогрессия нагрузок по неделям", body:"Нед. 1–2: освойте технику, бутылки 1.5л.\nНед. 3–4: больше повторений, начните пробовать 6л.\nНед. 5–8: рюкзак с несколькими бутылками, полные отжимания.\nНед. 9+: добавляйте подходы, новые упражнения." },
  { icon:"⏱️", title:"Отдых между подходами", body:"Пресс: 30–45 секунд\nСиловые (руки, грудь, спина): 60–90 секунд\n\nНе отдыхайте слишком долго — повышенный пульс помогает сжигать жир." },
  { icon:"🔄", title:"Разминка (5 мин) — обязательно", body:"Перед каждой тренировкой:\n• Вращения плечами — 10 раз вперёд/назад\n• Вращения запястьями и локтями\n• Боковые наклоны корпуса\n• Плавные повороты туловища\nРазминка снижает риск травм и повышает эффективность." },
  { icon:"📅", title:"Регулярность важнее идеальности", body:"3 тренировки в неделю дают результат. Пропустили — не страшно, просто продолжайте. 80% выполнения программы на протяжении 3 месяцев = отличный результат. Главное — не бросать после первых неудач." },
];

// ─────────────────────────────── COMPONENTS ──────────────────────────────────

function RestTimerOverlay({ initSec, exName, onDone }) {
  const [rem, setRem] = useState(initSec);
  useEffect(() => {
    if (rem <= 0) { onDone(); return; }
    const t = setTimeout(() => setRem(r => r - 1), 1000);
    return () => clearTimeout(t);
  }, [rem]);
  const pct = Math.min(100, ((initSec - rem) / initSec) * 100);

  return (
    <div style={{ position:"fixed",inset:0,background:"rgba(0,0,0,0.78)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:100,padding:20 }}>
      <div style={{ background:"white",borderRadius:28,padding:"36px 28px",textAlign:"center",maxWidth:300,width:"100%" }}>
        <div style={{ fontSize:11,color:"#9ca3af",textTransform:"uppercase",letterSpacing:3,marginBottom:14 }}>Отдых</div>
        <div style={{ fontSize:88,fontWeight:900,color:"#6366f1",lineHeight:1,marginBottom:6 }}>{rem}</div>
        <div style={{ fontSize:16,color:"#9ca3af",marginBottom:28 }}>секунд</div>
        <div style={{ background:"#f3f4f6",borderRadius:999,height:8,marginBottom:28,overflow:"hidden" }}>
          <div style={{ background:"#6366f1",height:"100%",width:`${pct}%`,transition:"width 1s linear",borderRadius:999 }} />
        </div>
        {exName && (
          <div style={{ fontSize:12,color:"#9ca3af",marginBottom:22 }}>
            Следующий: <strong style={{ color:"#374151" }}>{exName}</strong>
          </div>
        )}
        <button onClick={onDone}
          style={{ background:"#eef2ff",color:"#6366f1",border:"none",borderRadius:999,padding:"13px 32px",fontSize:14,fontWeight:700,cursor:"pointer" }}>
          Пропустить →
        </button>
      </div>
    </div>
  );
}

function ExerciseModal({ ex, onClose }) {
  if (!ex) return null;
  const catLabel = { core:"Пресс", arms:"Руки", chest:"Грудь", back:"Спина" }[ex.cat] || "";
  return (
    <div style={{ position:"fixed",inset:0,background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"flex-end",justifyContent:"center",zIndex:99 }} onClick={onClose}>
      <div style={{ background:"white",borderRadius:"24px 24px 0 0",padding:24,width:"100%",maxWidth:480,maxHeight:"88vh",overflowY:"auto" }}
        onClick={e => e.stopPropagation()}>
        <div style={{ width:40,height:4,background:"#e5e7eb",borderRadius:999,margin:"0 auto 22px" }} />
        <div style={{ display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:18 }}>
          <div style={{ display:"flex",alignItems:"center",gap:12 }}>
            <span style={{ fontSize:38 }}>{ex.emoji}</span>
            <div>
              <div style={{ fontSize:18,fontWeight:800,color:"#111827" }}>{ex.name}</div>
              <div style={{ fontSize:13,color:"#9ca3af",marginTop:2 }}>{catLabel}</div>
            </div>
          </div>
          <button onClick={onClose} style={{ background:"#f3f4f6",border:"none",borderRadius:100,width:34,height:34,cursor:"pointer",fontSize:15,color:"#9ca3af",display:"flex",alignItems:"center",justifyContent:"center" }}>✕</button>
        </div>
        <div style={{ display:"flex",gap:8,flexWrap:"wrap",marginBottom:22 }}>
          <span style={{ background:"#eef2ff",color:"#6366f1",borderRadius:999,padding:"6px 14px",fontSize:13,fontWeight:700 }}>
            {ex.sets} подхода × {ex.isTime ? `${ex.reps} сек` : `${ex.reps} повт.`}
          </span>
          <span style={{ background:"#fef3c7",color:"#92400e",borderRadius:999,padding:"6px 14px",fontSize:12,fontWeight:600 }}>
            🎒 {ex.eqp}
          </span>
        </div>
        <div style={{ fontSize:12,fontWeight:700,textTransform:"uppercase",letterSpacing:1.5,color:"#9ca3af",marginBottom:14 }}>Техника выполнения</div>
        {ex.steps.map((s, i) => (
          <div key={i} style={{ display:"flex",gap:12,marginBottom:12,alignItems:"flex-start" }}>
            <div style={{ minWidth:26,height:26,background:"#6366f1",color:"white",borderRadius:100,display:"flex",alignItems:"center",justifyContent:"center",fontSize:12,fontWeight:800,flexShrink:0 }}>{i+1}</div>
            <div style={{ fontSize:14,color:"#374151",lineHeight:1.55,paddingTop:4 }}>{s}</div>
          </div>
        ))}
        <div style={{ background:"#fef3c7",borderRadius:14,padding:"14px 16px",marginTop:20,marginBottom:12 }}>
          <div style={{ fontSize:13,color:"#92400e",lineHeight:1.5 }}>💡 {ex.tip}</div>
        </div>
        <div style={{ background:"#f0fdf4",borderRadius:14,padding:"14px 16px" }}>
          <div style={{ fontSize:11,fontWeight:700,textTransform:"uppercase",letterSpacing:1,color:"#16a34a",marginBottom:5 }}>📈 Прогрессия</div>
          <div style={{ fontSize:13,color:"#15803d",lineHeight:1.5 }}>{ex.prog}</div>
        </div>
      </div>
    </div>
  );
}

function ExerciseCard({ exId, doneSets, onMark, onInfo }) {
  const ex = EX[exId];
  const done = doneSets || 0;
  const isDone = done >= ex.sets;

  return (
    <div style={{ background:"white",borderRadius:16,padding:16,marginBottom:8,boxShadow:"0 1px 4px rgba(0,0,0,0.07)",border:`1.5px solid ${isDone ? "#c7d2fe" : "transparent"}`,transition:"border-color 0.3s" }}>
      <div style={{ display:"flex",gap:10,alignItems:"flex-start",marginBottom:13 }}>
        <span style={{ fontSize:26,flexShrink:0 }}>{ex.emoji}</span>
        <div style={{ flex:1,minWidth:0 }}>
          <div style={{ fontWeight:600,fontSize:14,color:isDone?"#6366f1":"#111827" }}>{ex.name}</div>
          <div style={{ fontSize:12,color:"#9ca3af",marginTop:2 }}>
            {ex.sets} подх. × {ex.isTime ? `${ex.reps} сек` : `${ex.reps} повт.`} · {ex.eqp}
          </div>
        </div>
        <button onClick={() => onInfo(exId)}
          style={{ background:"#f3f4f6",border:"none",borderRadius:8,width:28,height:28,cursor:"pointer",fontSize:14,color:"#9ca3af",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0 }}>
          ℹ
        </button>
      </div>
      <div style={{ display:"flex",gap:8,alignItems:"center" }}>
        {Array.from({ length: ex.sets }, (_, i) => {
          const setDone = i < done;
          return (
            <button key={i} onClick={() => !setDone && onMark(exId)} disabled={setDone}
              style={{ width:42,height:42,borderRadius:100,border:`2px solid ${setDone?"#6366f1":"#e5e7eb"}`,background:setDone?"#6366f1":"white",color:setDone?"white":"#d1d5db",fontWeight:800,fontSize:15,cursor:setDone?"default":"pointer",display:"flex",alignItems:"center",justifyContent:"center",transition:"all 0.2s ease",flexShrink:0 }}>
              {setDone ? "✓" : i+1}
            </button>
          );
        })}
        {isDone && <span style={{ fontSize:13,color:"#6366f1",fontWeight:700,marginLeft:4 }}>✨ Готово!</span>}
      </div>
    </div>
  );
}

// ─────────────────────────────── TABS ────────────────────────────────────────

function ScheduleTab({ setTab, setWId }) {
  return (
    <div style={{ padding:16 }}>
      <div style={{ background:"white",borderRadius:20,padding:16,marginBottom:16,boxShadow:"0 1px 4px rgba(0,0,0,0.07)" }}>
        <div style={{ fontWeight:700,fontSize:15,color:"#111827",marginBottom:14 }}>📅 Расписание недели</div>
        <div style={{ display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:6 }}>
          {SCHED.map(({ d, w, l }, i) => (
            <div key={i} style={{ textAlign:"center" }}>
              <div style={{ fontSize:10,color:"#9ca3af",marginBottom:6,fontWeight:600 }}>{d}</div>
              <div onClick={w ? () => { setWId(w); setTab("workout"); } : undefined}
                style={{ aspectRatio:"1",borderRadius:12,background:w?W[w].color:(l==="Прогулка"?"#f0fdf4":"#f3f4f6"),color:w?"white":(l==="Прогулка"?"#16a34a":"#c4c4c4"),display:"flex",alignItems:"center",justifyContent:"center",fontSize:w?14:16,fontWeight:w?800:400,cursor:w?"pointer":"default" }}>
                {w || (l==="Прогулка"?"🚶":"—")}
              </div>
            </div>
          ))}
        </div>
      </div>

      {Object.values(W).map(wk => (
        <div key={wk.id} style={{ borderRadius:20,padding:16,marginBottom:12,background:wk.light,border:`1.5px solid ${wk.border}` }}>
          <div style={{ display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:12 }}>
            <div>
              <div style={{ fontWeight:800,fontSize:16,color:"#111827" }}>{wk.name}</div>
              <div style={{ fontSize:13,color:"#6b7280",marginTop:2 }}>{wk.sub}</div>
            </div>
            <button onClick={() => { setWId(wk.id); setTab("workout"); }}
              style={{ background:wk.color,color:"white",border:"none",borderRadius:12,padding:"10px 18px",fontSize:13,fontWeight:700,cursor:"pointer" }}>
              Начать
            </button>
          </div>
          <div style={{ display:"flex",gap:14,fontSize:12,color:"#9ca3af" }}>
            <span>⏱ 35–45 мин</span><span>·</span>
            <span>10 упражнений</span><span>·</span>
            <span>{wk.id==="A"?"Пн, Пт":"Ср"}</span>
          </div>
        </div>
      ))}

      <div style={{ background:"#fff7ed",borderRadius:20,padding:16,border:"1.5px solid #fed7aa" }}>
        <div style={{ fontWeight:700,fontSize:14,color:"#c2410c",marginBottom:8 }}>📊 Ожидаемые результаты</div>
        <div style={{ fontSize:13,color:"#9a3412",lineHeight:1.7 }}>
          При соблюдении питания + 3 тренировки/нед:<br/>
          <strong>−1.5–2 кг в месяц</strong><br/>
          Цель 90 кг → <strong>6–9 месяцев</strong><br/>
          Визуальный результат через <strong>4–6 недель</strong>
        </div>
      </div>
    </div>
  );
}

function WorkoutTab({ wId, setWId, sets, markSet, resetWorkout, finishWorkout, setSelectedEx, sessionActive }) {
  const wk = W[wId];
  const allIds = [...wk.core, ...wk.main];
  const totalSets = allIds.reduce((acc, id) => acc + EX[id].sets, 0);
  const doneSets = allIds.reduce((acc, id) => acc + (sets[id] || 0), 0);
  const pct = totalSets > 0 ? Math.round((doneSets / totalSets) * 100) : 0;

  return (
    <div style={{ padding:16 }}>
      <div style={{ display:"flex",gap:8,marginBottom: sessionActive ? 8 : 16 }}>
        {Object.values(W).map(wk2 => {
          const locked = sessionActive && wId !== wk2.id;
          return (
            <button key={wk2.id} onClick={() => !locked && setWId(wk2.id)} disabled={locked}
              style={{ flex:1,padding:"12px 8px",borderRadius:14,border:`2px solid ${wId===wk2.id?wk2.color:"#e5e7eb"}`,background:wId===wk2.id?wk2.light:"white",color:wId===wk2.id?wk2.color:"#9ca3af",fontWeight:700,fontSize:13,cursor:locked?"not-allowed":"pointer",lineHeight:1.35,opacity:locked?0.45:1 }}>
              {wk2.name}<br/><span style={{ fontSize:11,fontWeight:400,opacity:0.8 }}>{wk2.sub}</span>
            </button>
          );
        })}
      </div>
      {sessionActive && (
        <div style={{ fontSize:11,color:"#9ca3af",marginBottom:16,textAlign:"center" }}>
          Завершите или сбросьте тренировку, чтобы переключиться
        </div>
      )}

      <div style={{ background:"white",borderRadius:16,padding:16,marginBottom:16,boxShadow:"0 1px 4px rgba(0,0,0,0.07)" }}>
        <div style={{ display:"flex",justifyContent:"space-between",marginBottom:10,fontSize:13 }}>
          <span style={{ color:"#6b7280",fontWeight:500 }}>Прогресс тренировки</span>
          <span style={{ fontWeight:800,color:wk.color }}>{doneSets} / {totalSets} подходов</span>
        </div>
        <div style={{ background:"#f3f4f6",borderRadius:999,height:10,overflow:"hidden" }}>
          <div style={{ background:wk.color,height:"100%",width:`${pct}%`,transition:"width 0.4s ease",borderRadius:999 }} />
        </div>
        {pct===100 && (
          <div style={{ textAlign:"center",marginTop:14,fontSize:15,fontWeight:700,color:wk.color }}>
            🎉 Отличная тренировка! Так держать!
          </div>
        )}
      </div>

      <div style={{ fontSize:11,fontWeight:700,textTransform:"uppercase",letterSpacing:1.5,color:"#9ca3af",marginBottom:10 }}>💪 Пресс и корпус</div>
      {wk.core.map(id => (
        <ExerciseCard key={id} exId={id} doneSets={sets[id]||0} onMark={markSet} onInfo={setSelectedEx} />
      ))}

      <div style={{ fontSize:11,fontWeight:700,textTransform:"uppercase",letterSpacing:1.5,color:"#9ca3af",marginBottom:10,marginTop:20 }}>
        🏋️ {wk.mainLabel}
      </div>
      {wk.main.map(id => (
        <ExerciseCard key={id} exId={id} doneSets={sets[id]||0} onMark={markSet} onInfo={setSelectedEx} />
      ))}

      <div style={{ display:"flex",gap:8,marginTop:20 }}>
        <button onClick={finishWorkout} disabled={doneSets===0}
          style={{ flex:1,padding:14,background:doneSets===0?"#f3f4f6":wk.color,border:"none",borderRadius:14,color:doneSets===0?"#c4c4c4":"white",fontSize:13,fontWeight:700,cursor:doneSets===0?"default":"pointer" }}>
          ✅ Завершить тренировку
        </button>
        <button onClick={resetWorkout}
          style={{ flex:1,padding:14,background:"#f9fafb",border:"1px solid #e5e7eb",borderRadius:14,color:"#9ca3af",fontSize:13,fontWeight:600,cursor:"pointer" }}>
          🔄 Сбросить
        </button>
      </div>
    </div>
  );
}

function ExercisesTab({ setSelectedEx }) {
  const [filter, setFilter] = useState("all");
  const cats = [
    { id:"all",label:"Все" },{ id:"core",label:"💪 Пресс" },
    { id:"arms",label:"🏋️ Руки" },{ id:"chest",label:"💠 Грудь" },{ id:"back",label:"🎒 Спина" },
  ];
  const filtered = Object.entries(EX).filter(([,ex]) => filter==="all"||ex.cat===filter);
  return (
    <div style={{ padding:16 }}>
      <div style={{ display:"flex",gap:6,marginBottom:16,overflowX:"auto",paddingBottom:2 }}>
        {cats.map(c => (
          <button key={c.id} onClick={() => setFilter(c.id)}
            style={{ flexShrink:0,padding:"7px 14px",borderRadius:999,border:"none",background:filter===c.id?"#6366f1":"#f3f4f6",color:filter===c.id?"white":"#6b7280",fontSize:13,fontWeight:600,cursor:"pointer" }}>
            {c.label}
          </button>
        ))}
      </div>
      {filtered.map(([id, ex]) => (
        <div key={id} onClick={() => setSelectedEx(id)}
          style={{ background:"white",borderRadius:16,padding:16,marginBottom:8,boxShadow:"0 1px 4px rgba(0,0,0,0.07)",cursor:"pointer",display:"flex",alignItems:"center",gap:14 }}>
          <span style={{ fontSize:28 }}>{ex.emoji}</span>
          <div style={{ flex:1,minWidth:0 }}>
            <div style={{ fontWeight:600,fontSize:14,color:"#111827" }}>{ex.name}</div>
            <div style={{ fontSize:12,color:"#9ca3af",marginTop:3 }}>{ex.sets} × {ex.isTime?`${ex.reps} сек`:`${ex.reps} повт.`} · {ex.eqp}</div>
          </div>
          <span style={{ color:"#d1d5db",fontSize:20,flexShrink:0 }}>›</span>
        </div>
      ))}
    </div>
  );
}

function TipsTab() {
  return (
    <div style={{ padding:16 }}>
      <div style={{ fontSize:11,fontWeight:700,textTransform:"uppercase",letterSpacing:2,color:"#9ca3af",marginBottom:16 }}>Советы для результата</div>
      {TIPS.map((t, i) => (
        <div key={i} style={{ background:"white",borderRadius:16,padding:16,marginBottom:10,boxShadow:"0 1px 4px rgba(0,0,0,0.07)" }}>
          <div style={{ display:"flex",gap:12,alignItems:"flex-start" }}>
            <span style={{ fontSize:28,flexShrink:0 }}>{t.icon}</span>
            <div>
              <div style={{ fontWeight:700,fontSize:14,color:"#111827",marginBottom:6 }}>{t.title}</div>
              <div style={{ fontSize:13,color:"#6b7280",lineHeight:1.65,whiteSpace:"pre-line" }}>{t.body}</div>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

function formatRu(iso) {
  if (!iso) return "";
  const months = ["янв","фев","мар","апр","май","июн","июл","авг","сен","окт","ноя","дек"];
  const [y, m, d] = iso.split("-").map(Number);
  return `${d} ${months[m-1]}`;
}

function StaleSessionDialog({ session, onContinue, onFinish, onForget }) {
  const wk = W[session.wId];
  const setsMap = (session.sets || {})[session.wId] || {};
  const done = WT.doneSetsForWorkout(wk, setsMap);
  const total = WT.totalSetsForWorkout(wk, EX);
  return (
    <div style={{ position:"fixed",inset:0,background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:120,padding:20 }}>
      <div style={{ background:"white",borderRadius:24,padding:24,maxWidth:340,width:"100%" }}>
        <div style={{ fontSize:32,textAlign:"center",marginBottom:8 }}>⏳</div>
        <div style={{ fontSize:17,fontWeight:800,color:"#111827",textAlign:"center",marginBottom:6 }}>Незаконченная тренировка</div>
        <div style={{ fontSize:13,color:"#6b7280",textAlign:"center",marginBottom:20,lineHeight:1.5 }}>
          {wk.name} от {formatRu(session.startedDate)}<br/>{done} / {total} подходов
        </div>
        <button onClick={onContinue}
          style={{ width:"100%",padding:13,borderRadius:14,border:"none",background:wk.color,color:"white",fontSize:14,fontWeight:700,cursor:"pointer",marginBottom:8 }}>
          Продолжить
        </button>
        <button onClick={onFinish}
          style={{ width:"100%",padding:13,borderRadius:14,border:`2px solid ${wk.color}`,background:"white",color:wk.color,fontSize:14,fontWeight:700,cursor:"pointer",marginBottom:8 }}>
          Завершить и начать новую
        </button>
        <button onClick={onForget}
          style={{ width:"100%",padding:13,borderRadius:14,border:"none",background:"#f9fafb",color:"#9ca3af",fontSize:13,fontWeight:600,cursor:"pointer" }}>
          Забыть
        </button>
      </div>
    </div>
  );
}

function ProgressTab({ history }) {
  const today = todayIso();
  const streak = WT.computeStreak(history, SCHED, today);
  const thisWeek = WT.workoutsThisWeek(history, today);
  const lastAgo = WT.lastTrainedDaysAgo(history, today);

  // Build last-30-days cells (oldest -> newest)
  const cells = [];
  const start = new Date(today + "T00:00:00");
  start.setDate(start.getDate() - 29);
  const byDate = {};
  history.forEach(h => { byDate[h.date] = h.wId; });
  for (let i = 0; i < 30; i++) {
    const d = new Date(start);
    d.setDate(start.getDate() + i);
    const iso = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
    cells.push({ iso, wId: byDate[iso] || null });
  }

  const stat = (label, value) => (
    <div style={{ flex:1,background:"white",borderRadius:16,padding:"16px 8px",textAlign:"center",boxShadow:"0 1px 4px rgba(0,0,0,0.07)" }}>
      <div style={{ fontSize:24,fontWeight:900,color:"#6366f1" }}>{value}</div>
      <div style={{ fontSize:11,color:"#9ca3af",marginTop:4 }}>{label}</div>
    </div>
  );

  return (
    <div style={{ padding:16 }}>
      <div style={{ display:"flex",gap:8,marginBottom:16 }}>
        {stat("🔥 серия", streak)}
        {stat("всего", history.length)}
        {stat("за неделю", thisWeek)}
      </div>

      <div style={{ fontSize:13,color:"#6b7280",marginBottom:16,textAlign:"center" }}>
        {lastAgo === null ? "Ещё нет тренировок" :
         lastAgo === 0 ? "Последняя тренировка: сегодня" :
         `Последняя тренировка: ${lastAgo} дн. назад`}
      </div>

      <div style={{ background:"white",borderRadius:16,padding:16,marginBottom:16,boxShadow:"0 1px 4px rgba(0,0,0,0.07)" }}>
        <div style={{ fontSize:12,fontWeight:700,color:"#9ca3af",textTransform:"uppercase",letterSpacing:1,marginBottom:12 }}>Последние 30 дней</div>
        <div style={{ display:"grid",gridTemplateColumns:"repeat(10,1fr)",gap:5 }}>
          {cells.map(c => (
            <div key={c.iso} title={c.iso}
              style={{ aspectRatio:"1",borderRadius:6,background:c.wId ? (W[c.wId]?.color || "#6366f1") : "#f3f4f6" }} />
          ))}
        </div>
      </div>

      <div style={{ fontSize:12,fontWeight:700,color:"#9ca3af",textTransform:"uppercase",letterSpacing:1,marginBottom:10 }}>История</div>
      {history.length === 0 && (
        <div style={{ color:"#9ca3af",fontSize:13,textAlign:"center",padding:20 }}>Пока пусто. Завершите тренировку!</div>
      )}
      {history.slice(0, 30).map((h, i) => (
        <div key={i} style={{ background:"white",borderRadius:14,padding:"12px 16px",marginBottom:8,boxShadow:"0 1px 4px rgba(0,0,0,0.07)",display:"flex",alignItems:"center",gap:12 }}>
          <div style={{ width:10,height:10,borderRadius:99,background:W[h.wId]?.color || "#9ca3af",flexShrink:0 }} />
          <div style={{ flex:1 }}>
            <div style={{ fontSize:14,fontWeight:700,color:"#111827" }}>{W[h.wId]?.name || h.wId}</div>
            <div style={{ fontSize:12,color:"#9ca3af" }}>{formatRu(h.date)}</div>
          </div>
          <div style={{ fontSize:13,fontWeight:700,color: h.doneSets>=h.totalSets ? "#16a34a" : "#9ca3af" }}>
            {h.doneSets}/{h.totalSets}
          </div>
        </div>
      ))}
    </div>
  );
}

function BottomNav({ tab, setTab, color }) {
  const items = [
    { id:"sched",label:"Расписание",emoji:"📅" },
    { id:"workout",label:"Тренировка",emoji:"🏋️" },
    { id:"exercises",label:"Упражнения",emoji:"📚" },
    { id:"progress",label:"Прогресс",emoji:"📈" },
    { id:"tips",label:"Советы",emoji:"💡" },
  ];
  return (
    <div style={{ position:"fixed",bottom:0,left:"50%",transform:"translateX(-50%)",width:"100%",maxWidth:480,background:"white",borderTop:"1px solid #f3f4f6",display:"flex",padding:"8px 0 12px",zIndex:50 }}>
      {items.map(it => (
        <button key={it.id} onClick={() => setTab(it.id)}
          style={{ flex:1,border:"none",background:"none",cursor:"pointer",display:"flex",flexDirection:"column",alignItems:"center",gap:3,padding:"6px 0",color:tab===it.id?color:"#d1d5db",transition:"color 0.2s" }}>
          <span style={{ fontSize:22 }}>{it.emoji}</span>
          <span style={{ fontSize:10,fontWeight:tab===it.id?700:500 }}>{it.label}</span>
        </button>
      ))}
    </div>
  );
}

// ─────────────────────────────── HELPERS ─────────────────────────────────────

function todayIso() {
  const d = new Date();
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

function normalize(doc) {
  const base = WT.emptyState();
  return {
    currentSession: {
      wId: doc?.currentSession?.wId ?? null,
      sets: { A: {}, B: {}, ...(doc?.currentSession?.sets || {}) },
      startedDate: doc?.currentSession?.startedDate ?? null,
    },
    history: Array.isArray(doc?.history) ? doc.history : base.history,
  };
}

// ─────────────────────────────────── LOGIN ───────────────────────────────────

function Login({ onSuccess }) {
  const [pw, setPw] = useState("");
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);

  async function submit(e) {
    e.preventDefault();
    setBusy(true); setErr("");
    try {
      const r = await fetch("/api/login", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ password: pw }),
      });
      if (r.ok) {
        localStorage.setItem("wt_token", pw);
        onSuccess(pw);
      } else if (r.status === 401) {
        setErr("Неверный пароль");
      } else {
        setErr("Ошибка входа. Попробуйте ещё раз");
      }
    } catch {
      setErr("Нет соединения");
    } finally {
      setBusy(false);
    }
  }

  return (
    <div style={{ fontFamily:"system-ui,sans-serif",minHeight:"100vh",background:"#6366f1",display:"flex",alignItems:"center",justifyContent:"center",padding:20 }}>
      <form onSubmit={submit} style={{ background:"white",borderRadius:24,padding:"32px 24px",width:"100%",maxWidth:360,boxShadow:"0 10px 40px rgba(0,0,0,0.2)" }}>
        <div style={{ fontSize:40,textAlign:"center",marginBottom:8 }}>🏋️</div>
        <div style={{ fontSize:20,fontWeight:800,textAlign:"center",color:"#111827",marginBottom:4 }}>Домашний тренер</div>
        <div style={{ fontSize:13,color:"#9ca3af",textAlign:"center",marginBottom:24 }}>Введите пароль для входа</div>
        <input type="password" value={pw} onChange={e => setPw(e.target.value)} placeholder="Пароль" autoFocus
          style={{ width:"100%",boxSizing:"border-box",padding:"14px 16px",borderRadius:14,border:"2px solid #e5e7eb",fontSize:16,marginBottom:12,outline:"none" }} />
        {err && <div style={{ color:"#dc2626",fontSize:13,marginBottom:12,textAlign:"center" }}>{err}</div>}
        <button type="submit" disabled={busy || !pw}
          style={{ width:"100%",padding:14,borderRadius:14,border:"none",background:busy||!pw?"#c7d2fe":"#6366f1",color:"white",fontSize:15,fontWeight:700,cursor:busy||!pw?"default":"pointer" }}>
          {busy ? "Проверка…" : "Войти"}
        </button>
      </form>
    </div>
  );
}

// ─────────────────────────────────── APP ─────────────────────────────────────

function App({ token, onLogout }) {
  const [tab, setTab] = useState("sched");
  const [wId, setWId] = useState("A");
  const [state, setState] = useState(() => WT.emptyState());
  const [loaded, setLoaded] = useState(false);
  const [saveErr, setSaveErr] = useState(false);
  const [restTimer, setRestTimer] = useState(null);
  const [selectedEx, setSelectedEx] = useState(null);
  const [showStale, setShowStale] = useState(false);
  const lastSaved = useRef(null); // serialized doc last persisted, to skip no-op PUTs

  // Load from cloud (fall back to local cache when offline)
  useEffect(() => {
    let alive = true;
    // Apply a loaded doc: sync wId to the session's workout (preserving the
    // wId === currentSession.wId invariant that markSet relies on) and decide
    // whether to resume or prompt. Used by both the cloud and offline paths.
    function applyDoc(doc) {
      const doc2 = normalize(doc);
      lastSaved.current = JSON.stringify(doc2); // freshly loaded == already saved
      setState(doc2);
      const decision = WT.decideOnOpen(doc2, todayIso());
      if (decision.action === "prompt") { setShowStale(true); setWId(doc2.currentSession.wId); setTab("workout"); }
      else if (decision.action === "resume") { setWId(doc2.currentSession.wId || "A"); setTab("workout"); }
    }
    (async () => {
      try {
        const r = await fetch("/api/state", { headers: { authorization: `Bearer ${token}` } });
        if (r.status === 401) { onLogout(); return; }
        const doc = await r.json();
        if (alive) applyDoc(doc);
      } catch {
        const cached = localStorage.getItem("wt_state");
        if (cached && alive) applyDoc(JSON.parse(cached));
      } finally {
        if (alive) setLoaded(true);
      }
    })();
    return () => { alive = false; };
  }, [token]);

  // Persist (debounced) whenever state changes after first load
  useEffect(() => {
    if (!loaded) return;
    const str = JSON.stringify(state);
    localStorage.setItem("wt_state", str);
    if (str === lastSaved.current) return; // nothing changed since last save
    const t = setTimeout(async () => {
      try {
        const r = await fetch("/api/state", {
          method: "PUT",
          headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
          body: str,
        });
        if (r.status === 401) { onLogout(); return; }
        if (r.ok) lastSaved.current = str;
        setSaveErr(!r.ok);
      } catch {
        setSaveErr(true);
      }
    }, 1500);
    return () => clearTimeout(t);
  }, [state, loaded, token]);

  const wk = W[wId];
  const sets = (state.currentSession.sets || {})[wId] || {};
  const sessionActive = WT.sessionHasProgress(state.currentSession);

  // Switching workouts is locked while a session has progress, so finishing
  // can't silently drop the other workout's logged sets.
  function chooseWorkout(id) {
    const cs = state.currentSession;
    if (sessionActive && cs.wId && id !== cs.wId) return;
    setWId(id);
  }

  function markSet(exId) {
    const ex = EX[exId];
    const wSets = (state.currentSession.sets || {})[wId] || {};
    if ((wSets[exId] || 0) >= ex.sets) return;
    const projected = { ...wSets, [exId]: (wSets[exId] || 0) + 1 };
    const completed =
      WT.doneSetsForWorkout(W[wId], projected) >= WT.totalSetsForWorkout(W[wId], EX);
    setState(prev => {
      const cs = prev.currentSession;
      const pSets = (cs.sets || {})[wId] || {};
      const curr = pSets[exId] || 0;
      if (curr >= ex.sets) return prev;
      const nextSets = { ...cs.sets, [wId]: { ...pSets, [exId]: curr + 1 } };
      const updated = { ...prev, currentSession: { ...cs, wId, sets: nextSets, startedDate: todayIso() } };
      const done = WT.doneSetsForWorkout(W[wId], nextSets[wId]);
      const total = WT.totalSetsForWorkout(W[wId], EX);
      if (done >= total) {
        return WT.endSession(updated, true, todayIso(), W, EX);
      }
      return updated;
    });
    if (!completed) setRestTimer({ exId, sec: wk.core.includes(exId) ? 45 : 60 });
  }

  function resetWorkout() {
    setState(prev => WT.endSession(prev, false, todayIso(), W, EX));
  }

  function finishWorkout() {
    setState(prev => WT.endSession(prev, true, todayIso(), W, EX));
  }

  function staleContinue() {
    setState(prev => WT.continueSession(prev, todayIso()));
    setShowStale(false);
  }
  function staleFinish() {
    setState(prev => WT.endSession(prev, true, todayIso(), W, EX));
    setShowStale(false);
  }
  function staleForget() {
    setState(prev => WT.endSession(prev, false, todayIso(), W, EX));
    setShowStale(false);
  }

  return (
    <div style={{ fontFamily:"'Inter',system-ui,sans-serif",height:"100vh",background:"#f9fafb",display:"flex",flexDirection:"column",maxWidth:480,margin:"0 auto",overflow:"hidden" }}>
      <div style={{ background:wk.color,padding:"28px 20px 16px",color:"white",flexShrink:0,transition:"background 0.4s ease" }}>
        <div style={{ display:"flex",justifyContent:"space-between",alignItems:"flex-start" }}>
          <div>
            <div style={{ fontSize:10,textTransform:"uppercase",letterSpacing:3,opacity:0.65,marginBottom:4 }}>Домашний тренер</div>
            <div style={{ fontSize:21,fontWeight:800 }}>Программа тренировок</div>
            <div style={{ fontSize:12,opacity:0.75,marginTop:4 }}>190 см · 110 → 90 кг · Верхний корпус</div>
          </div>
          <button onClick={onLogout} title="Выйти"
            style={{ background:"rgba(255,255,255,0.18)",border:"none",borderRadius:10,color:"white",padding:"8px 10px",fontSize:16,cursor:"pointer",flexShrink:0 }}>⎋</button>
        </div>
        {saveErr && <div style={{ marginTop:8,fontSize:11,background:"rgba(0,0,0,0.18)",borderRadius:8,padding:"4px 8px",display:"inline-block" }}>⚠️ не сохранено</div>}
      </div>

      <div style={{ flex:1,overflowY:"auto",paddingBottom:80 }}>
        {tab==="sched"    && <ScheduleTab setTab={setTab} setWId={chooseWorkout} />}
        {tab==="workout"  && <WorkoutTab wId={wId} setWId={chooseWorkout} sets={sets} markSet={markSet} resetWorkout={resetWorkout} finishWorkout={finishWorkout} setSelectedEx={setSelectedEx} sessionActive={sessionActive} />}
        {tab==="exercises"&& <ExercisesTab setSelectedEx={setSelectedEx} />}
        {tab==="progress" && <ProgressTab history={state.history} />}
        {tab==="tips"     && <TipsTab />}
      </div>

      <BottomNav tab={tab} setTab={setTab} color={wk.color} />

      {restTimer && (
        <RestTimerOverlay initSec={restTimer.sec} exName={EX[restTimer.exId]?.name} onDone={() => setRestTimer(null)} />
      )}
      {selectedEx && (
        <ExerciseModal ex={EX[selectedEx]} onClose={() => setSelectedEx(null)} />
      )}
      {showStale && state.currentSession.wId && (
        <StaleSessionDialog
          session={state.currentSession}
          onContinue={staleContinue}
          onFinish={staleFinish}
          onForget={staleForget}
        />
      )}
    </div>
  );
}

// ─────────────────────────────────── ROOT ────────────────────────────────────

function Root() {
  const [token, setToken] = useState(() => localStorage.getItem("wt_token"));
  if (!token) return <Login onSuccess={setToken} />;
  return <App token={token} onLogout={() => { localStorage.removeItem("wt_token"); setToken(null); }} />;
}

ReactDOM.createRoot(document.getElementById("root")).render(<Root />);
