/* =====================================================================
   ЛИНА — цифровой гайд для мамы новорождённого + AI-неонатолог
   Single-file React app. Запускается через index.html (CDN React+Babel+Tailwind).
   Все данные — в localStorage. Claude API вызывается напрямую из браузера.
   ⚠️ Приложение — помощник, не замена врачу.
   ===================================================================== */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ------------------------------------------------------------------ */
/*  КОНСТАНТЫ И ДАННЫЕ                                                  */
/* ------------------------------------------------------------------ */

const LS = {
  profile: 'baby_profile',
  plans: 'weekly_plans',
  feeding: 'feeding_log',
  sleep: 'sleep_log',
  diaper: 'diaper_log',
  weight: 'weight_measurements',
  chat: 'chat_history',
  tasks: 'completed_tasks',
  dismissed: 'dismissed_alerts',
  apiKey: 'anthropic_api_key',
  schedule: 'day_schedule',
};

const MODEL = 'claude-sonnet-4-6';   // актуальная Sonnet (старая claude-sonnet-4-20250514 выведена из обслуживания)

// Таблица объёмов кормления (смесь)
const FORMULA_VOLUMES = [
  { fromDay: 0,   toDay: 3,   mlPerKg: 30,  mealsPerDay: 8,  note: 'Первые дни — малые объёмы, часто' },
  { fromDay: 4,   toDay: 7,   mlPerKg: 50,  mealsPerDay: 8,  note: 'Объём нарастает постепенно' },
  { fromDay: 8,   toDay: 14,  mlPerKg: 70,  mealsPerDay: 7,  note: 'Приближаемся к норме' },
  { fromDay: 15,  toDay: 30,  mlPerKg: 80,  mealsPerDay: 7,  note: 'Объём по 1/5 от веса в сутки' },
  { fromDay: 31,  toDay: 60,  mlPerKg: 120, mealsPerDay: 6,  note: '' },
  { fromDay: 61,  toDay: 90,  mlPerKg: 150, mealsPerDay: 6,  note: '' },
  { fromDay: 91,  toDay: 150, mlPerKg: 180, mealsPerDay: 5,  note: '' },
  { fromDay: 151, toDay: 180, mlPerKg: 200, mealsPerDay: 5,  note: 'Готовимся к прикорму' },
];

// Перцентили веса ВОЗ (кг), упрощённо, по месяцам 0–12 (усреднённые)
const WHO_WEIGHT_PERCENTILES = {
  0:  { p3: 2.5, p15: 2.9, p50: 3.3,  p85: 3.9,  p97: 4.4 },
  1:  { p3: 3.4, p15: 3.9, p50: 4.5,  p85: 5.1,  p97: 5.7 },
  2:  { p3: 4.4, p15: 5.0, p50: 5.6,  p85: 6.3,  p97: 7.1 },
  3:  { p3: 5.1, p15: 5.7, p50: 6.4,  p85: 7.2,  p97: 8.0 },
  4:  { p3: 5.6, p15: 6.2, p50: 7.0,  p85: 7.9,  p97: 8.7 },
  5:  { p3: 6.1, p15: 6.7, p50: 7.5,  p85: 8.4,  p97: 9.3 },
  6:  { p3: 6.4, p15: 7.1, p50: 7.9,  p85: 8.9,  p97: 9.8 },
  7:  { p3: 6.7, p15: 7.4, p50: 8.3,  p85: 9.3,  p97: 10.3 },
  8:  { p3: 6.9, p15: 7.7, p50: 8.6,  p85: 9.6,  p97: 10.7 },
  9:  { p3: 7.1, p15: 7.9, p50: 8.9,  p85: 10.0, p97: 11.0 },
  10: { p3: 7.4, p15: 8.2, p50: 9.2,  p85: 10.3, p97: 11.4 },
  11: { p3: 7.6, p15: 8.4, p50: 9.4,  p85: 10.5, p97: 11.7 },
  12: { p3: 7.7, p15: 8.6, p50: 9.6,  p85: 10.8, p97: 12.0 },
};

// Нормы сна по возрасту (часы/сутки)
const SLEEP_NORMS = [
  { label: '0–1 мес',  total: '16–18 ч', day: '8–9 ч (4–5 снов)', night: '8–9 ч с пробуждениями' },
  { label: '1–3 мес',  total: '14–17 ч', day: '6–7 ч (3–4 сна)',  night: '8–10 ч' },
  { label: '3–6 мес',  total: '14–15 ч', day: '4–5 ч (3 сна)',    night: '10–11 ч' },
  { label: '6–9 мес',  total: '13–14 ч', day: '3–4 ч (2 сна)',    night: '10–11 ч' },
  { label: '9–12 мес', total: '13–14 ч', day: '2.5–3 ч (2 сна)',  night: '11 ч' },
];

// Фразы дня
const DAILY_PHRASES = [
  { fromDay: 0,   toDay: 3,   text: '{babyName} только пришёл в этот мир. Ты уже делаешь невозможное — просто быть рядом.' },
  { fromDay: 4,   toDay: 7,   text: 'Первая неделя — самая сложная. Ты справляешься лучше, чем думаешь.' },
  { fromDay: 8,   toDay: 14,  text: '{babyName} начинает узнавать твой голос. Говори с малышом — это его любимая музыка.' },
  { fromDay: 15,  toDay: 21,  text: 'Сегодня попробуйте вместе полежать на животике. Это первый шаг к большим свершениям.' },
  { fromDay: 22,  toDay: 30,  text: 'Скоро {babyName} подарит первую улыбку. Эти глаза уже ищут именно тебя.' },
  { fromDay: 31,  toDay: 45,  text: 'Месяц позади. Посмотри назад — сколько вы уже прошли вместе.' },
  { fromDay: 46,  toDay: 60,  text: 'Колики — это марафон, а не спринт. Дыши. Это обязательно пройдёт.' },
  { fromDay: 61,  toDay: 90,  text: '{babyName} учится «разговаривать» — гуление это начало большого диалога.' },
  { fromDay: 91,  toDay: 120, text: 'Малыш всё крепче держит голову и тянется к миру. Ты — его опора.' },
  { fromDay: 121, toDay: 180, text: 'Каждый день {babyName} открывает что-то новое. И ты рядом в каждом открытии.' },
  { fromDay: 181, toDay: 99999, text: 'Полгода чудес позади. Ты прошла большой путь, мама. 🤍' },
];

// Карточки «Сейчас важно» по возрасту
const AGE_CARDS = [
  { fromDay: 0, toDay: 3, cards: [
    { icon: '🔴', title: 'Пуповинный остаток', text: 'Не мочить, обрабатывать хлоргексидином 1–2 раза/день. Следить за покраснением и запахом. Отпадёт сама на 7–14 день.' },
    { icon: '🟡', title: 'Физиологическая желтуха', text: 'Может появиться на 2–4 день, пик на 3–5, исчезает к 2 неделям. Фотолечение — если желтизна доходит до стоп. Покажите малыша врачу.' },
    { icon: '🟢', title: 'Первый стул (меконий)', text: 'Чёрный или тёмно-зелёный — это норма. К 3–4 дню переходит в жёлтый.' },
    { icon: '💧', title: 'Потеря веса', text: 'Физиологическая потеря до 7–10% от веса при рождении — норма. Восстановление к 10–14 дням.' },
  ]},
  { fromDay: 4, toDay: 7, cards: [
    { icon: '🍼', title: 'Кормление (смесь)', text: 'Первые 10 дней объём в сутки ≈ день жизни × 80 (если вес >3200 г). Кормить каждые 3–3.5 часа ≈ 7–8 раз. Точный объём — в калькуляторе на вкладке «Уход».' },
    { icon: '🤱', title: 'Кормление (ГВ)', text: 'Кормить по требованию, не менее 8–12 раз/сутки. Признак достаточности — 6+ мокрых подгузников в день.' },
    { icon: '👃', title: 'Уход за носиком', text: 'Аспиратор — при необходимости. Физраствор по 1–2 капли в каждую ноздрю перед едой.' },
    { icon: '🛁', title: 'Купание', text: 'Первый раз — после отпадения пуповины (или раньше с зажимом, если разрешил педиатр). Вода 37°C, 5–7 минут. Без мыла ежедневно, с детским мылом 2–3 раза в неделю.' },
  ]},
  { fromDay: 8, toDay: 14, cards: [
    { icon: '⚖️', title: 'Контроль веса', text: 'Вес должен восстановиться до значения при рождении к 10–14 дню.' },
    { icon: '🌡️', title: 'Температура', text: 'Норма 36.3–37.4°C ректально. При 38°C и выше — звоните педиатру.' },
    { icon: '👶', title: 'Пупочная ранка', text: 'Обрабатывать после купания. Корочки — норма. Мокнутие, запах, краснота — к врачу.' },
    { icon: '🔊', title: 'Первые звуки', text: 'Крик — единственная коммуникация. Голодный (ритмичный нарастающий), боль (резкий пронзительный), усталость (ноющий).' },
  ]},
  { fromDay: 15, toDay: 21, cards: [
    { icon: '🫃', title: 'Время на животике', text: 'Начинать с 1–2 минут, 3–4 раза в день на твёрдой поверхности, когда малыш бодрствует и сыт. Укрепляет шею и плечи.' },
    { icon: '👁️', title: 'Зрение', text: 'Видит на расстоянии 20–30 см. Показывайте чёрно-белые контрастные картинки.' },
    { icon: '🎵', title: 'Слух и голос', text: 'Реагирует на мамин голос. Говорите, пойте, комментируйте действия.' },
    { icon: '💊', title: 'Витамин D', text: 'Начинать с 10–14 дня жизни, 500 МЕ/сутки — по назначению педиатра.' },
  ]},
  { fromDay: 22, toDay: 30, cards: [
    { icon: '🍼', title: 'Кормление (смесь)', text: 'Объём растёт. Ориентир: 1/5 от веса тела в сутки ÷ количество кормлений.' },
    { icon: '😊', title: 'Социальная улыбка', text: 'Появляется около 4–6 недель. Пока улыбка чаще рефлекторная.' },
    { icon: '💆', title: 'Массаж', text: 'Лёгкие поглаживания после купания, 5–7 минут. Направление — от периферии к центру.' },
    { icon: '🧠', title: 'Колики', text: 'Пик в 2–6 недель. Газики — норма. «Поза тигра» (животом на руке), тепло на живот, массаж по часовой стрелке.' },
  ]},
  { fromDay: 31, toDay: 56, cards: [
    { icon: '📅', title: 'Плановые осмотры', text: '1 месяц: педиатр, невролог, офтальмолог, ортопед, УЗИ тазобедренных суставов, УЗИ головы (нейросонография).' },
    { icon: '💉', title: 'Прививки', text: 'В 2 месяца — первая вакцинация (по нац. календарю). Заранее обсудите с педиатром жаропонижающее в дозе по весу.' },
    { icon: '🌙', title: 'Режим сна', text: 'Ночной сон удлиняется, но пока без гарантий. Норма 0–3 мес — 14–17 часов/сутки.' },
    { icon: '👁️', title: 'Слежение взглядом', text: 'Начинает следить за предметом, поворачивая голову до 180°.' },
  ]},
  { fromDay: 57, toDay: 120, cards: [
    { icon: '🤸', title: 'Переворот на бок', text: 'Готовится к перевороту. Помогайте лёгкими упражнениями, не оставляйте одного на высоте.' },
    { icon: '😊', title: 'Комплекс оживления', text: 'Улыбается, гулит, активно двигает ручками и ножками в ответ на общение.' },
    { icon: '🍼', title: 'Кормление (смесь)', text: '120–180 мл × 5–6 раз. Продолжайте ориентироваться на вес и аппетит.' },
    { icon: '🗣️', title: 'Гуление', text: 'Появляются певучие «агу». Разговаривайте с малышом как можно больше.' },
  ]},
  { fromDay: 121, toDay: 99999, cards: [
    { icon: '🤸', title: 'Перевороты', text: 'Осваивает перевороты со спины на живот и обратно. Безопасность на пеленальном столике — прежде всего.' },
    { icon: '🥄', title: 'Подготовка к прикорму', text: 'Ближе к 6 месяцам — знакомство с прикормом по рекомендации педиатра. Грудь/смесь остаются основой.' },
    { icon: '🧸', title: 'Хватание', text: 'Тянется к игрушкам, тащит в рот. Предлагайте безопасные прорезыватели.' },
    { icon: '😴', title: 'Регресс сна', text: 'Около 4 месяцев сон меняет структуру — это нормально и временно.' },
  ]},
];

// Алерты по возрасту
const AGE_ALERTS = [
  { id: 'umb-1',  fromDay: 1,  toDay: 2,  type: 'info',      category: 'care',        title: 'Пупочный зажим', message: 'Не мочить, наблюдать за остатком пуповины.' },
  { id: 'umb-2',  fromDay: 3,  toDay: 6,  type: 'info',      category: 'care',        title: 'Уход за пупочком', message: 'Обрабатывай пупочек хлоргексидином 1 раз после купания.' },
  { id: 'umb-3',  fromDay: 7,  toDay: 14, type: 'milestone', category: 'care',        title: 'Пупок отпадает', message: 'Остаток пуповины обычно отпадает на 7–14 день. Если не отпал к 3 неделям — скажи педиатру.' },
  { id: 'umb-4',  fromDay: 10, toDay: 16, type: 'info',      category: 'care',        title: 'Заживление ранки', message: 'Пупочная ранка заживает — продолжай обрабатывать до полного заживления.' },
  { id: 'tum-1',  fromDay: 15, toDay: 15, type: 'milestone', category: 'development', title: 'Старт «на животике»!', message: 'Сегодня первый раз кладём на животик! 1–2 минуты, 3 раза в день.' },
  { id: 'tum-2',  fromDay: 21, toDay: 23, type: 'info',      category: 'development', title: 'Больше времени на животике', message: 'Увеличь время на животике до 3–5 минут за подход.' },
  { id: 'tum-3',  fromDay: 42, toDay: 45, type: 'milestone', category: 'development', title: 'Удержание головы', message: 'Малыш уже должен удерживать голову лёжа на животе несколько секунд.' },
  { id: 'tum-4',  fromDay: 56, toDay: 59, type: 'info',      category: 'development', title: 'До 10 минут', message: 'Время на животике — до 10 минут 3–4 раза в день.' },
  { id: 'vd-1',   fromDay: 10, toDay: 14, type: 'info',      category: 'health',      title: 'Витамин D', message: 'Начинай давать витамин D 500 МЕ ежедневно — посоветуйся с педиатром.' },
  { id: 'chk-1',  fromDay: 28, toDay: 31, type: 'milestone', category: 'health',      title: '1 месяц!', message: 'Время первого планового осмотра: педиатр + невролог + окулист + УЗИ.' },
  { id: 'dev-1',  fromDay: 28, toDay: 42, type: 'milestone', category: 'development', title: 'Социальная улыбка', message: 'Малыш скоро улыбнётся тебе осознанно. Лови этот момент 🤍' },
  { id: 'col-1',  fromDay: 42, toDay: 56, type: 'warning',   category: 'health',      title: 'Колики в пике', message: 'Держись — пик колик. Это пройдёт к 3 месяцам.' },
  { id: 'vac-1',  fromDay: 56, toDay: 62, type: 'warning',   category: 'health',      title: 'Первые прививки', message: 'В 2 месяца — вакцинация. Обсуди с педиатром жаропонижающее по весу.' },
  { id: 'dev-2',  fromDay: 85, toDay: 95, type: 'milestone', category: 'development', title: 'Гуление и смех', message: 'Малыш начинает гулить и смеяться — разговаривай с ним как можно больше.' },
  { id: 'dev-3',  fromDay: 115, toDay: 125, type: 'warning', category: 'development', title: 'Скоро перевернётся!', message: 'Не оставляй одного на пеленальном столике ни на секунду.' },
];

// Энциклопедия ухода
const ENCYCLOPEDIA = [
  { id: 'bath', icon: '🛁', name: 'Купание', articles: [
    { q: 'Первое купание: когда и как', a: [
      'Когда: после отпадения пуповинного остатка, либо раньше с зажимом — если разрешил педиатр.',
      'Температура воды — 37°C (проверь термометром или локтем). Температура в комнате — 24–26°C.',
      'Последовательность: опускай малыша медленно, поддерживая головку и шейку. Сначала ополосни, затем при необходимости — детское мыло.',
      'Время: 5–7 минут для новорождённого. Сразу заверни в тёплое полотенце с капюшоном.',
    ]},
    { q: 'Ежедневный уход: глаза, нос, уши, ногти', a: [
      'Глаза: ватным диском с кипячёной водой, от внешнего угла к внутреннему, отдельный диск на каждый глаз.',
      'Нос: ватные турунды, при корочках — капля физраствора. Не используй ватные палочки глубоко.',
      'Уши: протирай только ушную раковину снаружи. Внутрь ничего не вводи.',
      'Ногти: подстригай детскими ножницами с закруглёнными концами, лучше во время сна.',
    ]},
    { q: 'Детская косметика: что можно', a: [
      'До 1 месяца — минимум средств. Чистая вода чаще всего достаточна.',
      'Подходят: детское мыло без отдушек, крем под подгузник, детское масло для складочек.',
      'Избегай: взрослой косметики, спиртовых лосьонов, ароматизированных средств.',
    ]},
    { q: 'Складочки и опрелости', a: [
      'После купания тщательно просушивай складочки промакивающими движениями.',
      'Обрабатывай детским кремом или маслом. Устраивай воздушные ванны 5–10 минут.',
      'Покраснение, мокнутие, не проходящая опрелость — повод показать педиатру.',
    ]},
  ]},
  { id: 'feeding', icon: '🍼', name: 'Кормление', articles: [
    { q: 'Смесь: объёмы по возрасту', a: [
      'Используй интерактивный калькулятор на экране «Уход» — введи вес и получи разовый объём.',
      'Общее правило: суточный объём не превышает 1/5 веса тела (макс. ~200 мл/кг/сут).',
      'Не заставляй доедать — ориентируйся на насыщение малыша.',
    ]},
    { q: 'ГВ: захват, позы, достаточность', a: [
      'Правильный захват: рот широко открыт, захвачен сосок и большая часть ареолы, губки вывернуты.',
      'Позы: «колыбелька», из-под руки, лёжа на боку. Меняй для равномерного опорожнения груди.',
      'Достаточно ли молока: 6+ мокрых подгузников в сутки, прибавка веса, спокойствие после еды.',
      'Лактационный криз (3–6 нед, 3 мес) — временно. Чаще прикладывай, отдыхай, пей достаточно.',
    ]},
    { q: 'Смешанное вскармливание', a: [
      'Сначала предлагай грудь, докорм смесью — после.',
      'Чтобы не потерять молоко: сохраняй ночные кормления и частые прикладывания.',
      'Объём докорма подбирай с педиатром по контрольным взвешиваниям.',
    ]},
    { q: 'Срыгивания: норма или нет', a: [
      'Норма: небольшое срыгивание после еды, малыш бодр и прибавляет в весе.',
      'Помогает: держать «столбиком» 10–15 минут после кормления, не перекармливать.',
      'Тревожно: фонтаном, с кровью/желчью, потеря веса, беспокойство — к врачу.',
    ]},
    { q: 'Голодный крик vs сытый', a: [
      'Ранние признаки голода: причмокивание, поиск груди, сосание кулачка.',
      'Голодный крик — ритмичный, нарастающий.',
      'Сытость: расслабленные ручки, отпускает грудь/бутылочку, засыпает.',
    ]},
  ]},
  { id: 'sleep', icon: '😴', name: 'Сон', articles: [
    { q: 'Нормы сна 0–12 мес', a: ['Смотри таблицу норм сна в этом разделе ниже по экрану — она зашита отдельным блоком на «Росте» и «Планах».',
      '0–1 мес: 16–18 ч; 1–3 мес: 14–17 ч; 3–6 мес: 14–15 ч; 6–12 мес: 13–14 ч.'] },
    { q: 'Безопасный сон', a: [
      'Только на спине. Жёсткий ровный матрас.',
      'Без подушек, одеял-«гнёзд», мягких бортиков и игрушек в кроватке до года.',
      'Температура в комнате 18–22°C, проветривай. Не перегревай.',
    ]},
    { q: 'Укладывание и ритуал', a: [
      'Повторяющийся ритуал: купание → кормление → приглушённый свет → колыбельная.',
      'Белый шум помогает воспроизвести звуки утробы.',
      'Пеленание (свободное) успокаивает до 3 месяцев / до первых попыток переворота.',
    ]},
    { q: 'Регрессы сна', a: [
      'Около 4 месяцев — перестройка структуры сна. В 8–10 мес — скачок развития.',
      'Это временно. Сохраняй ритуал, не вводи новых «костылей» надолго.',
    ]},
    { q: 'Совместный сон: правила', a: [
      'Отдельная поверхность для малыша безопаснее. Если спите вместе — твёрдый матрас, без алкоголя/курения у родителей, без тяжёлых одеял рядом с ребёнком.',
    ]},
  ]},
  { id: 'health', icon: '💊', name: 'Здоровье', articles: [
    { q: 'Температура', a: [
      'Измеряй ректально (точнее всего у младенцев) или электронным термометром.',
      'Норма 36.3–37.4°C ректально. 38°C+ — звони педиатру.',
      'Жаропонижающее — только по назначению врача и в дозе по весу.',
    ]},
    { q: 'Колики', a: [
      'Пик 2–6 недель, проходят к ~3 месяцам. Это не болезнь.',
      'Помогает: «поза тигра», тепло на животик, массаж по часовой стрелке, выкладывание на живот, ношение в слинге.',
    ]},
    { q: 'Стул: норма по возрасту', a: [
      'ГВ: от жёлтого кашицеобразного несколько раз в день до 1 раза в несколько дней — оба варианта норма, если малыш спокоен.',
      'Смесь: более плотный, обычно 1–3 раза в день.',
      'Тревожно: водянистый частый (понос), с кровью/слизью, отсутствие стула с беспокойством.',
    ]},
    { q: 'Сыпь', a: [
      'Потница — мелкие пузырьки в складках/на шее при перегреве.',
      'Токсическая эритема новорождённых — частая, проходит сама в первые недели.',
      'Атопический дерматит — сухость, покраснение, зуд. Любую стойкую сыпь покажи врачу.',
    ]},
    { q: 'Насморк у новорождённого', a: [
      'Физиологический насморк первых недель — частое явление.',
      'Помогает: физраствор по 1–2 капли, аспиратор перед едой и сном.',
      'К врачу: затруднённое дыхание, отказ от еды, температура.',
    ]},
  ]},
  { id: 'checkups', icon: '🩺', name: 'Осмотры и прививки', articles: [
    { q: 'Плановые осмотры', a: [
      '1 мес: педиатр, невролог, офтальмолог, ортопед, УЗИ ТБС, нейросонография, аудиоскрининг.',
      '3 мес: педиатр (+ перед вакцинацией).',
      '6 мес: педиатр, оценка развития и прикорма.',
      '12 мес: педиатр, невролог, ЛОР, стоматолог, общий анализ крови/мочи.',
    ]},
    { q: 'Прививочный календарь (ориентир)', a: [
      'Роддом: гепатит B, БЦЖ.',
      '1 мес: гепатит B (2).',
      '2 мес: пневмококк, начало серии по нац. календарю.',
      '3 / 4.5 / 6 мес: АКДС + полиомиелит + гемофильная + гепатит B (по схеме).',
      'Точный график — у твоего педиатра, он может отличаться по стране и ситуации.',
    ]},
    { q: 'Подготовка к прививке', a: [
      'Малыш должен быть здоров; осмотр педиатра в день прививки.',
      'После: наблюдай 30 минут в клинике, дома следи за температурой.',
      'Жаропонижающее — заранее обсуди с врачом дозу по весу.',
    ]},
  ]},
  { id: 'dev', icon: '🧠', name: 'Развитие', articles: [
    { q: 'Развитие по месяцам (0–6)', a: [
      '1 мес: фиксирует взгляд, реагирует на звук, поднимает голову лёжа на животе на пару секунд.',
      '2 мес: социальная улыбка, гуление, лучше держит голову.',
      '3 мес: уверенно держит голову, рассматривает ручки, смеётся.',
      '4 мес: опора на предплечья, переворот со спины на бок/живот, хватает игрушки.',
      '5–6 мес: переворачивается в обе стороны, тянется и хватает, начинает сидеть с поддержкой.',
    ]},
    { q: 'Красные флаги (повод к неврологу)', a: [
      'Не реагирует на громкие звуки, не следит взглядом к 2–3 мес.',
      'Не держит голову к 3–4 мес, выраженный гипо- или гипертонус.',
      'Нет улыбки/гуления к 3 мес, утрата ранее приобретённых навыков.',
      'Любые сомнения — лучше показать малыша специалисту.',
    ]},
    { q: 'Игры по возрасту', a: [
      '2 недели: контрастные чёрно-белые картинки на 20–30 см, мамин голос, ношение.',
      '1–2 мес: погремушки, пение, «разговор» с паузами, выкладывание на животик.',
      '3–4 мес: яркие подвесные игрушки, развивающий коврик, потешки и пальчиковые игры.',
    ]},
  ]},
  { id: 'myths', icon: '🧭', name: 'Мифы и факты (д-р Ченчак)', articles: [
    { q: 'Можно ли «избаловать» новорождённого вниманием?', a: [
      'Нет. Плач — единственный способ малыша сообщить о потребности, это не манипуляция.',
      'Отвечай на плач — так формируется базовое доверие и привязанность.',
    ]},
    { q: 'Нужно ли кутать ребёнка потеплее?', a: [
      'Нет. При температуре в комнате выше 22°C достаточно одного слоя комфортной одежды.',
      'Перегрев повышает риск СВДС (синдрома внезапной детской смерти). Лучше не перегревать.',
    ]},
    { q: 'Опасны ли сквозняки и кондиционер?', a: [
      'Нет. Квартиру нужно проветривать.',
      'Болезни вызывают инфекции (вирусы и бактерии), а не движение воздуха.',
    ]},
    { q: 'Полезны ли солнечные ванны для витамина D?', a: [
      'Нет, выкладывать голого малыша под прямые лучи не нужно.',
      'Солнечный ожог в детстве повышает риск меланомы. Витамин D — каплями по назначению педиатра.',
    ]},
    { q: 'Подбрасывать малыша вверх — это весело?', a: [
      'Нельзя. Есть риск синдрома детского сотрясения (shaken baby syndrome) с тяжёлыми последствиями.',
    ]},
    { q: 'Грудное вскармливание — любой ценой?', a: [
      'Решение о ГВ, смешанном или смеси — только твоё, без чувства вины и оправданий.',
      'Если кормить грудью больно или тяжело — это веская причина искать помощь или альтернативу.',
    ]},
    { q: 'Делать ли из малыша гения с рождения?', a: [
      'Не гонись за ранним развитием через тесты и «развивашки».',
      'Что действительно важно: нежность, чтение вслух, прогулки, режим сна и отклик на ребёнка.',
    ]},
    { q: 'Сразу ли приходит материнская любовь?', a: [
      'Не обязательно. Привязанность нередко развивается постепенно — это нормально, ты не «плохая мама».',
    ]},
  ]},
];

/* ------------------------------------------------------------------ */
/*  УТИЛИТЫ                                                             */
/* ------------------------------------------------------------------ */

function loadLS(key, fallback) {
  try {
    const raw = localStorage.getItem(key);
    return raw ? JSON.parse(raw) : fallback;
  } catch { return fallback; }
}
function saveLS(key, value) {
  try { localStorage.setItem(key, JSON.stringify(value)); } catch {}
}

// Хук состояния с привязкой к localStorage
function useLocalState(key, initial) {
  const [val, setVal] = useState(() => loadLS(key, initial));
  useEffect(() => { saveLS(key, val); }, [key, val]);
  return [val, setVal];
}

// Парсим "YYYY-MM-DD" как локальную дату (иначе new Date() трактует её как UTC
// и в некоторых часовых поясах возраст «съезжает» на день).
function parseLocalDate(s) {
  if (!s) return null;
  const [y, m, d] = String(s).split('-').map(Number);
  if (!y) return null;
  return new Date(y, (m || 1) - 1, d || 1);
}

function daysBetween(birthDate) {
  const b = parseLocalDate(birthDate);
  if (!b) return 0;
  b.setHours(0,0,0,0);
  const t = new Date(); t.setHours(0,0,0,0);
  return Math.max(0, Math.floor((t - b) / 86400000));
}

// Возраст по календарю: до 2 недель — дни, до ~10 недель — недели, дальше — месяцы + дни.
function ageLabel(birthDate) {
  const b = parseLocalDate(birthDate);
  if (!b) return '';
  b.setHours(0,0,0,0);
  const t = new Date(); t.setHours(0,0,0,0);
  const totalDays = Math.max(0, Math.floor((t - b) / 86400000));
  if (totalDays < 14) return `${totalDays} ${plural(totalDays, 'день','дня','дней')}`;
  let months = (t.getFullYear() - b.getFullYear()) * 12 + (t.getMonth() - b.getMonth());
  if (t.getDate() < b.getDate()) months--;
  // до 2 полных месяцев показываем недели, дальше — месяцы
  if (months < 2) {
    const w = Math.floor(totalDays / 7);
    return `${w} ${plural(w,'неделя','недели','недель')} (${totalDays} дн.)`;
  }
  const anchor = new Date(b.getFullYear(), b.getMonth() + months, b.getDate());
  const remDays = Math.floor((t - anchor) / 86400000);
  const mLabel = `${months} ${plural(months,'месяц','месяца','месяцев')}`;
  return remDays > 0 ? `${mLabel} ${remDays} ${plural(remDays,'день','дня','дней')}` : mLabel;
}

function plural(n, one, few, many) {
  const m10 = n % 10, m100 = n % 100;
  if (m10 === 1 && m100 !== 11) return one;
  if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20)) return few;
  return many;
}

function fillTemplate(str, profile) {
  if (!str) return '';
  return str
    .replace(/\{babyName\}/g, profile?.babyName || 'малыш')
    .replace(/\{motherName\}/g, profile?.motherName || 'мама');
}

function pickByDay(arr, day) {
  return arr.find(x => day >= x.fromDay && day <= x.toDay) || arr[arr.length - 1];
}

// Расчёт объёма смеси по принятым педиатрическим методикам:
//  • первые 10 дней — формула Финкельштейна (день жизни × 70/80);
//  • 11 дн – 2 мес — объёмный метод 1/5 массы тела;
//  • 2–4 мес — 1/6; 4–6 мес — 1/7; старше 6 мес — 1/8 (+ прикорм).
// Источники: similac.ru, nutrilak.com, kp.ru (Комаровский). Цифры — ориентир, не предписание.
function formulaForDay(day, weightGrams) {
  const w = weightGrams || 3300;
  let daily, meals, note;
  if (day <= 10) {
    const k = w < 3200 ? 70 : 80;
    const n = Math.max(1, day);               // день жизни
    daily = n * k;
    meals = 8;
    note = `первые 10 дней: день жизни × ${k}`;
  } else if (day < 60) {
    daily = Math.round(w / 5);                 // 1/5 массы
    meals = day < 30 ? 7 : 6;
    note = '≈ 1/5 массы тела в сутки';
  } else if (day < 120) {
    daily = Math.round(w / 6);                 // 1/6
    meals = 6;
    note = '≈ 1/6 массы тела';
  } else if (day < 180) {
    daily = Math.round(w / 7);                 // 1/7
    meals = 5;
    note = '≈ 1/7 массы тела';
  } else {
    daily = Math.round(w / 8);                 // 1/8 + прикорм
    meals = 5;
    note = '≈ 1/8 массы + прикорм';
  }
  if (daily > 1100) daily = 1100;              // суточный объём смеси обычно не больше ~1–1.1 л
  const perFeed = Math.round(daily / meals / 5) * 5;
  return { daily, perFeed, meals, note };
}

function todayKey() {
  return new Date().toISOString().slice(0, 10);
}

function fmtTime(ts) {
  return new Date(ts).toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
}

/* ------------------------------------------------------------------ */
/*  CLAUDE API                                                         */
/* ------------------------------------------------------------------ */

async function callClaude(messages, systemPrompt, { maxTokens = 1000 } = {}) {
  const apiKey = loadLS(LS.apiKey, '');
  if (!apiKey) throw new Error('NO_KEY');
  const response = await fetch('https://api.anthropic.com/v1/messages', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey,
      'anthropic-version': '2023-06-01',
      'anthropic-dangerous-direct-browser-access': 'true',
    },
    body: JSON.stringify({
      model: MODEL,
      max_tokens: maxTokens,
      system: systemPrompt,
      messages,
    }),
  });
  if (!response.ok) {
    const t = await response.text().catch(() => '');
    throw new Error(`API ${response.status}: ${t.slice(0, 200)}`);
  }
  const data = await response.json();
  return data.content?.[0]?.text || '';
}

function babyContextLines(profile, days) {
  const weeks = Math.floor(days / 7);
  return `- Имя: ${profile.babyName}, ${days} дней (${weeks} недель)
- Тип кормления: ${profile.feedingType}
- Вес при рождении: ${profile.birthWeight}г, текущий: ${profile.currentWeight || profile.birthWeight}г
- Недоношенный: ${profile.isPremature ? `да, рождён в ${profile.gestationalWeeks} недель` : 'нет'}
- Имя мамы: ${profile.motherName}`;
}

/* ------------------------------------------------------------------ */
/*  МЕЛКИЕ UI-КОМПОНЕНТЫ                                                */
/* ------------------------------------------------------------------ */

function Card({ children, className = '' }) {
  return <div className={`bg-white rounded-card shadow-card p-4 ${className}`}>{children}</div>;
}

function SectionTitle({ children, sub }) {
  return (
    <div className="mb-3">
      <h2 className="text-xl text-ink">{children}</h2>
      {sub && <p className="text-inkSoft text-[13px] mt-0.5">{sub}</p>}
    </div>
  );
}

function PrimaryButton({ children, onClick, disabled, className = '', type = 'button' }) {
  return (
    <button
      type={type}
      onClick={onClick}
      disabled={disabled}
      className={`min-h-[44px] px-6 rounded-btn bg-terra text-white font-semibold shadow-card
        active:scale-[0.98] transition disabled:opacity-50 disabled:active:scale-100 ${className}`}
    >
      {children}
    </button>
  );
}

function Dots() {
  return (
    <span className="inline-flex gap-1 items-center" aria-label="загрузка">
      <span className="dot w-2 h-2 rounded-full bg-terra" style={{ animationDelay: '0s' }} />
      <span className="dot w-2 h-2 rounded-full bg-terra" style={{ animationDelay: '0.2s' }} />
      <span className="dot w-2 h-2 rounded-full bg-terra" style={{ animationDelay: '0.4s' }} />
    </span>
  );
}

function Skeleton({ className = '' }) {
  return <div className={`skeleton rounded-card ${className}`} />;
}

function NannyAvatar({ size = 40 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 64 64" aria-hidden="true" className="shrink-0">
      <circle cx="32" cy="32" r="32" fill="#7BBFB5" />
      <circle cx="32" cy="30" r="16" fill="#FDF8F5" />
      <path d="M16 28a16 16 0 0132 0c0-9-7-15-16-15s-16 6-16 15z" fill="#6394C1" />
      <circle cx="26" cy="30" r="2.2" fill="#2D2520" />
      <circle cx="38" cy="30" r="2.2" fill="#2D2520" />
      <path d="M27 36c2 2 8 2 10 0" stroke="#2D2520" strokeWidth="2" fill="none" strokeLinecap="round" />
      <circle cx="23" cy="34" r="2.5" fill="#88B4D8" opacity="0.5" />
      <circle cx="41" cy="34" r="2.5" fill="#88B4D8" opacity="0.5" />
    </svg>
  );
}

/* ------------------------------------------------------------------ */
/*  ОНБОРДИНГ                                                           */
/* ------------------------------------------------------------------ */

// Вынесены на уровень модуля — иначе React пересоздаёт их на каждый ввод
// и поле теряет фокус после каждой буквы.
function OnbField({ label, children }) {
  return (
    <label className="block mb-4">
      <span className="text-[13px] text-inkSoft font-medium">{label}</span>
      <div className="mt-1">{children}</div>
    </label>
  );
}
function OnbChoice({ value, current, onClick, children }) {
  return (
    <button type="button" onClick={onClick}
      className={`min-h-[44px] flex-1 px-3 rounded-2xl border text-sm font-medium transition
        ${current === value ? 'bg-terra text-white border-terra' : 'bg-white text-ink border-[#EADAD3]'}`}>
      {children}
    </button>
  );
}

function Onboarding({ onDone }) {
  const [f, setF] = useState({
    motherName: '', babyName: '', birthDate: '', feedingType: 'Грудное',
    birthWeight: '', currentWeight: '', currentHeight: '', hasComplications: false, complications: '',
    isPremature: false, gestationalWeeks: '', isFirstChild: true, timezone: '',
  });
  const [step, setStep] = useState(0); // 0 форма, 1 приветствие

  const set = (k, v) => setF(p => ({ ...p, [k]: v }));
  const valid = f.motherName && f.babyName && f.birthDate && f.birthWeight;

  const finish = () => {
    const profile = {
      ...f,
      birthWeight: Number(f.birthWeight) || 0,
      currentWeight: Number(f.currentWeight) || Number(f.birthWeight) || 0,
      currentHeight: Number(f.currentHeight) || null,
      gestationalWeeks: Number(f.gestationalWeeks) || null,
      complications: f.hasComplications ? f.complications : '',
      createdAt: Date.now(),
    };
    saveLS(LS.profile, profile);
    // Заносим первый замер, чтобы трекер роста сразу был не пустым
    const existing = loadLS(LS.weight, []);
    if (existing.length === 0 && profile.currentWeight) {
      saveLS(LS.weight, [{ id: Date.now(), date: todayKey(), weight: profile.currentWeight, height: profile.currentHeight, head: null }]);
    }
    setStep(1);
  };

  if (step === 1) {
    const days = daysBetween(f.birthDate);
    return (
      <div className="min-h-full flex flex-col items-center justify-center text-center px-6 fade-screen">
        <div className="text-5xl mb-4">🤍</div>
        <h1 className="text-3xl text-ink mb-4 leading-snug">Привет, {f.motherName}!</h1>
        <p className="text-inkSoft max-w-sm">
          Я Стефан — твой помощник в самое важное путешествие жизни. {f.babyName} уже{' '}
          <span className="text-terraDk font-semibold">{days} {plural(days,'день','дня','дней')}</span>,
          и каждый день — маленькое чудо.
        </p>
        <PrimaryButton className="mt-8" onClick={onDone}>Начать →</PrimaryButton>
      </div>
    );
  }

  const inputCls = 'w-full min-h-[44px] px-4 rounded-2xl border border-[#EADAD3] bg-white text-ink focus:border-terra outline-none';

  return (
    <div className="min-h-full px-5 py-8 fade-screen">
      <div className="max-w-md mx-auto">
        <div className="text-center mb-6">
          <div className="text-4xl mb-2">🍼</div>
          <h1 className="text-2xl text-ink">Давай познакомимся</h1>
          <p className="text-inkSoft text-[13px] mt-1">Эти данные останутся только на твоём устройстве</p>
        </div>

        <OnbField label="Как тебя зовут?">
          <input className={inputCls} value={f.motherName} onChange={e => set('motherName', e.target.value)} placeholder="Имя мамы" />
        </OnbField>
        <OnbField label="Имя малыша">
          <input className={inputCls} value={f.babyName} onChange={e => set('babyName', e.target.value)} placeholder="Имя ребёнка" />
        </OnbField>
        <OnbField label="Дата рождения">
          <input type="date" className={inputCls} value={f.birthDate} max={todayKey()} onChange={e => set('birthDate', e.target.value)} />
        </OnbField>
        <OnbField label="Тип кормления">
          <div className="flex gap-2">
            {['Грудное','Смесь','Смешанное'].map(t => (
              <OnbChoice key={t} value={t} current={f.feedingType} onClick={() => set('feedingType', t)}>{t}</OnbChoice>
            ))}
          </div>
        </OnbField>
        <div className="flex gap-3">
          <OnbField label="Вес при рождении (г)">
            <input type="number" inputMode="numeric" className={inputCls} value={f.birthWeight} onChange={e => set('birthWeight', e.target.value)} placeholder="3300" />
          </OnbField>
          <OnbField label="Вес сейчас (г)">
            <input type="number" inputMode="numeric" className={inputCls} value={f.currentWeight} onChange={e => set('currentWeight', e.target.value)} placeholder="опц." />
          </OnbField>
        </div>
        <OnbField label="Рост сейчас (см)">
          <input type="number" inputMode="numeric" className={inputCls} value={f.currentHeight} onChange={e => set('currentHeight', e.target.value)} placeholder="напр. 52 — опционально" />
        </OnbField>

        <OnbField label="Были осложнения при родах?">
          <div className="flex gap-2">
            <OnbChoice value={false} current={f.hasComplications} onClick={() => set('hasComplications', false)}>Нет</OnbChoice>
            <OnbChoice value={true} current={f.hasComplications} onClick={() => set('hasComplications', true)}>Да</OnbChoice>
          </div>
          {f.hasComplications && (
            <input className={inputCls + ' mt-2'} value={f.complications} onChange={e => set('complications', e.target.value)} placeholder="Коротко опиши" />
          )}
        </OnbField>

        <OnbField label="Малыш родился недоношенным?">
          <div className="flex gap-2">
            <OnbChoice value={false} current={f.isPremature} onClick={() => set('isPremature', false)}>Нет</OnbChoice>
            <OnbChoice value={true} current={f.isPremature} onClick={() => set('isPremature', true)}>Да</OnbChoice>
          </div>
          {f.isPremature && (
            <input type="number" inputMode="numeric" className={inputCls + ' mt-2'} value={f.gestationalWeeks}
              onChange={e => set('gestationalWeeks', e.target.value)} placeholder="Срок при рождении, недель (напр. 35)" />
          )}
        </OnbField>

        <OnbField label="Это твой первый ребёнок?">
          <div className="flex gap-2">
            <OnbChoice value={true} current={f.isFirstChild} onClick={() => set('isFirstChild', true)}>Да</OnbChoice>
            <OnbChoice value={false} current={f.isFirstChild} onClick={() => set('isFirstChild', false)}>Нет</OnbChoice>
          </div>
        </OnbField>

        <OnbField label="Город / часовой пояс">
          <input className={inputCls} value={f.timezone} onChange={e => set('timezone', e.target.value)} placeholder="напр. Москва" />
        </OnbField>

        <PrimaryButton className="w-full mt-2" onClick={finish} disabled={!valid}>
          Продолжить
        </PrimaryButton>
        <p className="text-center text-[11px] text-inkSoft mt-4">
          Приложение — помощник, а не замена врачу.
        </p>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН 1 — СЕГОДНЯ                                                   */
/* ------------------------------------------------------------------ */

// Кто выполняет пункт режима — малыш или мама. Используется для разделения «дорожек».
const WHO = {
  baby: { icon: '🍼', label: 'Малыш', bar: '#88B4D8', soft: '#EAF2FA' },
  mom:  { icon: '🤱', label: 'Мама',  bar: '#C99BC0', soft: '#F6ECF4' },
};
const whoOf = (it) => WHO[it.who] || WHO.baby;

// Время ↔ минуты от полуночи
const timeToMin = (t) => { const [h, m] = String(t).split(':').map(Number); return (h || 0) * 60 + (m || 0); };
const minToTime = (m) => {
  m = ((Math.round(m) % 1440) + 1440) % 1440;
  return `${String(Math.floor(m / 60)).padStart(2, '0')}:${String(m % 60).padStart(2, '0')}`;
};

function buildSchedule(days, feedingType, weight) {
  const isFormula = feedingType === 'Смесь' || feedingType === 'Смешанное';
  const f = formulaForDay(days, weight);
  const vol = f ? `${f.perFeed} мл` : '';
  const feedLabel = isFormula ? `Кормление${vol ? ` (${vol})` : ''}` : 'Кормление (по требованию)';
  const base = [
    { time: '06:00', text: feedLabel, who: 'baby' },
    { time: '06:00', text: 'Завтрак, стакан воды', who: 'mom' },
    { time: '06:30', text: 'Бодрствование, контакт «кожа к коже»', who: 'baby' },
    { time: '07:00', text: 'Сон', who: 'baby' },
    { time: '07:00', text: 'Отдохнуть, пока малыш спит', who: 'mom' },
    { time: '09:30', text: feedLabel, note: 'уход за пупочком', who: 'baby' },
    { time: '10:00', text: days >= 15 ? 'Сон' : 'Сон', note: days >= 15 ? 'на животике 1–5 мин' : '', who: 'baby' },
    { time: '12:30', text: feedLabel, who: 'baby' },
    { time: '13:00', text: 'Прогулка / сон на свежем воздухе', who: 'baby' },
    { time: '13:30', text: 'Обед', who: 'mom' },
    { time: '15:30', text: feedLabel, who: 'baby' },
    { time: '16:00', text: 'Гимнастика, массаж, разговор', who: 'baby' },
    { time: '18:30', text: feedLabel, who: 'baby' },
    { time: '19:00', text: 'Спокойное бодрствование', who: 'baby' },
    { time: '21:00', text: 'Время для себя, отдых', who: 'mom' },
    { time: '22:00', text: 'Вечернее купание (37°C, 7–10 мин)', who: 'baby' },
    { time: '22:30', text: feedLabel, note: 'укладывание на ночь', who: 'baby' },
    { time: '02:30', text: 'Ночное кормление', who: 'baby' },
  ];
  return base.map((x, i) => ({ note: '', who: 'baby', ...x, id: `task_${i}` }));
}

function TodayScreen({ profile, days, goTo }) {
  const [tasks, setTasks] = useLocalState(LS.tasks, {});
  const [custom] = useLocalState(LS.schedule, []);
  const tk = todayKey();
  const doneToday = tasks[tk] || [];
  // Если мама создала свой режим во вкладке «Режим» — показываем его, иначе шаблон по возрасту
  const schedule = useMemo(
    () => (custom.length ? [...custom].sort((a,b) => a.time.localeCompare(b.time)) : buildSchedule(days, profile.feedingType, profile.currentWeight)),
    [custom, days, profile]
  );

  const toggle = (id) => {
    setTasks(prev => {
      const list = new Set(prev[tk] || []);
      list.has(id) ? list.delete(id) : list.add(id);
      return { ...prev, [tk]: [...list] };
    });
  };

  const phrase = fillTemplate(pickByDay(DAILY_PHRASES, days).text, profile);
  const cardSet = pickByDay(AGE_CARDS, days);
  const f = formulaForDay(days, profile.currentWeight);

  return (
    <div className="fade-screen pb-4">
      {/* Шапка */}
      <div className="px-5 pt-6 pb-4">
        <p className="text-inkSoft text-[13px]">{new Date().toLocaleDateString('ru-RU', { weekday:'long', day:'numeric', month:'long' })}</p>
        <h1 className="text-3xl text-ink mt-1">{profile.babyName}</h1>
        <p className="text-teal font-semibold">{ageLabel(profile.birthDate)}</p>
      </div>

      {/* Фраза дня */}
      <div className="px-5">
        <div className="bg-gradient-to-br from-terra to-terraDk text-white rounded-card p-5 shadow-cardLg">
          <p className="text-[11px] uppercase tracking-wide opacity-80 mb-1">Фраза дня</p>
          <p className="font-display text-lg leading-snug">{phrase}</p>
        </div>
      </div>

      {/* Сейчас важно */}
      <div className="px-5 mt-6">
        <SectionTitle sub="Подобрано по возрасту малыша">Сейчас важно</SectionTitle>
        <div className="flex gap-3 overflow-x-auto no-scrollbar -mx-5 px-5 pb-1">
          {cardSet.cards.map((c, i) => (
            <div key={i} className="bg-white rounded-card shadow-card p-4 min-w-[260px] max-w-[260px]">
              <div className="text-2xl mb-2">{c.icon}</div>
              <h3 className="text-base text-ink mb-1">{c.title}</h3>
              <p className="text-inkSoft text-[13px] leading-relaxed">{c.text}</p>
            </div>
          ))}
        </div>
      </div>

      {/* Подсказка по объёму */}
      {f && (profile.feedingType !== 'Грудное') && (
        <div className="px-5 mt-5">
          <Card className="flex items-center gap-4">
            <div className="text-3xl">🍼</div>
            <div>
              <p className="text-ink font-semibold">≈ {f.perFeed} мл за кормление</p>
              <p className="text-inkSoft text-[13px]">~{f.meals} раз/сутки · суточно ≈ {f.daily} мл{f.note ? ` · ${f.note}` : ''}</p>
            </div>
          </Card>
        </div>
      )}

      {/* Расписание дня */}
      <div className="px-5 mt-6">
        <div className="flex items-end justify-between mb-3">
          <div>
            <h2 className="text-xl text-ink">Расписание дня</h2>
            <p className="text-inkSoft text-[13px]">{custom.length ? 'Твой режим' : 'Шаблон по возрасту'} · выполнено {doneToday.length} из {schedule.length}</p>
          </div>
          <button onClick={() => goTo('routine')} className="text-teal text-[13px] font-semibold min-h-[44px] px-1 shrink-0">
            {custom.length ? 'Изменить' : 'Создать свой'} →
          </button>
        </div>
        <div className="flex gap-3 mb-2 text-[12px] text-inkSoft">
          <span className="flex items-center gap-1">{WHO.baby.icon} малыш</span>
          <span className="flex items-center gap-1">{WHO.mom.icon} мама</span>
        </div>
        <Card className="p-0 overflow-hidden">
          {schedule.map((s, i) => {
            const done = doneToday.includes(s.id);
            const w = whoOf(s);
            return (
              <button key={s.id} onClick={() => toggle(s.id)} aria-label={`Отметить: ${s.text}`}
                className={`w-full flex items-center gap-3 pr-4 py-3 text-left min-h-[44px] border-l-4
                  ${i ? 'border-t border-t-[#F1E7E1]' : ''} active:bg-milk transition`}
                style={{ borderLeftColor: w.bar, paddingLeft: '12px' }}>
                <span className="text-teal font-semibold text-[13px] w-12 shrink-0">{s.time}</span>
                <span className="flex-1 min-w-0">
                  <span className={`text-[14px] flex items-center gap-1 ${done ? 'line-through text-inkSoft' : 'text-ink'}`}>
                    <span className="shrink-0">{w.icon}</span>{s.text}
                  </span>
                  {s.note ? <span className="block text-[12px] text-inkSoft mt-0.5">💬 {s.note}</span> : null}
                </span>
                <span className={`w-6 h-6 rounded-full border-2 flex items-center justify-center shrink-0
                  ${done ? 'bg-teal border-teal text-white' : 'border-[#DCC9C1]'}`}>
                  {done ? '✓' : ''}
                </span>
              </button>
            );
          })}
        </Card>
      </div>

      <div className="px-5 mt-5">
        <button onClick={() => goTo('nanny')} className="w-full bg-white rounded-card shadow-card p-4 flex items-center gap-3 active:scale-[0.99] transition">
          <NannyAvatar size={44} />
          <div className="text-left">
            <p className="text-ink font-semibold">Спроси Стефана</p>
            <p className="text-inkSoft text-[13px]">AI-неонатолог ответит на любой вопрос о малыше</p>
          </div>
          <span className="ml-auto text-terra text-xl">→</span>
        </button>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН 2 — ПЛАНЫ                                                     */
/* ------------------------------------------------------------------ */

function PlansScreen({ profile, days }) {
  const [plans, setPlans] = useLocalState(LS.plans, {});
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');
  const [showHistory, setShowHistory] = useState(false);

  const weeks = Math.floor(days / 7);
  const weekKey = `week_${weeks}`;
  const current = plans[weekKey];

  const generate = async () => {
    setLoading(true); setError('');
    const sys = 'Ты опытный неонатолог и педиатр.';
    const prompt = `Ты опытный неонатолог и педиатр. Составь персонализированный план на неделю для мамы и ребёнка.

ДАННЫЕ:
- Имя мамы: ${profile.motherName}
- Имя ребёнка: ${profile.babyName}
- Возраст: ${weeks} недель (${days} дней)
- Тип кормления: ${profile.feedingType}
- Вес при рождении: ${profile.birthWeight}г
- Текущий вес: ${profile.currentWeight || profile.birthWeight}г
- Недоношенный: ${profile.isPremature ? 'да' : 'нет'}${profile.isPremature ? `, рождён в ${profile.gestationalWeeks} недель` : ''}
- Осложнения при родах: ${profile.complications || 'нет'}
- Первый ребёнок: ${profile.isFirstChild ? 'да' : 'нет'}

СТРУКТУРА ПЛАНА — верни JSON с такими блоками:
{
  "weekFocus": "главная тема недели (1 предложение)",
  "babyMilestones": ["что малыш умеет/должен уметь на этой неделе — 3–5 пунктов"],
  "feedingPlan": { "schedule": "...", "volumePerFeeding": "...", "dailyTotal": "...", "tips": ["..."] },
  "sleepPlan": { "totalHoursNorm": "...", "nightSleepExpectation": "...", "napSchedule": "...", "tips": ["..."] },
  "developmentActivities": [ {"activity":"...","duration":"...","frequency":"...","how":"...","why":"..."} ],
  "careTasks": [ {"task":"...","frequency":"...","instructions":"..."} ],
  "momCare": { "physicalRecovery":"...", "emotionalNote":"...", "selfCareIdeas":["..."] },
  "watchFor": ["3–5 симптомов когда звонить педиатру"],
  "weeklyGoal": "одна главная цель на неделю для мамы"
}

Пиши тепло, по-человечески, без канцелярита. Обращайся к маме по имени. Если ребёнок недоношенный — используй корректированный возраст. Верни ТОЛЬКО JSON, без пояснений.`;

    try {
      const text = await callClaude([{ role: 'user', content: prompt }], sys, { maxTokens: 2000 });
      const jsonStr = text.slice(text.indexOf('{'), text.lastIndexOf('}') + 1);
      const plan = JSON.parse(jsonStr);
      setPlans(prev => ({ ...prev, [weekKey]: { ...plan, _week: weeks, _at: Date.now() } }));
    } catch (e) {
      setError(e.message === 'NO_KEY'
        ? 'Добавь ключ Claude API в настройках (⚙️ вверху), чтобы генерировать планы.'
        : 'Не удалось сгенерировать план. Проверь соединение и ключ API.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="fade-screen px-5 pt-6 pb-4">
      <div className="flex items-start justify-between">
        <h1 className="text-2xl text-ink">Неделя {weeks}<br/><span className="text-inkSoft text-base font-normal">план для вас и {profile.babyName}</span></h1>
        <button onClick={() => setShowHistory(s => !s)} className="text-teal text-[13px] font-semibold min-h-[44px] px-2">
          Прошлые недели
        </button>
      </div>

      {showHistory && (
        <Card className="mt-3">
          <p className="text-[13px] text-inkSoft mb-2">История планов</p>
          {Object.keys(plans).length === 0 && <p className="text-sm text-inkSoft">Пока нет сохранённых планов.</p>}
          <div className="flex flex-col gap-1">
            {Object.entries(plans).sort((a,b) => (b[1]._week||0)-(a[1]._week||0)).map(([k, p]) => (
              <div key={k} className="flex items-center justify-between py-1 border-b border-[#F1E7E1] last:border-0">
                <span className="text-sm text-ink">Неделя {p._week}</span>
                <span className="text-[12px] text-inkSoft">{p.weekFocus?.slice(0,40)}…</span>
              </div>
            ))}
          </div>
        </Card>
      )}

      {!current && !loading && (
        <div className="mt-6 text-center">
          <div className="text-4xl mb-3">📅</div>
          <p className="text-inkSoft mb-4 max-w-xs mx-auto">
            Персональный план на эту неделю учтёт возраст, вес, кормление и особенности {profile.babyName}.
          </p>
          <PrimaryButton onClick={generate}>Сгенерировать план на эту неделю</PrimaryButton>
        </div>
      )}

      {error && <p className="mt-4 text-center text-[13px] text-terraDk bg-[#EAF2FA] rounded-card p-3">{error}</p>}

      {loading && (
        <div className="mt-6 space-y-3">
          <div className="flex justify-center mb-2"><Dots /></div>
          <Skeleton className="h-24 w-full" />
          <Skeleton className="h-32 w-full" />
          <Skeleton className="h-28 w-full" />
        </div>
      )}

      {current && !loading && <PlanView plan={current} onRegen={generate} />}
    </div>
  );
}

function PlanBlock({ icon, title, accent = 'teal', children }) {
  return (
    <Card className="mt-4">
      <div className="flex items-center gap-2 mb-2">
        <span className="text-xl">{icon}</span>
        <h3 className={`text-lg ${accent === 'terra' ? 'text-terraDk' : 'text-ink'}`}>{title}</h3>
      </div>
      {children}
    </Card>
  );
}

function Bullets({ items }) {
  if (!items?.length) return null;
  return (
    <ul className="space-y-1">
      {items.map((t, i) => (
        <li key={i} className="text-[14px] text-ink flex gap-2"><span className="text-teal">•</span><span>{t}</span></li>
      ))}
    </ul>
  );
}

function PlanView({ plan, onRegen }) {
  return (
    <div className="mt-4">
      <div className="bg-gradient-to-br from-teal to-[#5FA89D] text-white rounded-card p-5 shadow-cardLg">
        <p className="text-[11px] uppercase tracking-wide opacity-80 mb-1">🎯 Фокус недели</p>
        <p className="font-display text-xl leading-snug">{plan.weekFocus}</p>
      </div>

      {plan.babyMilestones && (
        <PlanBlock icon="🌟" title="Что умеет малыш">
          <Bullets items={plan.babyMilestones} />
        </PlanBlock>
      )}

      {plan.feedingPlan && (
        <PlanBlock icon="🍼" title="План кормления">
          <div className="grid grid-cols-3 gap-2 mb-3">
            {[['Режим', plan.feedingPlan.schedule], ['Порция', plan.feedingPlan.volumePerFeeding], ['В сутки', plan.feedingPlan.dailyTotal]].map(([l,v]) => (
              <div key={l} className="bg-milk rounded-xl p-2 text-center">
                <p className="text-[10px] text-inkSoft uppercase">{l}</p>
                <p className="text-[13px] text-ink font-semibold mt-0.5">{v}</p>
              </div>
            ))}
          </div>
          <Bullets items={plan.feedingPlan.tips} />
        </PlanBlock>
      )}

      {plan.sleepPlan && (
        <PlanBlock icon="😴" title="Сон">
          <div className="space-y-1 mb-2 text-[14px] text-ink">
            <p><b className="text-inkSoft font-medium">Норма:</b> {plan.sleepPlan.totalHoursNorm}</p>
            <p><b className="text-inkSoft font-medium">Ночь:</b> {plan.sleepPlan.nightSleepExpectation}</p>
            <p><b className="text-inkSoft font-medium">Дневные сны:</b> {plan.sleepPlan.napSchedule}</p>
          </div>
          <Bullets items={plan.sleepPlan.tips} />
        </PlanBlock>
      )}

      {plan.developmentActivities && (
        <PlanBlock icon="🌱" title="Развитие">
          <div className="space-y-3">
            {plan.developmentActivities.map((a, i) => (
              <div key={i} className="bg-milk rounded-xl p-3">
                <div className="flex justify-between items-center">
                  <p className="font-semibold text-ink text-[14px]">{a.activity}</p>
                  <span className="text-[11px] text-teal font-semibold whitespace-nowrap">{a.duration} · {a.frequency}</span>
                </div>
                {a.how && <p className="text-[13px] text-inkSoft mt-1"><b>Как:</b> {a.how}</p>}
                {a.why && <p className="text-[13px] text-inkSoft"><b>Зачем:</b> {a.why}</p>}
              </div>
            ))}
          </div>
        </PlanBlock>
      )}

      {plan.careTasks && (
        <PlanBlock icon="🛁" title="Уход">
          <div className="space-y-2">
            {plan.careTasks.map((c, i) => (
              <div key={i} className="flex gap-2 text-[14px]">
                <span className="text-teal mt-0.5">☐</span>
                <div>
                  <p className="text-ink font-medium">{c.task} <span className="text-inkSoft font-normal">· {c.frequency}</span></p>
                  {c.instructions && <p className="text-inkSoft text-[13px]">{c.instructions}</p>}
                </div>
              </div>
            ))}
          </div>
        </PlanBlock>
      )}

      {plan.momCare && (
        <PlanBlock icon="💕" title="Маме" accent="terra">
          {plan.momCare.physicalRecovery && <p className="text-[14px] text-ink mb-1"><b className="text-inkSoft font-medium">Тело:</b> {plan.momCare.physicalRecovery}</p>}
          {plan.momCare.emotionalNote && <p className="text-[14px] text-ink italic bg-[#EAF2FA] rounded-xl p-3 my-2">{plan.momCare.emotionalNote}</p>}
          <Bullets items={plan.momCare.selfCareIdeas} />
        </PlanBlock>
      )}

      {plan.watchFor && (
        <PlanBlock icon="⚠️" title="Когда к врачу">
          <div className="flex flex-wrap gap-2">
            {plan.watchFor.map((w, i) => (
              <span key={i} className="text-[12px] bg-[#D9E8F5] text-terraDk rounded-full px-3 py-1">{w}</span>
            ))}
          </div>
        </PlanBlock>
      )}

      {plan.weeklyGoal && (
        <div className="mt-4 bg-terra text-white rounded-card p-4 text-center">
          <p className="text-[11px] uppercase tracking-wide opacity-80">Цель недели</p>
          <p className="font-display text-lg mt-1">{plan.weeklyGoal}</p>
        </div>
      )}

      <button onClick={onRegen} className="w-full mt-4 text-teal text-[13px] font-semibold min-h-[44px]">
        ↻ Перегенерировать план
      </button>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН 3 — УХОД (ЭНЦИКЛОПЕДИЯ)                                       */
/* ------------------------------------------------------------------ */

// Одна статья энциклопедии — раскрывается по нажатию (один уровень).
function CareArticle({ art }) {
  const [open, setOpen] = useState(false);
  return (
    <div className="bg-white rounded-card shadow-card overflow-hidden">
      <button onClick={() => setOpen(o => !o)}
        className="w-full text-left px-4 py-3 min-h-[48px] flex justify-between items-center gap-2 active:bg-milk">
        <span className="text-[14px] text-ink font-medium">{art.q}</span>
        <span className="text-teal text-lg shrink-0">{open ? '−' : '+'}</span>
      </button>
      {open && (
        <div className="px-4 pb-3 fade-screen">
          {art.a.map((p, pi) => (
            <p key={pi} className="text-[13px] text-inkSoft leading-relaxed mb-1.5 flex gap-2">
              <span className="text-teal shrink-0">•</span><span>{p}</span>
            </p>
          ))}
        </div>
      )}
    </div>
  );
}

function CareScreen({ profile }) {
  const [view, setView] = useState('home');   // 'home' | 'calc' | 'sleep' | <catId>
  const [calcWeight, setCalcWeight] = useState(profile.currentWeight || profile.birthWeight || 3300);
  const [calcDay, setCalcDay] = useState(daysBetween(profile.birthDate));
  const calc = formulaForDay(calcDay, calcWeight);

  // Плитки: 2 инструмента + категории энциклопедии
  const tiles = [
    { id: 'calc', icon: '🍼', name: 'Калькулятор смеси' },
    { id: 'sleep', icon: '😴', name: 'Нормы сна' },
    ...ENCYCLOPEDIA.map(c => ({ id: c.id, icon: c.icon, name: c.name })),
  ];

  const BackBar = ({ title, icon }) => (
    <div className="mb-3">
      <button onClick={() => setView('home')} className="text-teal text-[13px] font-semibold min-h-[44px] flex items-center gap-1">← Все темы</button>
      <div className="flex items-center gap-2"><span className="text-2xl">{icon}</span><h2 className="text-xl text-ink">{title}</h2></div>
    </div>
  );

  // ── Экран: главная сетка плиток ─────────────────────────────
  if (view === 'home') {
    return (
      <div key="home" className="fade-screen px-5 pt-6 pb-4">
        <SectionTitle sub="Выбери тему — открой карточку с ответами">Уход и энциклопедия</SectionTitle>
        <div className="grid grid-cols-2 gap-3">
          {tiles.map(t => (
            <button key={t.id} onClick={() => setView(t.id)}
              className="bg-white rounded-card shadow-card p-4 flex flex-col items-center justify-center text-center gap-2 min-h-[104px] active:scale-95 transition">
              <span className="text-3xl">{t.icon}</span>
              <span className="text-[13px] text-ink font-medium leading-tight">{t.name}</span>
            </button>
          ))}
        </div>
        <p className="text-center text-[11px] text-inkSoft mt-5">
          Информация основана на рекомендациях ВОЗ, AAP и доказательной педиатрии (Е. Комаровский, неонатолог В. Ченчак). Не заменяет консультацию врача.
        </p>
      </div>
    );
  }

  // ── Экран: калькулятор смеси ────────────────────────────────
  if (view === 'calc') {
    return (
      <div key="calc" className="fade-screen px-5 pt-6 pb-4">
        <BackBar title="Калькулятор смеси" icon="🍼" />
        <Card>
          <div className="flex gap-3">
            <label className="flex-1"><span className="text-[12px] text-inkSoft">Вес малыша (г)</span>
              <input type="number" inputMode="numeric" value={calcWeight} onChange={e => setCalcWeight(Number(e.target.value))}
                className="w-full min-h-[44px] mt-1 px-3 rounded-2xl border border-[#EADAD3] outline-none focus:border-terra" /></label>
            <label className="flex-1"><span className="text-[12px] text-inkSoft">Возраст (дней)</span>
              <input type="number" inputMode="numeric" value={calcDay} onChange={e => setCalcDay(Number(e.target.value))}
                className="w-full min-h-[44px] mt-1 px-3 rounded-2xl border border-[#EADAD3] outline-none focus:border-terra" /></label>
          </div>
          {calc && (
            <div className="mt-3 bg-milk rounded-xl p-4 text-center">
              <p className="text-3xl font-display text-terraDk">{calc.perFeed} мл</p>
              <p className="text-[13px] text-inkSoft mt-1">за одно кормление · ~{calc.meals} раз/сут · суточно ≈ {calc.daily} мл</p>
              {calc.note && <p className="text-[12px] text-teal mt-1">{calc.note}</p>}
            </div>
          )}
          <p className="text-[11px] text-inkSoft mt-3">Ориентир по педиатрическим методикам. Не заставляй доедать — малыш умеет саморегуляцию. Финальное слово за педиатром.</p>
        </Card>
      </div>
    );
  }

  // ── Экран: нормы сна ────────────────────────────────────────
  if (view === 'sleep') {
    return (
      <div key="sleep" className="fade-screen px-5 pt-6 pb-4">
        <BackBar title="Нормы сна 0–12 мес" icon="😴" />
        <Card>
          <div className="grid grid-cols-3 gap-1 text-inkSoft font-semibold text-[13px] pb-1 border-b border-[#F1E7E1]">
            <span>Возраст</span><span>Всего</span><span>День / ночь</span>
          </div>
          {SLEEP_NORMS.map((s, i) => (
            <div key={i} className="grid grid-cols-3 gap-1 py-2 border-b border-[#F6EDE8] last:border-0 text-[13px]">
              <span className="text-ink font-medium">{s.label}</span>
              <span className="text-ink">{s.total}</span>
              <span className="text-inkSoft text-[12px]">{s.day} · {s.night}</span>
            </div>
          ))}
        </Card>
      </div>
    );
  }

  // ── Экран: статьи выбранной категории ───────────────────────
  const cat = ENCYCLOPEDIA.find(c => c.id === view);
  return (
    <div key={view} className="fade-screen px-5 pt-6 pb-4">
      <BackBar title={cat.name} icon={cat.icon} />
      <div className="space-y-2">
        {cat.articles.map((art, i) => <CareArticle key={i} art={art} />)}
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН 4 — РОСТ (ТРЕКЕР)                                             */
/* ------------------------------------------------------------------ */

function percentileBand(months, kg) {
  const m = Math.min(12, Math.max(0, Math.round(months)));
  const p = WHO_WEIGHT_PERCENTILES[m];
  if (!p) return { label: '—', color: '#8C7B74' };
  if (kg < p.p3) return { label: 'ниже 3‰', color: '#D9925A' };
  if (kg < p.p15) return { label: '3–15‰', color: '#E0B15C' };
  if (kg <= p.p85) return { label: '15–85‰ (норма)', color: '#7BBFB5' };
  if (kg <= p.p97) return { label: '85–97‰', color: '#E0B15C' };
  return { label: 'выше 97‰', color: '#D9925A' };
}

function GrowthChart({ measurements, birthDate }) {
  const W = 320, H = 180, pad = 28;
  const maxM = 12;
  const months = Array.from({ length: 13 }, (_, i) => i);
  const allKg = months.flatMap(m => [WHO_WEIGHT_PERCENTILES[m].p3, WHO_WEIGHT_PERCENTILES[m].p97]);
  const minY = Math.min(...allKg) - 0.5, maxY = Math.max(...allKg) + 0.5;
  const x = m => pad + (m / maxM) * (W - pad * 1.4);
  const y = kg => H - pad - ((kg - minY) / (maxY - minY)) * (H - pad * 1.6);

  const line = key => months.map(m => `${x(m)},${y(WHO_WEIGHT_PERCENTILES[m][key])}`).join(' ');

  const pts = measurements
    .filter(m => m.weight)
    .map(m => {
      const mo = daysBetween(birthDate) === 0 ? 0 : (new Date(m.date) - new Date(birthDate)) / (86400000 * 30.44);
      return { mo, kg: m.weight / 1000, date: m.date };
    })
    .filter(p => p.mo >= 0 && p.mo <= maxM)
    .sort((a, b) => a.mo - b.mo);

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="w-full" role="img" aria-label="График веса с перцентилями ВОЗ">
      {/* band норма */}
      <polygon points={`${line('p15')} ${months.slice().reverse().map(m=>`${x(m)},${y(WHO_WEIGHT_PERCENTILES[m].p85)}`).join(' ')}`} fill="#7BBFB5" opacity="0.12" />
      {[['p3','#E0A85C'],['p15','#7BBFB5'],['p50','#7BBFB5'],['p85','#7BBFB5'],['p97','#E0A85C']].map(([k,c]) => (
        <polyline key={k} points={line(k)} fill="none" stroke={c} strokeWidth={k==='p50'?1.6:1} strokeDasharray={k==='p50'?'':'3 3'} opacity="0.6" />
      ))}
      {/* подписи перцентилей */}
      <text x={x(12)+2} y={y(WHO_WEIGHT_PERCENTILES[12].p50)} fontSize="7" fill="#8C7B74">50‰</text>
      {/* оси подписи */}
      {[0,3,6,9,12].map(m => <text key={m} x={x(m)} y={H-8} fontSize="8" fill="#8C7B74" textAnchor="middle">{m}м</text>)}
      {/* данные */}
      {pts.length > 1 && <polyline points={pts.map(p=>`${x(p.mo)},${y(p.kg)}`).join(' ')} fill="none" stroke="#6394C1" strokeWidth="2" />}
      {pts.map((p, i) => <circle key={i} cx={x(p.mo)} cy={y(p.kg)} r="3.5" fill="#6394C1" stroke="#fff" strokeWidth="1.5" />)}
    </svg>
  );
}

function GrowthScreen({ profile, days, setProfile }) {
  const [weights, setWeights] = useLocalState(LS.weight, []);
  const [feeds, setFeeds] = useLocalState(LS.feeding, []);
  const [sleeps, setSleeps] = useLocalState(LS.sleep, []);
  const [diapers, setDiapers] = useLocalState(LS.diaper, []);

  const [wForm, setWForm] = useState({ date: todayKey(), weight: '', height: '', head: '' });
  const [feedForm, setFeedForm] = useState({ type: profile.feedingType === 'Грудное' ? 'breast' : 'bottle', volume: '', breast: 'Левая', minutes: '', time: '' });
  const [sleepForm, setSleepForm] = useState({ start: '', end: '' });
  const [diaperForm, setDiaperForm] = useState({ time: '', kind: 'wet' });

  // Превращает "ЧЧ:ММ" в метку времени сегодняшнего дня; пусто → сейчас
  const timeTs = (hhmm) => {
    if (!hhmm) return Date.now();
    const [h, m] = hhmm.split(':').map(Number);
    const d = new Date(); d.setHours(h, m, 0, 0);
    return d.getTime();
  };

  const addWeight = () => {
    if (!wForm.weight) return;
    const m = { ...wForm, weight: Number(wForm.weight), height: Number(wForm.height)||null, head: Number(wForm.head)||null, id: Date.now() };
    setWeights(prev => [...prev, m].sort((a,b) => new Date(a.date)-new Date(b.date)));
    setProfile(p => ({ ...p, currentWeight: m.weight }));
    setWForm({ date: todayKey(), weight: '', height: '', head: '' });
  };
  const removeWeight = id => setWeights(prev => prev.filter(w => w.id !== id));

  const last24 = ts => Date.now() - ts < 86400000;
  const feeds24 = feeds.filter(f => last24(f.ts));
  const volSum = feeds24.reduce((s,f) => s + (f.volume||0), 0);
  const diapers24 = diapers.filter(d => last24(d.ts));
  const wet = diapers24.filter(d => d.kind==='wet').length;
  const dirty = diapers24.filter(d => d.kind==='dirty').length;

  const openSleep = sleeps.find(s => !s.end);
  const sleeps24 = sleeps.filter(s => s.end && last24(s.start));
  const sleepMin = sleeps24.reduce((s,x) => s + (x.end-x.start)/60000, 0);

  const addFeed = () => {
    const rec = { id: Date.now(), ts: timeTs(feedForm.time), type: feedForm.type };
    if (feedForm.type === 'bottle') { if(!feedForm.volume) return; rec.volume = Number(feedForm.volume); }
    else { rec.breast = feedForm.breast; rec.minutes = Number(feedForm.minutes)||0; }
    setFeeds(prev => [rec, ...prev]);
    setFeedForm(f => ({ ...f, volume: '', minutes: '', time: '' }));
  };
  const removeFeed = id => setFeeds(prev => prev.filter(f => (f.id||f.ts) !== id));

  const toggleSleep = () => {
    if (openSleep) setSleeps(prev => prev.map(s => s.id===openSleep.id ? {...s, end: Date.now()} : s));
    else setSleeps(prev => [{ id: Date.now(), start: Date.now(), end: null }, ...prev]);
  };
  const addSleepManual = () => {
    if (!sleepForm.start || !sleepForm.end) return;
    setSleeps(prev => [{ id: Date.now(), start: timeTs(sleepForm.start), end: timeTs(sleepForm.end) }, ...prev]);
    setSleepForm({ start: '', end: '' });
  };
  const removeSleep = id => setSleeps(prev => prev.filter(s => s.id !== id));

  const addDiaper = kind => setDiapers(prev => [{ id: Date.now(), ts: Date.now(), kind }, ...prev]);
  const addDiaperManual = () => {
    setDiapers(prev => [{ id: Date.now(), ts: timeTs(diaperForm.time), kind: diaperForm.kind }, ...prev]);
    setDiaperForm(f => ({ ...f, time: '' }));
  };
  const removeDiaper = id => setDiapers(prev => prev.filter(d => (d.id||d.ts) !== id));

  const lastW = weights[weights.length-1];
  const months = days / 30.44;
  const band = lastW ? percentileBand(months, lastW.weight/1000) : null;
  // ожидаемая прибавка для текущего возраста
  const gainPerDay = months < 3 ? '25–30 г/день (~750–900 г/мес)'
    : months < 6 ? '20–25 г/день (~600 г/мес)'
    : months < 9 ? '~15 г/день (~450 г/мес)'
    : '~10 г/день (~300 г/мес)';

  const inputCls = 'w-full min-h-[44px] px-3 rounded-2xl border border-[#EADAD3] outline-none focus:border-terra bg-white';
  const lbl = 'text-[12px] text-inkSoft font-medium';

  return (
    <div className="fade-screen px-5 pt-6 pb-4 space-y-5">
      <SectionTitle sub="Антропометрия, нормы прибавки и ежедневные трекеры">Рост и трекеры</SectionTitle>

      {/* Антропометрия */}
      <Card>
        <div className="flex items-center gap-2 mb-3"><span className="text-xl">📈</span><h3 className="text-lg text-ink">Вес и рост</h3></div>
        {weights.length === 0 ? (
          <p className="text-inkSoft text-[13px] mb-1">Пока нет замеров. Добавь первый — и появится график с перцентилями ВОЗ. 🌱</p>
        ) : (
          <>
            <GrowthChart measurements={weights} birthDate={profile.birthDate} />
            {band && (
              <div className="flex items-center gap-2 mt-2 justify-center">
                <span className="w-3 h-3 rounded-full" style={{ background: band.color }} />
                <span className="text-[13px] text-ink">Последний вес {(lastW.weight/1000).toFixed(2)} кг — <b style={{color:band.color}}>{band.label}</b></span>
              </div>
            )}
            {/* История замеров с удалением */}
            <div className="mt-3 space-y-1">
              {[...weights].reverse().slice(0,6).map(w => (
                <div key={w.id} className="flex items-center text-[13px] text-ink py-1 border-b border-[#F6EDE8] last:border-0">
                  <span className="w-24 text-inkSoft">{new Date(w.date).toLocaleDateString('ru-RU',{day:'numeric',month:'short'})}</span>
                  <span className="flex-1">{(w.weight/1000).toFixed(2)} кг{w.height?` · ${w.height} см`:''}{w.head?` · 👶 ${w.head}`:''}</span>
                  <button onClick={()=>removeWeight(w.id)} aria-label="Удалить замер" className="text-inkSoft w-8 h-8 shrink-0">✕</button>
                </div>
              ))}
            </div>
          </>
        )}

        <div className="mt-4 grid grid-cols-2 gap-3">
          <label className="block"><span className={lbl}>Дата</span>
            <input className={inputCls+' mt-1'} type="date" value={wForm.date} max={todayKey()} onChange={e=>setWForm(f=>({...f,date:e.target.value}))} /></label>
          <label className="block"><span className={lbl}>Вес, граммы</span>
            <input className={inputCls+' mt-1'} type="number" inputMode="numeric" placeholder="напр. 4500" value={wForm.weight} onChange={e=>setWForm(f=>({...f,weight:e.target.value}))} /></label>
          <label className="block"><span className={lbl}>Рост, см</span>
            <input className={inputCls+' mt-1'} type="number" inputMode="numeric" placeholder="напр. 56" value={wForm.height} onChange={e=>setWForm(f=>({...f,height:e.target.value}))} /></label>
          <label className="block"><span className={lbl}>Окружность головы, см</span>
            <input className={inputCls+' mt-1'} type="number" inputMode="numeric" placeholder="напр. 38" value={wForm.head} onChange={e=>setWForm(f=>({...f,head:e.target.value}))} /></label>
        </div>
        <PrimaryButton className="w-full mt-3" onClick={addWeight} disabled={!wForm.weight}>Добавить замер</PrimaryButton>
      </Card>

      {/* Нормы прибавки — советы */}
      <Card className="bg-gradient-to-br from-white to-[#EAF2FA]">
        <div className="flex items-center gap-2 mb-2"><span className="text-xl">📐</span><h3 className="text-lg text-ink">Нормы прибавки веса</h3></div>
        <p className="text-[13px] text-ink mb-2">Ожидаемо для возраста <b className="text-terraDk">{ageLabel(profile.birthDate)}</b>: <b>{gainPerDay}</b>.</p>
        <div className="text-[13px] text-ink space-y-1.5">
          <p>• <b>0–3 мес:</b> ~25–30 г/день · <b>3–6 мес:</b> ~20–25 г/день · <b>6–12 мес:</b> ~10–15 г/день.</p>
          <p>• Минимум по ВОЗ — не менее <b>0.5 кг в месяц</b> в первом полугодии.</p>
          <p>• Отклонение ±10% от средних — норма. Каждый малыш растёт по-своему.</p>
        </div>
        <div className="mt-3 bg-white rounded-xl p-3 text-[13px] text-ink leading-relaxed">
          <p className="font-semibold mb-1">🧠 Принцип Комаровского</p>
          Смотри не на одну цифру на весах, а на <b>динамику и самочувствие</b>: активность, настроение, 6+ мокрых подгузников, развитие по возрасту. На смеси <b>не перекармливай</b> — даже искусственник умеет саморегуляцию, не заставляй доедать. Взвешивай не чаще раза в неделю.
        </div>
        <p className="text-[11px] text-inkSoft mt-2">По материалам ВОЗ и доказательной педиатрии (Е. Комаровский, неонатолог В. Ченчак). Любые сомнения — к своему педиатру.</p>
      </Card>

      {/* Кормления */}
      <Card>
        <div className="flex items-center gap-2 mb-3"><span className="text-xl">🍼</span><h3 className="text-lg text-ink">Кормления</h3></div>
        <div className="flex gap-2 mb-2">
          {[['bottle','Бутылочка'],['breast','Грудь']].map(([v,l]) => (
            <button key={v} onClick={()=>setFeedForm(f=>({...f,type:v}))}
              className={`flex-1 min-h-[44px] rounded-2xl border text-sm font-medium ${feedForm.type===v?'bg-teal text-white border-teal':'border-[#EADAD3] text-ink'}`}>{l}</button>
          ))}
        </div>
        {feedForm.type === 'bottle' ? (
          <input className={inputCls} type="number" inputMode="numeric" placeholder="Объём, мл" value={feedForm.volume} onChange={e=>setFeedForm(f=>({...f,volume:e.target.value}))} />
        ) : (
          <div>
            <p className="text-[12px] text-inkSoft mb-1">Какая грудь:</p>
            <div className="flex gap-2">
              {['Левая','Правая'].map(b => (
                <button key={b} onClick={()=>setFeedForm(f=>({...f,breast:b}))}
                  className={`flex-1 min-h-[44px] rounded-2xl border font-medium text-sm ${feedForm.breast===b?'bg-teal text-white border-teal':'border-[#EADAD3] text-ink'}`}>{b}</button>
              ))}
            </div>
            <input className={inputCls+' mt-2'} type="number" inputMode="numeric" placeholder="Сколько минут кормила" value={feedForm.minutes} onChange={e=>setFeedForm(f=>({...f,minutes:e.target.value}))} />
          </div>
        )}
        <div className="flex items-center gap-2 mt-2">
          <input className="w-[120px] min-h-[44px] px-3 rounded-2xl border border-[#EADAD3] outline-none focus:border-terra" type="time" value={feedForm.time} onChange={e=>setFeedForm(f=>({...f,time:e.target.value}))} aria-label="Время кормления" />
          <span className="text-[12px] text-inkSoft">пусто = сейчас</span>
        </div>
        <PrimaryButton className="w-full mt-2" onClick={addFeed}>Записать кормление</PrimaryButton>
        <p className="text-[13px] text-inkSoft mt-3">За 24 ч: <b className="text-ink">{feeds24.length}</b> кормл.{volSum>0 && <> · <b className="text-ink">{volSum} мл</b></>}</p>
        <div className="mt-1 max-h-40 overflow-y-auto">
          {feeds24.map(f => (
            <div key={f.id||f.ts} className="flex items-center text-[13px] text-ink py-1 border-b border-[#F6EDE8] last:border-0">
              <span className="w-14 text-inkSoft">{fmtTime(f.ts)}</span>
              <span className="flex-1">{f.type==='bottle' ? `🍼 ${f.volume} мл` : `🤱 ${f.breast||''} · ${f.minutes} мин`}</span>
              <button onClick={()=>removeFeed(f.id||f.ts)} aria-label="Удалить кормление" className="text-inkSoft w-8 h-8 shrink-0">✕</button>
            </div>
          ))}
        </div>
      </Card>

      {/* Сон */}
      <Card>
        <div className="flex items-center gap-2 mb-3"><span className="text-xl">💤</span><h3 className="text-lg text-ink">Сон</h3></div>
        <button onClick={toggleSleep}
          className={`w-full min-h-[44px] rounded-2xl font-semibold text-white ${openSleep ? 'bg-terra' : 'bg-teal'}`}>
          {openSleep ? `Проснулся (спит с ${fmtTime(openSleep.start)})` : 'Уснул сейчас'}
        </button>

        {/* Добавить сон вручную */}
        <div className="mt-3 bg-milk rounded-xl p-3">
          <p className="text-[12px] text-inkSoft mb-2">Или впиши прошедший сон вручную:</p>
          <div className="flex items-center gap-2">
            <label className="text-[12px] text-inkSoft">с
              <input className="ml-1 min-h-[40px] px-2 rounded-xl border border-[#EADAD3] outline-none focus:border-terra" type="time" value={sleepForm.start} onChange={e=>setSleepForm(f=>({...f,start:e.target.value}))} /></label>
            <label className="text-[12px] text-inkSoft">до
              <input className="ml-1 min-h-[40px] px-2 rounded-xl border border-[#EADAD3] outline-none focus:border-terra" type="time" value={sleepForm.end} onChange={e=>setSleepForm(f=>({...f,end:e.target.value}))} /></label>
            <button onClick={addSleepManual} disabled={!sleepForm.start||!sleepForm.end}
              className="ml-auto min-h-[40px] px-4 rounded-xl bg-teal text-white text-sm font-semibold disabled:opacity-50">Добавить</button>
          </div>
        </div>

        <p className="text-[13px] text-inkSoft mt-3">Сон за 24 ч: <b className="text-ink">{Math.floor(sleepMin/60)} ч {Math.round(sleepMin%60)} мин</b> · {sleeps24.length} {plural(sleeps24.length,'сон','сна','снов')}</p>
        <div className="mt-1 max-h-40 overflow-y-auto">
          {sleeps.filter(s=>s.end && last24(s.start)).map(s => (
            <div key={s.id} className="flex items-center text-[13px] text-ink py-1 border-b border-[#F6EDE8] last:border-0">
              <span className="flex-1">😴 {fmtTime(s.start)}–{fmtTime(s.end)} · {Math.round((s.end-s.start)/60000)} мин</span>
              <button onClick={()=>removeSleep(s.id)} aria-label="Удалить сон" className="text-inkSoft w-8 h-8 shrink-0">✕</button>
            </div>
          ))}
        </div>
      </Card>

      {/* Подгузники */}
      <Card>
        <div className="flex items-center gap-2 mb-3"><span className="text-xl">💩</span><h3 className="text-lg text-ink">Подгузники</h3></div>
        <div className="flex gap-2">
          <button onClick={()=>addDiaper('wet')} className="flex-1 min-h-[44px] rounded-2xl bg-[#E8F2F0] text-teal font-semibold">💧 Мокрый сейчас</button>
          <button onClick={()=>addDiaper('dirty')} className="flex-1 min-h-[44px] rounded-2xl bg-[#EAF2FA] text-terraDk font-semibold">💩 Грязный сейчас</button>
        </div>

        {/* Добавить вручную */}
        <div className="mt-3 bg-milk rounded-xl p-3">
          <p className="text-[12px] text-inkSoft mb-2">Или впиши вручную:</p>
          <div className="flex items-center gap-2">
            <input className="min-h-[40px] px-2 rounded-xl border border-[#EADAD3] outline-none focus:border-terra" type="time" value={diaperForm.time} onChange={e=>setDiaperForm(f=>({...f,time:e.target.value}))} aria-label="Время" />
            <select className="min-h-[40px] px-2 rounded-xl border border-[#EADAD3] outline-none focus:border-terra text-sm" value={diaperForm.kind} onChange={e=>setDiaperForm(f=>({...f,kind:e.target.value}))}>
              <option value="wet">💧 Мокрый</option>
              <option value="dirty">💩 Грязный</option>
            </select>
            <button onClick={addDiaperManual} className="ml-auto min-h-[40px] px-4 rounded-xl bg-teal text-white text-sm font-semibold">Добавить</button>
          </div>
        </div>

        <p className="text-[13px] text-inkSoft mt-3">За 24 ч: 💧 <b className="text-ink">{wet}</b> · 💩 <b className="text-ink">{dirty}</b></p>
        <p className={`text-[12px] mt-1 ${wet>=6?'text-teal':'text-inkSoft'}`}>
          {wet>=6 ? '✓ 6+ мокрых — признак достаточного питания' : 'Норма — 6+ мокрых подгузников в сутки'}
        </p>
        <div className="mt-2 max-h-36 overflow-y-auto">
          {diapers24.map(d => (
            <div key={d.id||d.ts} className="flex items-center text-[13px] text-ink py-1 border-b border-[#F6EDE8] last:border-0">
              <span className="w-14 text-inkSoft">{fmtTime(d.ts)}</span>
              <span className="flex-1">{d.kind==='wet'?'💧 Мокрый':'💩 Грязный'}</span>
              <button onClick={()=>removeDiaper(d.id||d.ts)} aria-label="Удалить" className="text-inkSoft w-8 h-8 shrink-0">✕</button>
            </div>
          ))}
        </div>
      </Card>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН 5 — AI-НЕОНАТОЛОГ (ЧАТ)                                                   */
/* ------------------------------------------------------------------ */

const QUICK_Q = ['Сколько должен есть?', 'Почему плачет?', 'Это нормально?', 'Помоги уложить спать'];

function NannyScreen({ profile, days }) {
  const [chat, setChat] = useLocalState(LS.chat, []);
  const [input, setInput] = useState('');
  const [sending, setSending] = useState(false);
  const [error, setError] = useState('');
  const endRef = useRef(null);

  useEffect(() => { endRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [chat, sending]);

  const systemPrompt = `Ты — Лина, опытный врач-неонатолог и педиатр с подготовкой консультанта по грудному вскармливанию. Ты практикуешь доказательную медицину (ВОЗ, AAP, российские клинические протоколы; по духу — как Е. Комаровский и неонатолог В. Ченчак). Ты тёплая, спокойная и по-настоящему компетентная: рассуждаешь как клиницист, а не выдаёшь поверхностные шаблонные списки.

КОНТЕКСТ РЕБЁНКА (из профиля):
${babyContextLines(profile, days)}

КАК ТЫ ДУМАЕШЬ И ОТВЕЧАЕШЬ:
1. Сначала пойми ситуацию. Если не хватает данных для безопасного ответа (например, какая именно температура у ребёнка и чем измерена, как давно длится, есть ли другие симптомы) — коротко уточни, прежде чем делать выводы.
2. Давай конкретный, обоснованный ответ с объяснением «почему», опираясь на доказательную медицину. Не общими фразами, а по сути.
3. Чётко разделяй три вещи: что является нормой, за чем наблюдать, и когда нужно к врачу или вызвать скорую.
4. Учитывай точный возраст ребёнка (для недоношенных — корректированный возраст). Что норма в 1 неделю, может быть тревожным в 3 месяца, и наоборот.
5. Обращайся к маме и к ребёнку по именам. Пиши тепло и по-человечески, но без сюсюканья и без канцелярита.

КЛЮЧЕВЫЕ ВРАЧЕБНЫЕ ПРИНЦИПЫ (применяй обязательно и не ошибайся в них):
• ГРУДНОЕ ВСКАРМЛИВАНИЕ ПРИ БОЛЕЗНИ МАМЫ. Если кормящая мама заболела обычной инфекцией (ОРВИ, грипп, температура, кишечная инфекция) — грудное вскармливание НЕ прекращают. С грудным молоком малышу передаются мамины антитела, которые его ЗАЩИЩАЮТ. Прекращение ГВ в этой ситуации — вредный миф. Мама продолжает кормить, тщательно моет руки, при респираторной инфекции надевает маску при контакте. Но не обещай абсолютную защиту: ГВ снижает риск, а не гарантирует, что малыш точно не заболеет — говори честно.
• ЗДОРОВЬЕ САМОЙ МАМЫ ВАЖНО. Температура 38+ у недавно родившей или кормящей женщины — повод позаботиться и о себе: проверить грудь на признаки лактостаза/мастита (болезненное уплотнение, покраснение, жар), пить много жидкости, отдыхать, при необходимости — жаропонижающее, совместимое с ГВ (по согласованию с врачом), и при высокой или держащейся температуре обратиться к врачу для себя.
• ДОВЕРЯЙ СЛОВАМ МАМЫ. Если мама пишет, что кормит грудью (или иначе, чем указано в профиле) — исходи из её слов, а не из профиля, и мягко предложи обновить данные в настройках (⚙️).
• Витамин D, безопасный сон на спине, отклик на плач, отсутствие необходимости в раннем «развивании» — по доказательным принципам.

БЕЗОПАСНОСТЬ:
6. Ты не ставишь окончательных диагнозов, но можешь объяснить вероятные причины и дать доказательные рекомендации.
7. КРАСНЫЕ ФЛАГИ — немедленно скажи «срочно к педиатру» или «вызывай скорую»: у новорождённого температура ≥38°C, вялость или трудно разбудить, отказ от еды, судороги, синюшность кожи/губ, затруднённое или частое дыхание, рвота «фонтаном», признаки обезвоживания (сухой подгузник 6+ часов, западший родничок), выбухающий родничок, монотонный пронзительный крик.
8. Уместно (не в каждом предложении) напоминай, что это общая информация и при сомнениях нужно показать малыша врачу очно.

ПОДДЕРЖКА:
9. Поддерживай маму эмоционально — тревога, усталость, слёзы и выгорание в материнстве нормальны. Но поддержка не заменяет конкретного врачебного ответа: дай и то, и другое.

Отвечай на том же языке, на котором пишет мама. Будь полезной, точной и человечной.`;

  const send = async (text) => {
    const content = (text ?? input).trim();
    if (!content || sending) return;
    setInput(''); setError('');
    const userMsg = { role: 'user', content };
    const next = [...chat, userMsg];
    setChat(next.slice(-50));
    setSending(true);
    try {
      const apiMsgs = next.slice(-20).map(m => ({ role: m.role, content: m.content }));
      const reply = await callClaude(apiMsgs, systemPrompt, { maxTokens: 1200 });
      setChat(prev => [...prev, { role: 'assistant', content: reply }].slice(-50));
    } catch (e) {
      const m = e.message || '';
      if (m === 'NO_KEY') {
        setError('Добавь ключ Claude API в настройках (⚙️ вверху), чтобы общаться со Стефаном.');
      } else if (m.includes('401')) {
        setError('Ключ не принят. Проверь в ⚙️, что ключ скопирован полностью (начинается с sk-ant-) и без пробелов.');
      } else if (m.includes('400') || m.includes('404') || m.toLowerCase().includes('model')) {
        setError('Техническая ошибка модели. Обнови страницу (Cmd+Shift+R) — должно заработать.');
      } else if (m.includes('429')) {
        setError('Слишком много запросов или закончился баланс. Проверь баланс в console.anthropic.com → Billing.');
      } else if (m.includes('credit') || m.includes('billing')) {
        setError('Нужно пополнить баланс API в console.anthropic.com → Plans & Billing.');
      } else {
        setError('Стефан сейчас недоступен. Причина: ' + m.slice(0, 160));
      }
    } finally {
      setSending(false);
    }
  };

  return (
    <div className="fade-screen flex flex-col" style={{ height: '100%' }}>
      <div className="px-5 pt-5 pb-3 flex items-center gap-3 border-b border-[#F1E7E1] bg-milk">
        <NannyAvatar size={44} />
        <div>
          <h1 className="text-xl text-ink leading-none">Стефан</h1>
          <p className="text-teal text-[12px]">AI-неонатолог · всегда на связи</p>
        </div>
        {chat.length > 0 && (
          <button onClick={() => setChat([])} className="ml-auto text-inkSoft text-[12px] min-h-[44px]">Очистить</button>
        )}
      </div>

      <div className="flex-1 overflow-y-auto px-4 py-4 space-y-3">
        {chat.length === 0 && (
          <div className="text-center mt-6">
            <NannyAvatar size={72} />
            <p className="text-ink font-display text-xl mt-3">Привет, {profile.motherName}! 🤍</p>
            <p className="text-inkSoft text-[14px] max-w-xs mx-auto mt-1">
              Я Стефан. Спроси меня о чём угодно — кормление, сон, плач, развитие или просто если тяжело.
            </p>
          </div>
        )}
        {chat.map((m, i) => (
          <div key={i} className={`flex ${m.role==='user'?'justify-end':'justify-start'}`}>
            {m.role==='assistant' && <div className="mr-2 mt-1"><NannyAvatar size={28} /></div>}
            <div className={`max-w-[78%] px-4 py-2.5 text-[14px] leading-relaxed whitespace-pre-wrap
              ${m.role==='user'
                ? 'bg-terra text-white rounded-[18px] rounded-br-md'
                : 'bg-white text-ink shadow-card rounded-[18px] rounded-bl-md'}`}>
              {m.content}
            </div>
          </div>
        ))}
        {sending && (
          <div className="flex justify-start">
            <div className="mr-2 mt-1"><NannyAvatar size={28} /></div>
            <div className="bg-white shadow-card rounded-[18px] rounded-bl-md px-4 py-3"><Dots /></div>
          </div>
        )}
        {error && <p className="text-center text-[13px] text-terraDk bg-[#EAF2FA] rounded-card p-3">{error}</p>}
        <div ref={endRef} />
      </div>

      {/* Быстрые вопросы */}
      <div className="px-4 pb-1 flex gap-2 overflow-x-auto no-scrollbar">
        {QUICK_Q.map(q => (
          <button key={q} onClick={() => send(q)} disabled={sending}
            className="whitespace-nowrap text-[12px] bg-white shadow-card text-ink rounded-full px-3 py-2 min-h-[36px] active:scale-95 transition disabled:opacity-50">
            {q}
          </button>
        ))}
      </div>

      {/* Ввод */}
      <div className="px-4 py-3 flex gap-2 items-end border-t border-[#F1E7E1] bg-milk">
        <textarea
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyDown={e => { if (e.key==='Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
          rows={1}
          placeholder="Напиши Стефану…"
          className="flex-1 resize-none max-h-28 px-4 py-2.5 rounded-3xl border border-[#EADAD3] bg-white outline-none focus:border-terra text-[14px]"
        />
        <button onClick={() => send()} disabled={sending || !input.trim()} aria-label="Отправить"
          className="w-11 h-11 shrink-0 rounded-full bg-terra text-white text-lg flex items-center justify-center disabled:opacity-50 active:scale-95 transition">
          ↑
        </button>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  АЛЕРТЫ                                                              */
/* ------------------------------------------------------------------ */

function AlertBanner({ profile, days }) {
  const [dismissed, setDismissed] = useLocalState(LS.dismissed, []);
  const active = AGE_ALERTS.filter(a => days >= a.fromDay && days <= a.toDay && !dismissed.includes(a.id));
  if (active.length === 0) return null;
  const a = active[0];
  const styles = {
    info:      'bg-[#E8F2F0] text-teal border-teal',
    milestone: 'bg-[#EAF2FA] text-terraDk border-terra',
    warning:   'bg-[#D9E8F5] text-terraDk border-terraDk',
  };
  const icon = { info: 'ℹ️', milestone: '🌟', warning: '⚠️' }[a.type];
  return (
    <div className={`mx-5 mt-4 rounded-card border-l-4 p-3 flex gap-3 ${styles[a.type]} fade-screen`}>
      <span className="text-lg">{icon}</span>
      <div className="flex-1">
        <p className="font-semibold text-[14px] text-ink">{a.title}</p>
        <p className="text-[13px] text-ink/80">{a.message}</p>
      </div>
      <button onClick={() => setDismissed(prev => [...prev, a.id])} aria-label="Закрыть" className="text-inkSoft self-start text-lg leading-none">×</button>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  НАСТРОЙКИ (API-ключ)                                                */
/* ------------------------------------------------------------------ */

function SettingsModal({ onClose, profile, onReset, onSave }) {
  const [key, setKey] = useState(loadLS(LS.apiKey, ''));
  const [p, setP] = useState({
    motherName: profile.motherName || '', babyName: profile.babyName || '',
    birthDate: profile.birthDate || '', feedingType: profile.feedingType || 'Грудное',
    currentWeight: profile.currentWeight || '',
  });
  const setF = (k, v) => setP(s => ({ ...s, [k]: v }));
  const [testMsg, setTestMsg] = useState('');
  const [testing, setTesting] = useState(false);
  const testKey = async () => {
    setTesting(true); setTestMsg('Проверяю…');
    saveLS(LS.apiKey, key.trim());   // тестируем то, что сейчас в поле
    try {
      await callClaude([{ role: 'user', content: 'Ответь одним словом: привет' }], 'Ты тест связи.', { maxTokens: 20 });
      setTestMsg('✅ Ключ работает! Стефан готов отвечать.');
    } catch (e) {
      const m = e.message || '';
      if (m === 'NO_KEY') setTestMsg('Сначала вставь ключ в поле выше.');
      else if (m.includes('401')) setTestMsg('❌ Ключ не принят (401). Скопируй ключ заново целиком, без пробелов.');
      else if (m.includes('404') || m.toLowerCase().includes('model')) setTestMsg('❌ Проблема с моделью: ' + m.slice(0, 180));
      else if (m.includes('400')) setTestMsg('❌ Ошибка запроса (400): ' + m.slice(0, 180));
      else if (m.includes('429') || m.toLowerCase().includes('credit') || m.toLowerCase().includes('balance')) setTestMsg('❌ Баланс/лимит: пополни баланс в console.anthropic.com → Billing.');
      else setTestMsg('❌ ' + m.slice(0, 220));
    } finally { setTesting(false); }
  };
  const save = () => {
    saveLS(LS.apiKey, key.trim());
    onSave({ ...p, currentWeight: Number(p.currentWeight) || profile.currentWeight });
    onClose();
  };
  const inputCls = 'w-full min-h-[44px] mt-1 px-3 rounded-2xl border border-[#EADAD3] outline-none focus:border-terra';
  // показать текущий возраст по введённой дате — чтобы сразу видеть, что дата верная
  const agePreview = p.birthDate ? ageLabel(p.birthDate) : '';

  return (
    <div className="fixed inset-0 z-50 bg-black/30 flex items-end sm:items-center justify-center" onClick={onClose}>
      <div className="bg-white w-full sm:max-w-md rounded-t-3xl sm:rounded-card p-5 fade-screen max-h-[92vh] overflow-y-auto" onClick={e=>e.stopPropagation()}>
        <h2 className="text-xl text-ink mb-3">Настройки</h2>

        <p className="text-[13px] text-ink font-semibold mb-1">Данные ребёнка</p>
        <label className="block mb-2 text-[12px] text-inkSoft">Имя малыша
          <input className={inputCls} value={p.babyName} onChange={e=>setF('babyName', e.target.value)} /></label>
        <label className="block mb-1 text-[12px] text-inkSoft">Дата рождения
          <input type="date" max={todayKey()} className={inputCls} value={p.birthDate} onChange={e=>setF('birthDate', e.target.value)} /></label>
        {agePreview && <p className="text-[12px] text-teal mb-2">Сейчас малышу: <b>{agePreview}</b></p>}
        <label className="block mb-2 text-[12px] text-inkSoft">Имя мамы
          <input className={inputCls} value={p.motherName} onChange={e=>setF('motherName', e.target.value)} /></label>
        <div className="mb-2"><span className="text-[12px] text-inkSoft">Тип кормления</span>
          <div className="flex gap-2 mt-1">
            {['Грудное','Смесь','Смешанное'].map(t => (
              <button key={t} type="button" onClick={()=>setF('feedingType', t)}
                className={`flex-1 min-h-[40px] rounded-2xl border text-[13px] font-medium ${p.feedingType===t?'bg-terra text-white border-terra':'border-[#EADAD3] text-ink'}`}>{t}</button>
            ))}
          </div>
        </div>
        <label className="block mb-2 text-[12px] text-inkSoft">Текущий вес (г)
          <input type="number" inputMode="numeric" className={inputCls} value={p.currentWeight} onChange={e=>setF('currentWeight', e.target.value)} /></label>

        <p className="text-[13px] text-ink font-semibold mb-1 mt-4">Ключ Claude API</p>
        <p className="text-[12px] text-inkSoft mb-1">Для Стефана (AI-неонатолога) и генерации планов. Хранится только на устройстве.</p>
        <input type="password" value={key} onChange={e=>setKey(e.target.value)} placeholder="sk-ant-…" className={inputCls} />
        <button onClick={testKey} disabled={testing || !key.trim()}
          className="w-full mt-2 min-h-[44px] rounded-2xl border border-teal text-teal font-semibold text-[13px] disabled:opacity-50">
          {testing ? 'Проверяю…' : '🔌 Проверить ключ'}
        </button>
        {testMsg && <p className={`text-[12px] mt-2 rounded-xl p-2 ${testMsg.startsWith('✅') ? 'bg-[#E8F2F0] text-teal' : 'bg-[#FBEFEB] text-terraDk'}`}>{testMsg}</p>}

        <PrimaryButton className="w-full mt-4" onClick={save}>Сохранить</PrimaryButton>
        <button onClick={onClose} className="w-full mt-2 min-h-[44px] text-inkSoft text-[13px]">Отмена</button>

        <div className="mt-3 pt-3 border-t border-[#F1E7E1]">
          <button onClick={() => { if (confirm('Удалить все данные и пройти онбординг заново?')) onReset(); }}
            className="text-terraDk text-[12px] min-h-[44px]">Сбросить все данные</button>
        </div>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН — РЕЖИМ ДНЯ (редактируемый)                                   */
/* ------------------------------------------------------------------ */

const HOUR_PX = 64;            // высота одного часа на таймлайне
const PX_PER_MIN = HOUR_PX / 60;
const HOURS = Array.from({ length: 25 }, (_, i) => i);

const normalizeSchedule = (list) => (Array.isArray(list) ? list : []).map((x, i) => ({
  id: x.id || `c_${Date.now()}_${i}`,
  time: x.time || '12:00',
  text: x.text || '',
  note: x.note || '',
  who: x.who === 'mom' ? 'mom' : 'baby',
}));

// Одна карточка на таймлайне — её можно перетаскивать по вертикали, чтобы менять время
function TimelineCard({ it, onDrag, onTap }) {
  const w = whoOf(it);
  const ref = useRef({ startY: 0, startMin: 0, moved: false, active: false });
  const down = (e) => {
    e.currentTarget.setPointerCapture(e.pointerId);
    ref.current = { startY: e.clientY, startMin: timeToMin(it.time), moved: false, active: true };
  };
  const move = (e) => {
    const d = ref.current;
    if (!d.active) return;
    const dy = e.clientY - d.startY;
    if (Math.abs(dy) > 4) d.moved = true;
    let m = d.startMin + dy / PX_PER_MIN;
    m = Math.max(0, Math.min(1435, Math.round(m / 5) * 5));
    onDrag(it.id, minToTime(m));
  };
  const up = () => {
    const d = ref.current;
    d.active = false;
    if (!d.moved) onTap(it.id);
  };
  return (
    <div
      onPointerDown={down} onPointerMove={move} onPointerUp={up} onPointerCancel={up}
      style={{ top: timeToMin(it.time) * PX_PER_MIN, background: w.soft, borderLeft: `3px solid ${w.bar}` }}
      className="absolute left-0 right-0 rounded-xl shadow-card px-2 py-1.5 touch-none select-none cursor-grab active:cursor-grabbing active:shadow-cardLg active:z-10"
    >
      <div className="flex items-center gap-1.5 min-w-0">
        <span className="text-[12px] font-semibold text-teal shrink-0 tabular-nums">{it.time}</span>
        <span className="text-[12px] shrink-0">{w.icon}</span>
        <span className="text-[12px] text-ink truncate flex-1 min-w-0">{it.text || 'Без названия'}</span>
        {it.note ? <span className="text-[11px] shrink-0" title={it.note}>💬</span> : null}
      </div>
    </div>
  );
}

// Нижняя панель редактирования одного пункта
function ItemEditor({ it, onChange, onDelete, onClose }) {
  return (
    <div className="fixed inset-0 z-30 flex items-end" onClick={onClose}>
      <div className="absolute inset-0 bg-black/30" />
      <div onClick={e => e.stopPropagation()}
        className="relative w-full max-w-md mx-auto bg-white rounded-t-3xl p-5 pb-7 shadow-cardLg fade-screen"
        style={{ paddingBottom: 'calc(1.75rem + env(safe-area-inset-bottom))' }}>
        <div className="w-10 h-1 bg-[#E5D6CE] rounded-full mx-auto mb-4" />

        <p className="text-inkSoft text-[12px] font-medium mb-1.5">Чьё это дело?</p>
        <div className="flex gap-2 mb-4">
          {['baby', 'mom'].map(k => (
            <button key={k} onClick={() => onChange({ who: k })}
              className={`flex-1 min-h-[44px] rounded-xl border-2 font-semibold text-[14px] flex items-center justify-center gap-1.5 transition
                ${it.who === k ? 'text-white' : 'bg-white text-ink border-[#EADAD3]'}`}
              style={it.who === k ? { background: WHO[k].bar, borderColor: WHO[k].bar } : {}}>
              {WHO[k].icon} {WHO[k].label}
            </button>
          ))}
        </div>

        <div className="flex gap-3 mb-3">
          <div className="shrink-0">
            <p className="text-inkSoft text-[12px] font-medium mb-1.5">Время</p>
            <input type="time" value={it.time} onChange={e => onChange({ time: e.target.value })}
              className="w-[110px] min-h-[44px] px-3 rounded-xl border border-[#EADAD3] text-teal font-semibold outline-none focus:border-terra" />
          </div>
          <div className="flex-1 min-w-0">
            <p className="text-inkSoft text-[12px] font-medium mb-1.5">Что делаем</p>
            <input value={it.text} onChange={e => onChange({ text: e.target.value })} placeholder="Кормление, сон, прогулка…"
              className="w-full min-h-[44px] px-3 rounded-xl border border-[#EADAD3] outline-none focus:border-terra text-[14px]" />
          </div>
        </div>

        <p className="text-inkSoft text-[12px] font-medium mb-1.5">💬 Комментарий <span className="font-normal">— деталь к делу, по желанию</span></p>
        <input value={it.note} onChange={e => onChange({ note: e.target.value })} placeholder="напр. на животике, уход за пупочком…"
          className="w-full min-h-[44px] px-3 rounded-xl border border-[#EADAD3] outline-none focus:border-terra text-[14px] mb-5" />

        <div className="flex gap-2">
          <button onClick={onDelete} className="min-h-[48px] px-4 rounded-btn text-terraDk font-semibold border border-[#EADAD3]">Удалить</button>
          <button onClick={onClose} className="flex-1 min-h-[48px] rounded-btn bg-teal text-white font-semibold active:scale-[0.99] transition">Готово</button>
        </div>
      </div>
    </div>
  );
}

function RoutineScreen({ profile, days }) {
  const [saved, setSaved] = useLocalState(LS.schedule, []);
  const [draft, setDraft] = useState(() => normalizeSchedule(saved));
  const [editId, setEditId] = useState(null);
  const [toast, setToast] = useState(false);

  const dirty = JSON.stringify(draft) !== JSON.stringify(normalizeSchedule(saved));
  const editing = draft.find(it => it.id === editId) || null;

  const fromTemplate = () => setDraft(
    buildSchedule(days, profile.feedingType, profile.currentWeight)
      .map((x, i) => ({ id: `c_${Date.now()}_${i}`, time: x.time, text: x.text, note: x.note || '', who: x.who || 'baby' }))
  );
  const update = (id, patch) => setDraft(prev => prev.map(it => it.id === id ? { ...it, ...patch } : it));
  const removeItem = (id) => { setDraft(prev => prev.filter(it => it.id !== id)); setEditId(null); };
  const addItem = (who) => {
    const id = `c_${Date.now()}`;
    setDraft(prev => [...prev, { id, time: '12:00', text: '', note: '', who }]);
    setEditId(id);
  };
  const save = () => { setSaved(draft); setToast(true); setTimeout(() => setToast(false), 1800); };
  const resetTemplate = () => { if (confirm('Вернуться к шаблону по возрасту? Текущие изменения в черновике заменятся (сохранятся только после «Сохранить»).')) fromTemplate(); };
  const clearAll = () => { if (confirm('Очистить весь режим? На «Сегодня» снова будет шаблон по возрасту.')) { setDraft([]); setSaved([]); } };

  // Экран создания, пока режима ещё нет
  if (draft.length === 0) {
    return (
      <div className="fade-screen px-5 pt-6 pb-4">
        <SectionTitle sub="Твой личный распорядок дня">Режим дня</SectionTitle>
        <div className="text-center mt-4">
          <div className="text-4xl mb-3">🗓️</div>
          <p className="text-inkSoft mb-5 max-w-xs mx-auto">
            Создай свой режим для себя и {profile.babyName}. Можно начать с готового шаблона по возрасту и поменять под себя — перетаскивая дела по времени.
          </p>
          <PrimaryButton onClick={fromTemplate}>Создать из шаблона по возрасту</PrimaryButton>
          <button onClick={() => addItem('baby')} className="block mx-auto mt-4 text-teal text-[13px] font-semibold min-h-[44px]">
            или собрать с нуля +
          </button>
        </div>
      </div>
    );
  }

  const lanes = { baby: draft.filter(it => it.who === 'baby'), mom: draft.filter(it => it.who === 'mom') };

  return (
    <div className="fade-screen px-5 pt-6">
      <SectionTitle sub="Перетаскивай дела вверх и вниз, чтобы менять время. Нажми на дело — чтобы изменить текст.">Режим дня</SectionTitle>

      {/* Дорожки: малыш и мама */}
      <div className="flex pl-9 gap-2 mb-1 sticky top-0 z-20 bg-milk/95 backdrop-blur py-1.5">
        {['baby', 'mom'].map(k => (
          <div key={k} className="flex-1 flex items-center justify-center gap-1.5 text-[12px] font-semibold rounded-lg py-1"
            style={{ background: WHO[k].soft, color: '#2D2520' }}>
            <span>{WHO[k].icon}</span>{WHO[k].label}
          </div>
        ))}
      </div>

      {/* Таймлайн */}
      <div className="relative" style={{ height: 24 * HOUR_PX }}>
        {/* Часовая сетка + подписи */}
        {HOURS.map(h => (
          <div key={h} className="absolute left-0 right-0 flex items-start" style={{ top: h * HOUR_PX }}>
            <span className="w-9 shrink-0 -mt-1.5 text-[10px] text-inkSoft tabular-nums text-right pr-1.5">
              {h < 24 ? `${String(h).padStart(2, '0')}:00` : ''}
            </span>
            <span className="flex-1 border-t border-[#F1E7E1]" />
          </div>
        ))}
        {/* Две колонки с карточками */}
        <div className="absolute inset-0 flex pl-9 gap-2">
          {['baby', 'mom'].map(k => (
            <div key={k} className="relative flex-1">
              {lanes[k].map(it => (
                <TimelineCard key={it.id} it={it}
                  onDrag={(id, time) => update(id, { time })}
                  onTap={(id) => setEditId(id)} />
              ))}
            </div>
          ))}
        </div>
      </div>

      {/* Добавить дело */}
      <div className="flex gap-2 mt-4">
        <button onClick={() => addItem('baby')} className="flex-1 min-h-[44px] rounded-btn border-2 border-dashed font-medium text-[13px] active:bg-white transition"
          style={{ borderColor: WHO.baby.bar, color: '#2D2520' }}>+ Дело малыша</button>
        <button onClick={() => addItem('mom')} className="flex-1 min-h-[44px] rounded-btn border-2 border-dashed font-medium text-[13px] active:bg-white transition"
          style={{ borderColor: WHO.mom.bar, color: '#2D2520' }}>+ Дело мамы</button>
      </div>

      <div className="flex gap-2 mt-2">
        <button onClick={resetTemplate} className="flex-1 min-h-[44px] text-teal text-[13px] font-semibold">↻ Вернуть шаблон</button>
        <button onClick={clearAll} className="flex-1 min-h-[44px] text-inkSoft text-[13px]">Очистить всё</button>
      </div>

      <p className="text-[12px] text-inkSoft mt-3 text-center pb-24">
        Этот режим показывается на вкладке «Сегодня» — там его можно отмечать галочками.
      </p>

      {/* Липкая панель сохранения */}
      <div className="sticky bottom-0 -mx-5 px-5 py-3 bg-milk/95 backdrop-blur border-t border-[#F1E7E1] flex items-center gap-3">
        <span className="text-[12px] text-inkSoft flex-1">
          {toast ? '✓ Сохранено' : dirty ? '● Есть несохранённые изменения' : 'Всё сохранено'}
        </span>
        <button onClick={save} disabled={!dirty}
          className={`min-h-[46px] px-6 rounded-btn font-semibold text-white transition active:scale-[0.99] ${dirty ? 'bg-teal' : 'bg-[#CFE0DA]'}`}>
          Сохранить график
        </button>
      </div>

      {editing && (
        <ItemEditor it={editing}
          onChange={(patch) => update(editing.id, patch)}
          onDelete={() => removeItem(editing.id)}
          onClose={() => setEditId(null)} />
      )}
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  ЭКРАН — ЭТАПЫ РАЗВИТИЯ (рекомендации по возрасту)                   */
/* ------------------------------------------------------------------ */

const ROADMAP = [
  { id: 'w1', label: '1-я неделя', sub: '0–7 дней', fromDay: 0, toDay: 7,
    sleep: '16–18 ч/сут, сон по 1–3 часа, день и ночь почти не различаются.',
    feeding: 'Смесь 30–60 мл × 8–10 раз; ГВ — по требованию, 8–12 раз. 6+ мокрых подгузников.',
    tummy: 'Пока рано. Больше контакта «кожа к коже» на груди у мамы.',
    senses: 'Видит на 20–30 см — лицо мамы. Узнаёт голос. Говори и пой.',
    add: ['Обработка пупочка после купания', 'Первое купание после отпадения пуповины', 'Прогулки по самочувствию'] },
  { id: 'w2', label: '2-я неделя', sub: '8–14 дней', fromDay: 8, toDay: 14,
    sleep: '16–18 ч/сут. Может путать день и ночь — днём больше света и активности.',
    feeding: 'С 11 дня — объёмный метод: суточный объём ≈ 1/5 массы тела (для 3500 г ≈ 700 мл/сут, ~100 мл за раз). Вес возвращается к рождённому к 10–14 дню.',
    tummy: 'Короткие выкладывания на живот можно начинать пробовать понемногу.',
    senses: 'Чёрно-белые контрастные картинки на 20–30 см. Разговаривай, комментируй действия.',
    add: ['Витамин D 500 МЕ с 10–14 дня (по согласованию с педиатром)', 'Ежедневное умывание глаз и носика'] },
  { id: 'w3', label: '3–4 недели', sub: '15–30 дней', fromDay: 15, toDay: 30,
    sleep: '15–17 ч/сут, появляются более длинные ночные отрезки.',
    feeding: 'Смесь 80–90 мл × 7 раз (≈ 1/5 веса в сутки). ГВ — по требованию.',
    tummy: 'СТАРТ выкладывания: 1–2 мин, 3–4 раза в день, перед едой. Постепенно увеличивай.',
    senses: 'Следит за лицом, реагирует на погремушку. Контрастные картинки, мобиль.',
    add: ['Лёгкий массаж и поглаживания после купания', 'Гимнастика, воздушные ванны'] },
  { id: 'm2', label: '2-й месяц', sub: '31–60 дней', fromDay: 31, toDay: 60,
    sleep: '15–17 ч/сут. Ночной сон удлиняется (но без гарантий).',
    feeding: 'Смесь ≈ 120 мл × 6 раз.',
    tummy: '3–5 мин несколько раз в день. Учится удерживать голову лёжа на животе.',
    senses: 'Следит за предметом, появляется социальная улыбка и гуление. Яркие подвесные игрушки.',
    add: ['Подготовка к осмотру в 1 мес и прививкам в 2 мес', 'Ритуал укладывания, белый шум'] },
  { id: 'm3', label: '3-й месяц', sub: '61–90 дней', fromDay: 61, toDay: 90,
    sleep: '14–16 ч/сут, 3–4 дневных сна.',
    feeding: 'Смесь ≈ 150 мл × 5–6 раз.',
    tummy: 'До 10–15 мин, опора на предплечья, уверенно держит голову.',
    senses: 'Гулит «в диалоге», смеётся, рассматривает ручки. Музыка, потешки, зеркало.',
    add: ['Развивающий коврик', 'Пальчиковые игры и песенки'] },
  { id: 'm46', label: '4–6 месяцев', sub: '91–180 дней', fromDay: 91, toDay: 99999,
    sleep: '14–15 ч/сут, около 3 снов. Возможен регресс сна в 4 мес — это норма.',
    feeding: 'Смесь 180–210 мл × 5 раз. Грудь/смесь остаются основой.',
    tummy: 'Перевороты! Не оставляй одного на высоте. Тянется и хватает игрушки.',
    senses: 'Хватает и тащит в рот, изучает предметы, реагирует на имя.',
    add: ['Безопасные прорезыватели', 'К 6 мес — подготовка к прикорму по рекомендации педиатра'] },
];

// Детали этапа — 4 строки + чипы «добавить в режим»
function StageDetails({ band }) {
  const Row = ({ icon, label, text }) => (
    <div className="flex gap-2 py-1.5 border-b border-[#F6EDE8] last:border-0">
      <span className="text-base shrink-0">{icon}</span>
      <div className="text-[13px] leading-relaxed">
        <span className="text-inkSoft font-medium">{label}: </span><span className="text-ink">{text}</span>
      </div>
    </div>
  );
  return (
    <div>
      <Row icon="😴" label="Сон" text={band.sleep} />
      <Row icon="🍼" label="Кормление" text={band.feeding} />
      <Row icon="🫃" label="Животик" text={band.tummy} />
      <Row icon="👁️" label="Зрение и слух" text={band.senses} />
      <div className="pt-3">
        <p className="text-inkSoft text-[12px] font-medium mb-1.5">➕ Что добавить в режим:</p>
        <div className="flex flex-wrap gap-1.5">
          {band.add.map((a, i) => <span key={i} className="text-[12px] bg-milk text-ink rounded-full px-3 py-1.5">{a}</span>)}
        </div>
      </div>
    </div>
  );
}

// Сворачиваемая строка «другого» этапа
function StageRow({ band }) {
  const [open, setOpen] = useState(false);
  return (
    <div className="bg-white rounded-card shadow-card overflow-hidden">
      <button onClick={() => setOpen(o => !o)} className="w-full flex items-center gap-3 px-4 py-3 min-h-[52px] text-left active:bg-milk transition">
        <div className="flex-1">
          <p className="text-ink font-semibold">{band.label}</p>
          <p className="text-inkSoft text-[12px]">{band.sub}</p>
        </div>
        <span className="text-teal text-lg shrink-0">{open ? '−' : '+'}</span>
      </button>
      {open && <div className="px-4 pb-4 fade-screen"><StageDetails band={band} /></div>}
    </div>
  );
}

function RoadmapScreen({ profile, days }) {
  const current = pickByDay(ROADMAP, days);
  const [showPlan, setShowPlan] = useState(false);
  const others = ROADMAP.filter(b => b.id !== current.id);

  return (
    <div className="fade-screen px-5 pt-6 pb-4">
      <SectionTitle sub="Что важно для малыша сейчас и что будет дальше">Этапы развития</SectionTitle>

      {/* Текущий этап — крупно и сразу раскрыт */}
      <p className="text-teal text-[12px] font-semibold uppercase tracking-wide mb-2">Сейчас</p>
      <div className="bg-white rounded-card shadow-cardLg p-5 border-2 border-teal">
        <h3 className="text-xl text-ink mb-1">{current.label}</h3>
        <p className="text-inkSoft text-[12px] mb-3">{current.sub} · {profile.babyName}</p>
        <StageDetails band={current} />
      </div>

      {/* Другие этапы */}
      <p className="text-inkSoft text-[13px] font-medium mt-7 mb-2">Что было и что впереди — нажми этап:</p>
      <div className="space-y-2">
        {others.map(b => <StageRow key={b.id} band={b} />)}
      </div>

      {/* Персональный план от Стефана — отдельной кнопкой, не мешает */}
      <div className="mt-7">
        {!showPlan ? (
          <button onClick={() => setShowPlan(true)}
            className="w-full bg-white rounded-card shadow-card p-4 flex items-center gap-3 active:scale-[0.99] transition text-left">
            <span className="text-2xl">✨</span>
            <div className="flex-1">
              <p className="text-ink font-semibold">Персональный план недели</p>
              <p className="text-inkSoft text-[13px]">Стефан составит план под {profile.babyName}</p>
            </div>
            <span className="text-terra text-xl">→</span>
          </button>
        ) : (
          <div className="-mx-5 border-t border-[#F1E7E1]">
            <PlansScreen profile={profile} days={days} />
          </div>
        )}
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  НИЖНЯЯ НАВИГАЦИЯ                                                    */
/* ------------------------------------------------------------------ */

const NAV = [
  { id: 'today',   icon: '🏠',  label: 'Сегодня' },
  { id: 'routine', icon: '🗓️',  label: 'Режим' },
  { id: 'roadmap', icon: '🌱',  label: 'Этапы' },
  { id: 'care',    icon: '🍼',  label: 'Уход' },
  { id: 'growth',  icon: '📊',  label: 'Рост' },
  { id: 'nanny',   icon: '🩺',  label: 'Стефан' },
];

function BottomNav({ tab, setTab }) {
  return (
    <nav className="shrink-0 bg-white border-t border-[#F1E7E1] flex" style={{ paddingBottom: 'env(safe-area-inset-bottom)' }}>
      {NAV.map(n => (
        <button key={n.id} onClick={() => setTab(n.id)} aria-label={n.label} aria-current={tab===n.id}
          className="flex-1 min-h-[56px] flex flex-col items-center justify-center gap-0.5 transition">
          <span className={`text-xl transition ${tab===n.id ? 'scale-110' : 'opacity-50 grayscale'}`}>{n.icon}</span>
          <span className={`text-[10px] font-medium ${tab===n.id ? 'text-terraDk' : 'text-inkSoft'}`}>{n.label}</span>
        </button>
      ))}
    </nav>
  );
}

/* ------------------------------------------------------------------ */
/*  КОРНЕВОЙ КОМПОНЕНТ                                                  */
/* ------------------------------------------------------------------ */

function App() {
  const [profile, setProfile] = useState(() => loadLS(LS.profile, null));
  const [tab, setTab] = useState('today');
  const [settings, setSettings] = useState(false);

  useEffect(() => { if (profile) saveLS(LS.profile, profile); }, [profile]);

  if (!profile) {
    return (
      <div className="min-h-full bg-milk">
        <Onboarding onDone={() => setProfile(loadLS(LS.profile, null))} />
      </div>
    );
  }

  const days = daysBetween(profile.birthDate);

  const reset = () => {
    Object.values(LS).forEach(k => localStorage.removeItem(k));
    setProfile(null);
    setSettings(false);
    setTab('today');
  };

  const scrollable = tab !== 'nanny';

  return (
    <div className="flex flex-col mx-auto max-w-md bg-milk" style={{ height: '100%' }}>
      {/* Топ-бар с настройками (кроме чата, у него своя шапка) */}
      {tab !== 'nanny' && (
        <div className="shrink-0 flex justify-end px-4 pt-3">
          <button onClick={() => setSettings(true)} aria-label="Настройки" className="text-xl text-inkSoft min-h-[44px] w-11">⚙️</button>
        </div>
      )}

      <main className={`flex-1 ${scrollable ? 'overflow-y-auto' : 'overflow-hidden'}`}>
        {tab === 'today' && <><AlertBanner profile={profile} days={days} /><TodayScreen profile={profile} days={days} goTo={setTab} /></>}
        {tab === 'routine' && <RoutineScreen profile={profile} days={days} />}
        {tab === 'roadmap' && <RoadmapScreen profile={profile} days={days} />}
        {tab === 'care' && <CareScreen profile={profile} />}
        {tab === 'growth' && <GrowthScreen profile={profile} days={days} setProfile={setProfile} />}
        {tab === 'nanny' && <NannyScreen profile={profile} days={days} />}

        {tab !== 'nanny' && (
          <footer className="px-5 py-6 text-center">
            <p className="text-[11px] text-inkSoft">
              🤍 «Стефан» — помощник для мамы, а не замена врачу.<br/>
              При любых тревожных симптомах обращайся к педиатру.
            </p>
          </footer>
        )}
      </main>

      <BottomNav tab={tab} setTab={setTab} />

      {settings && <SettingsModal onClose={() => setSettings(false)} profile={profile} onReset={reset} onSave={(patch) => setProfile(p => ({ ...p, ...patch }))} />}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
