const { useState, useEffect, useRef } = React;

const YELLOW = "#F5C518";
const ORANGE = "#F97316";
const VIOLET = "#7C3AED";
const PINK = "#E87CB0";
const ICE = "#8FCBE8";
const PLAIN = "#FFFFFF";
const BLACK = "#000000";
const RED = "#EF4444";

const ACT = {
  sport: { color: "#F5C518", emoji: "🏋️" },
  group: { color: "#F97316", emoji: "👥" },
  lesson: { color: "#E87CB0", emoji: "🎤" },
  speaking: { color: "#25A244", emoji: "💬" },
  english: { color: "#7C3AED", emoji: "📘" },
  cycle: { color: "#DC2626", emoji: "🚴" },
  run: { color: "#8B5CF6", emoji: "👟" },
  birthday: { color: "#22C55E", emoji: "🎂" },
  rest: { color: "#3B82F6", emoji: "🌴" },
  volunteer: { color: "#1E4FD8", emoji: "🤝" },
  event: { color: "#B91C1C", emoji: "🛡️" },
};

const TRAINER_TYPES = ["sport", "group", "cycle", "run"];
const VOLUNTEER_TYPE = "volunteer";
const GREEN_DICT = "#25A244";
const VOCAL_TYPES = ["lesson"];
const ENGLISH_TYPES = ["english", "speaking"];

const SESSION_PRESETS = ["Спліт Expert — Боклан Богдан"];
const CYCLE_PRESETS = ["Dance Cycle - Виноград Дарина"];
const CYCLE_LOCATION = "Спортивний зал Riots, Ірпінь";
const LESSON_PRESETS = ["Заняття з вокалу 30 хвилин (Ярослава Куліченко)"];
const SPEAKING_PRESETS = ["Урок SPEAKING (Мамчур Анастасія)"];
const ENGLISH_PRESETS = ["Урок Англійської мови (Мамчур Анастасія)"];

const GROUP_LOCATIONS = [
  "Спортивний зал Reforma Hub, Ірпінь",
  "Спортивний зал Riots, Ірпінь",
];

const THEMES = {
  dark: {
    "--bg": "#000000",
    "--surface": "#0d0d0d",
    "--input": "#0d0d0d",
    "--line": "#242424",
    "--fg": "#ffffff",
    "--on-surface": "#ffffff",
    "--muted": "#7a7a7a",
  },
  rose: {
    "--bg": "#FFFFFF",
    "--surface": "#F9E3EC",
    "--input": "#FFFFFF",
    "--line": "#E3E3E6",
    "--fg": "#2E2229",
    "--on-surface": "#2E2229",
    "--muted": "#8A8A8E",
  },
  green: {
    "--bg": "#FFFFFF",
    "--surface": "#EAF6EC",
    "--input": "#FFFFFF",
    "--line": "#D8ECDC",
    "--fg": "#16351F",
    "--on-surface": "#16351F",
    "--muted": "#7E9285",
  },
  light: {
    "--bg": "#ffffff",
    "--surface": "#f4f4f4",
    "--input": "#f4f4f4",
    "--line": "#e2e2e2",
    "--fg": "#000000",
    "--on-surface": "#000000",
    "--muted": "#767676",
  },
};

// Registerable roles. "admin" is intentionally not self-registerable from the UI;
// it is seeded directly in the database (see migrations/) and requires an invite code
// if ever registered through the API.
const REGISTERABLE_ROLES = ["trainer", "englishTeacher", "vocalTeacher"];

const RIGHTS = {
  trainer: { add: false, cancel: false, remove: false, edit: true },
  englishTeacher: { add: true, cancel: true, remove: false, edit: true },
  vocalTeacher: { add: true, cancel: true, remove: false, edit: true },
  admin: { add: true, cancel: true, remove: true, edit: true },
};

const RANGE = { start: { y: 2026, m: 7 }, end: { y: 2027, m: 11 } };

const L = {
  uk: {
    subtitle: "Вхід у кабінет",
    connectTitle: "Підключення",
    connectText: "Щоб бачити спільний розклад, дозвольте доступ до спільних даних.",
    connectBtn: "Підключити",
    connectWait: "Підключення…",
    password: "Пароль",
    newPassword: "Змінити пароль",
    passwordPh: "Пароль ще не встановлено",
    passwordHint: "Тут видно поточний пароль користувача — торкнись іконки ока, щоб показати або приховати",
    setPassword: "Зберегти зміни",
    passwordSaved: "Пароль оновлено — з ним можна входити",
    passwordLocalOnly: "Не вдалося змінити пароль на сервері. Вхід досі за старим паролем.",
    passwordNoAccount: "Спочатку користувач має зареєструватися — тоді пароль можна змінити.",
    passwordError: "Не вдалося оновити пароль",
    login: "Увійти",
    error: "Неправильний email або пароль",
    haveAccount: "Вже є акаунт? Увійти",
    noAccount: "Немає акаунту? Зареєструватися",
    register: "Зареєструватися",
    emailField: "Пошта",
    role: "Роль",
    roleTrainer: "Тренер",
    roleEnglishTeacher: "Вчитель англійської",
    roleVocalTeacher: "Вчитель вокалу",
    regFirstName: "Ім'я",
    regLastName: "Прізвище",
    regSuccess: "Реєстрація успішна, увійдіть",
    roleTaken: "Ця роль вже зареєстрована. Увійдіть у свій акаунт.",
    fillAll: "Заповніть усі поля",
    serverError: "Помилка сервера, спробуйте пізніше",
    loading: "Зачекайте…",
    acts1: "Акти за наступний місяць виставляються 25-го числа.",
    acts2: "Оплата — до 28-го числа поточного місяця.",
    schedule: "Розклад",
    all: "Загальний",
    everyone: "Усі",
    dict: "Словник",
    dictEmpty: "Слів поки немає",
    addWords: "Додати слова",
    oneWord: "Одне слово",
    manyWords: "Кілька слів",
    wordLabel: "Слово",
    translationLabel: "Переклад",
    addAll: "Додати всі",
    lessonLabel: "Урок",
    noLesson: "Без уроку",
    pastLessons: "З минулих уроків",
    activeLessons: "Актуальні уроки",
    allWords: "Усі слова",
    wordsCount: "слів",
    addedOn: "Додано",
    viewOnlyDict: "Перегляд",
    addRow: "Ще рядок",
    searchWord: "Пошук: англійське слово або переклад",
    nothingFound: "Нічого не знайдено",
    sendRequest: "Подати запит",
    rejected: "Відхилено вчителем",
    gotIt: "Зрозуміло",
    rejectedHint: "Ці слова вчитель не прийняв",
    requests: "Запити від адміністратора",
    approve: "Підтвердити",
    reject: "Відхилити",
    pendingSent: "Запит надіслано вчителю",
    addedBy: "Додав",
    roleAdmin: "Адміністратор",
    roleTeacher: "Вчитель англійської",
    infoTitle: "Про слово",
    events: "Події",
    accounts: "Акаунти",
    search: "Пошук за імʼям або прізвищем",
    notFound: "Нічого не знайдено",
    noName: "Без імені",
    account: "Акаунт",
    myProfile: "Мій профіль",
    pay: "Оплата",
    paySoon: "Розділ оплат у розробці",
    balance: "Баланс",
    rateLesson: "Ставка за урок",
    rateClass: "Ставка за заняття",
    editRate: "Змінити ставку",
    at: "о",
    byWhom: "ким",
    admin2: "Адмін",
    held: "Проведено",
    upcoming: "Заплановано",
    cancelledN: "Скасовано",
    history: "Історія",
    accrued: "Нараховано",
    adjust: "Коригування",
    addAdjust: "Додати коригування",
    amount: "Сума",
    note: "Коментар",
    notePh: "напр. Аванс",
    cancelledBy: "скасував",
    waiting: "очікує проведення",
    noPay: "Операцій поки немає",
    playlist: "Плейліст",
    addTrack: "Додати пісню",
    newTrack: "Нова пісня",
    trackTitle: "Назва пісні",
    trackArtist: "Виконавець",
    trackLink: "Посилання на пісню",
    trackCover: "Обкладинка",
    searchGoogle: "Знайти в Google",
    noTracks: "Пісень поки немає",
    open: "Відкрити",
    inWork: "У роботі",
    doneTab: "Виконано",
    markDone: "Виконано",
    markBack: "Повернути в роботу",
    forEvent: "Захід",
    forEventPh: "напр. Звітний концерт",
    noDone: "Поки нічого не вивчено",
    thisMonth: "Активностей цього місяця",
    lessonsMonth: "Занять цього місяця",
    noEvents: "Подій поки немає",
    eventsHint: "Події додає адміністратор",
    firstName: "Ім я",
    lastName: "Прізвище",
    phone: "Номер телефону",
    phoneHint: "10 цифр після +38",
    email: "Пошта (Gmail)",
    birth: "Дата народження",
    photo: "Змінити фото",
    photoZoom: "Масштаб",
    photoRemove: "Видалити фото",
    photoReplace: "Інше фото",
    photoSave: "Зберегти фото",
    photoSaved: "Фото збережено",
    pinchHint: "Стисни, щоб змінити масштаб, або потягни пальцем, щоб посунути фото",
    save: "Зберегти",
    saved: "Збережено",
    locked: "Дані заповнено. Змінити може лише адміністратор.",
    card: "Номер картки",
    cardHint: "16 цифр",
    paySystem: "Платіжна система",
    bank: "Банк",
    platform: "Платформа занять",
    addEvent: "Додати подію",
    eventTitle: "Назва події",
    eventDate: "Дата",
    add: "Додати",
    del: "Видалити",
    edit: "Редагувати",
    saveEdit: "Зберегти зміни",
    resetDate: "Скинути дату",
    cancelEdit: "Скасувати редагування",
    cancelIt: "Скасувати",
    restore: "Повернути",
    cancelled: "На жаль, запис скасовано",
    lock: "Заблокувати",
    unlock: "Розблокувати",
    wipe: "Видалити профіль",
    confirmWipe: "Точно видалити всі дані профілю?",
    everyoneTarget: "Всім",
    adminBadge: "Адмін",
    adminName: "Імʼя",
    adminProfile: "Адміністратор",
    type: "Тип",
    sport: "Сесія",
    group: "Групове заняття",
    cycle: "Dance Cycle",
    cycleLabel: "Сайклінг",
    lesson: "Заняття",
    speaking: "SPEAKING",
    english: "Англійська",
    run: "Біг",
    birthday: "День народження",
    hb: "HB",
    rest: "Відпочинок",
    volunteer: "Волонтерство",
    volunteerPh: "напр. Центр, вул. Соборна 1",
    titleTrainer: "Назва / тренер",
    titlePh: "напр. Спліт Expert — Боклан Богдан",
    titleTeacher: "Назва / учень",
    lessonPh: "напр. Заняття з вокалу 30 хвилин",
    choosePreset: "Обрати зі списку",
    manual: "Ввести вручну",
    groupName: "Назва групового заняття",
    groupPh: "напр. Кросфіт-група",
    labelSub: "Підпис",
    date: "Дата",
    from: "З",
    to: "До",
    place: "Локація",
    placePh: "напр. Парк Перемоги",
    km: "Кілометри",
    kmPh: "10",
    dateFrom: "Дата з",
    dateTo: "Дата до",
    allDay: "Цілий день",
    addToSchedule: "Додати в графік",
    planned: "Заплановане",
    plannedHint: "тапни, щоб змінити",
    viewOnly: "Тільки перегляд",
    birthAuto: "З профілю",
    eventName: "Назва заходу",
    uploadPhoto: "Завантажити фото",
    noPhoto: "Фото не обрано",
    useDefault: "Стандартне фото Spartan",
    addSpartan: "Додати захід",
    createEvent: "Створити подію",
    newEvent: "Нова подія",
    close: "Закрити",
    forWhom: "Кому",
    forAll: "Всім",
    created: "Створені події",
    dayFree: "Відпочинок. Подій не заплановано.",
    days: ["ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ", "НД"],
    daysFull: ["Понеділок", "Вівторок", "Середа", "Четвер", "Пʼятниця", "Субота", "Неділя"],
    months: ["Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"],
    monthsGen: ["січня", "лютого", "березня", "квітня", "травня", "червня", "липня", "серпня", "вересня", "жовтня", "листопада", "грудня"],
    names: { trainer: "Тренер", englishTeacher: "Вчитель англійської", vocalTeacher: "Вчитель вокалу", admin: "Адмін" },
  },
  en: {
    subtitle: "Cabinet login",
    connectTitle: "Connection",
    connectText: "To see the shared schedule, allow access to shared data.",
    connectBtn: "Connect",
    connectWait: "Connecting…",
    password: "Password",
    newPassword: "Change password",
    passwordPh: "No password set yet",
    passwordHint: "Shows the user's current password — tap the eye icon to reveal or hide it",
    setPassword: "Save changes",
    passwordSaved: "Password updated — it works for login",
    passwordLocalOnly: "Could not change the password on the server. The old one still works for login.",
    passwordNoAccount: "The user must register first — then the password can be changed.",
    passwordError: "Failed to update password",
    login: "Log in",
    error: "Wrong email or password",
    haveAccount: "Already have an account? Log in",
    noAccount: "No account? Register",
    register: "Register",
    emailField: "Email",
    role: "Role",
    roleTrainer: "Trainer",
    roleEnglishTeacher: "English teacher",
    roleVocalTeacher: "Vocal teacher",
    regFirstName: "First name",
    regLastName: "Last name",
    regSuccess: "Registration successful, please log in",
    roleTaken: "This role is already registered. Please log in.",
    fillAll: "Fill in all fields",
    serverError: "Server error, try again later",
    loading: "Please wait…",
    acts1: "Acts for the next month are issued on the 25th.",
    acts2: "Payment — by the 28th of the current month.",
    schedule: "Schedule",
    all: "Shared",
    everyone: "All",
    dict: "Dictionary",
    dictEmpty: "No words yet",
    addWords: "Add words",
    oneWord: "One word",
    manyWords: "Several words",
    wordLabel: "Word",
    translationLabel: "Translation",
    addAll: "Add all",
    lessonLabel: "Lesson",
    noLesson: "No lesson",
    pastLessons: "Past lessons",
    activeLessons: "Upcoming lessons",
    allWords: "All words",
    wordsCount: "words",
    addedOn: "Added",
    viewOnlyDict: "View only",
    addRow: "One more row",
    searchWord: "Search: English word or translation",
    nothingFound: "Nothing found",
    sendRequest: "Send request",
    rejected: "Rejected by the teacher",
    gotIt: "Got it",
    rejectedHint: "The teacher did not accept these words",
    requests: "Requests from administrator",
    approve: "Approve",
    reject: "Reject",
    pendingSent: "Request sent to the teacher",
    addedBy: "Added by",
    roleAdmin: "Administrator",
    roleTeacher: "English teacher",
    infoTitle: "About the word",
    events: "Events",
    accounts: "Accounts",
    search: "Search by first or last name",
    notFound: "Nothing found",
    noName: "No name",
    account: "Account",
    myProfile: "My profile",
    pay: "Payments",
    paySoon: "Payments section in progress",
    balance: "Balance",
    rateLesson: "Rate per lesson",
    rateClass: "Rate per class",
    editRate: "Change rate",
    at: "at",
    byWhom: "by",
    admin2: "Admin",
    held: "Held",
    upcoming: "Scheduled",
    cancelledN: "Cancelled",
    history: "History",
    accrued: "Accrued",
    adjust: "Adjustment",
    addAdjust: "Add adjustment",
    amount: "Amount",
    note: "Note",
    notePh: "e.g. Advance",
    cancelledBy: "cancelled by",
    waiting: "pending",
    noPay: "No operations yet",
    playlist: "Playlist",
    addTrack: "Add song",
    newTrack: "New song",
    trackTitle: "Song title",
    trackArtist: "Artist",
    trackLink: "Song link",
    trackCover: "Cover",
    searchGoogle: "Search on Google",
    noTracks: "No songs yet",
    open: "Open",
    inWork: "In progress",
    doneTab: "Done",
    markDone: "Done",
    markBack: "Back to work",
    forEvent: "Event",
    forEventPh: "e.g. Final concert",
    noDone: "Nothing learned yet",
    thisMonth: "Activities this month",
    lessonsMonth: "Lessons this month",
    noEvents: "No events yet",
    eventsHint: "Events are added by the administrator",
    firstName: "First name",
    lastName: "Last name",
    phone: "Phone number",
    phoneHint: "10 digits after +38",
    email: "Email (Gmail)",
    birth: "Date of birth",
    photo: "Change photo",
    photoZoom: "Zoom",
    photoRemove: "Remove photo",
    photoReplace: "Replace photo",
    photoSave: "Save photo",
    photoSaved: "Photo saved",
    pinchHint: "Pinch to zoom, or drag with your finger to move the photo",
    save: "Save",
    saved: "Saved",
    locked: "Profile filled. Only the administrator can edit it.",
    card: "Card number",
    cardHint: "16 digits",
    paySystem: "Payment system",
    bank: "Bank",
    platform: "Lesson platform",
    addEvent: "Add event",
    eventTitle: "Event title",
    eventDate: "Date",
    add: "Add",
    del: "Delete",
    edit: "Edit",
    saveEdit: "Save changes",
    resetDate: "Reset date",
    cancelEdit: "Cancel editing",
    cancelIt: "Cancel",
    restore: "Restore",
    cancelled: "Unfortunately, this entry was cancelled",
    lock: "Lock",
    unlock: "Unlock",
    wipe: "Delete profile",
    confirmWipe: "Delete all profile data?",
    everyoneTarget: "Everyone",
    adminBadge: "Admin",
    adminName: "Name",
    adminProfile: "Administrator",
    type: "Type",
    sport: "Session",
    group: "Group class",
    cycle: "Dance Cycle",
    cycleLabel: "Cycling",
    lesson: "Lesson",
    speaking: "SPEAKING",
    english: "English",
    run: "Running",
    birthday: "Birthday",
    hb: "HB",
    rest: "Rest",
    volunteer: "Volunteering",
    volunteerPh: "e.g. Center, Soborna st. 1",
    titleTrainer: "Title / trainer",
    titlePh: "e.g. Split Expert — Boklan Bohdan",
    titleTeacher: "Title / student",
    lessonPh: "e.g. Vocal lesson 30 min",
    choosePreset: "Choose from list",
    manual: "Enter manually",
    groupName: "Group class name",
    groupPh: "e.g. Crossfit group",
    labelSub: "Label",
    date: "Date",
    from: "From",
    to: "To",
    place: "Location",
    placePh: "e.g. Victory Park",
    km: "Kilometers",
    kmPh: "10",
    dateFrom: "Date from",
    dateTo: "Date to",
    allDay: "All day",
    addToSchedule: "Add to schedule",
    planned: "Planned",
    plannedHint: "tap to change",
    viewOnly: "View only",
    birthAuto: "From profile",
    eventName: "Event name",
    uploadPhoto: "Upload photo",
    noPhoto: "No photo selected",
    useDefault: "Default Spartan photo",
    addSpartan: "Add event",
    createEvent: "Create event",
    newEvent: "New event",
    close: "Close",
    forWhom: "For whom",
    forAll: "Everyone",
    created: "Created events",
    dayFree: "Rest day. Nothing scheduled.",
    days: ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"],
    daysFull: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
    months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    monthsGen: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    names: { trainer: "Trainer", englishTeacher: "English teacher", vocalTeacher: "Vocal teacher", admin: "Admin" },
  },
  ru: {
    subtitle: "Вход в кабинет",
    connectTitle: "Подключение",
    connectText: "Чтобы видеть общее расписание, разрешите доступ к общим данным.",
    connectBtn: "Подключить",
    connectWait: "Подключение…",
    password: "Пароль",
    newPassword: "Изменить пароль",
    passwordPh: "Пароль ещё не задан",
    passwordHint: "Здесь виден текущий пароль пользователя — нажми на иконку глаза, чтобы показать или скрыть",
    setPassword: "Сохранить изменения",
    passwordSaved: "Пароль обновлён — с ним можно входить",
    passwordLocalOnly: "Не удалось изменить пароль на сервере. Вход всё ещё по старому паролю.",
    passwordNoAccount: "Сначала пользователь должен зарегистрироваться — тогда пароль можно изменить.",
    passwordError: "Не удалось обновить пароль",
    login: "Войти",
    error: "Неверный email или пароль",
    haveAccount: "Уже есть аккаунт? Войти",
    noAccount: "Нет аккаунта? Зарегистрироваться",
    register: "Зарегистрироваться",
    emailField: "Почта",
    role: "Роль",
    roleTrainer: "Тренер",
    roleEnglishTeacher: "Учитель английского",
    roleVocalTeacher: "Учитель вокала",
    regFirstName: "Имя",
    regLastName: "Фамилия",
    regSuccess: "Регистрация успешна, войдите",
    roleTaken: "Эта роль уже зарегистрирована. Войдите в свой аккаунт.",
    fillAll: "Заполните все поля",
    serverError: "Ошибка сервера, попробуйте позже",
    loading: "Подождите…",
    acts1: "Акты за следующий месяц выставляются 25-го числа.",
    acts2: "Оплата — до 28-го числа текущего месяца.",
    schedule: "Расписание",
    all: "Общий",
    everyone: "Все",
    dict: "Словарь",
    dictEmpty: "Слов пока нет",
    addWords: "Добавить слова",
    oneWord: "Одно слово",
    manyWords: "Несколько слов",
    wordLabel: "Слово",
    translationLabel: "Перевод",
    addAll: "Добавить все",
    lessonLabel: "Урок",
    noLesson: "Без урока",
    pastLessons: "Из прошлых уроков",
    activeLessons: "Актуальные уроки",
    allWords: "Все слова",
    wordsCount: "слов",
    addedOn: "Добавлено",
    viewOnlyDict: "Просмотр",
    addRow: "Ещё строка",
    searchWord: "Поиск: английское слово или перевод",
    nothingFound: "Ничего не найдено",
    sendRequest: "Подать запрос",
    rejected: "Отклонено учителем",
    gotIt: "Понятно",
    rejectedHint: "Эти слова учитель не принял",
    requests: "Запросы от администратора",
    approve: "Подтвердить",
    reject: "Отклонить",
    pendingSent: "Запрос отправлен учителю",
    addedBy: "Добавил",
    roleAdmin: "Администратор",
    roleTeacher: "Учитель английского",
    infoTitle: "О слове",
    events: "События",
    accounts: "Аккаунты",
    search: "Поиск по имени или фамилии",
    notFound: "Ничего не найдено",
    noName: "Без имени",
    account: "Аккаунт",
    myProfile: "Мой профиль",
    pay: "Оплата",
    paySoon: "Раздел оплат в разработке",
    balance: "Баланс",
    rateLesson: "Ставка за урок",
    rateClass: "Ставка за занятие",
    editRate: "Изменить ставку",
    at: "в",
    byWhom: "кем",
    admin2: "Админ",
    held: "Проведено",
    upcoming: "Запланировано",
    cancelledN: "Отменено",
    history: "История",
    accrued: "Начислено",
    adjust: "Корректировка",
    addAdjust: "Добавить корректировку",
    amount: "Сумма",
    note: "Комментарий",
    notePh: "напр. Аванс",
    cancelledBy: "отменил",
    waiting: "ожидает проведения",
    noPay: "Операций пока нет",
    playlist: "Плейлист",
    addTrack: "Добавить песню",
    newTrack: "Новая песня",
    trackTitle: "Название песни",
    trackArtist: "Исполнитель",
    trackLink: "Ссылка на песню",
    trackCover: "Обложка",
    searchGoogle: "Найти в Google",
    noTracks: "Песен пока нет",
    open: "Открыть",
    inWork: "В работе",
    doneTab: "Выполнено",
    markDone: "Выполнено",
    markBack: "Вернуть в работу",
    forEvent: "Мероприятие",
    forEventPh: "напр. Отчётный концерт",
    noDone: "Пока ничего не выучено",
    thisMonth: "Активностей в этом месяце",
    lessonsMonth: "Занятий в этом месяце",
    noEvents: "Событий пока нет",
    eventsHint: "События добавляет администратор",
    firstName: "Имя",
    lastName: "Фамилия",
    phone: "Номер телефона",
    phoneHint: "10 цифр после +38",
    email: "Почта (Gmail)",
    birth: "Дата рождения",
    photo: "Изменить фото",
    photoZoom: "Масштаб",
    photoRemove: "Удалить фото",
    photoReplace: "Другое фото",
    photoSave: "Сохранить фото",
    photoSaved: "Фото сохранено",
    pinchHint: "Сожми, чтобы изменить масштаб, или потяни пальцем, чтобы сдвинуть фото",
    save: "Сохранить",
    saved: "Сохранено",
    locked: "Данные заполнены. Изменить может только администратор.",
    card: "Номер карты",
    cardHint: "16 цифр",
    paySystem: "Платёжная система",
    bank: "Банк",
    platform: "Платформа занятий",
    addEvent: "Добавить событие",
    eventTitle: "Название события",
    eventDate: "Дата",
    add: "Добавить",
    del: "Удалить",
    edit: "Редактировать",
    saveEdit: "Сохранить изменения",
    resetDate: "Сбросить дату",
    cancelEdit: "Отменить редактирование",
    cancelIt: "Отменить",
    restore: "Вернуть",
    cancelled: "К сожалению, запись отменена",
    lock: "Заблокировать",
    unlock: "Разблокировать",
    wipe: "Удалить профиль",
    confirmWipe: "Точно удалить все данные профиля?",
    everyoneTarget: "Всем",
    adminBadge: "Админ",
    adminName: "Имя",
    adminProfile: "Администратор",
    type: "Тип",
    sport: "Сессия",
    group: "Групповое занятие",
    cycle: "Dance Cycle",
    cycleLabel: "Сайклинг",
    lesson: "Занятие",
    speaking: "SPEAKING",
    english: "Английский",
    run: "Бег",
    birthday: "День рождения",
    hb: "HB",
    rest: "Отдых",
    volunteer: "Волонтёрство",
    volunteerPh: "напр. Центр, ул. Соборная 1",
    titleTrainer: "Название / тренер",
    titlePh: "напр. Сплит Expert — Боклан Богдан",
    titleTeacher: "Название / ученик",
    lessonPh: "напр. Занятие по вокалу 30 минут",
    choosePreset: "Выбрать из списка",
    manual: "Ввести вручную",
    groupName: "Название группового занятия",
    groupPh: "напр. Кроссфит-группа",
    labelSub: "Подпись",
    date: "Дата",
    from: "С",
    to: "До",
    place: "Локация",
    placePh: "напр. Парк Победы",
    km: "Километры",
    kmPh: "10",
    dateFrom: "Дата с",
    dateTo: "Дата по",
    allDay: "Весь день",
    addToSchedule: "Добавить в график",
    planned: "Запланировано",
    plannedHint: "нажми, чтобы изменить",
    viewOnly: "Только просмотр",
    birthAuto: "Из профиля",
    eventName: "Название мероприятия",
    uploadPhoto: "Загрузить фото",
    noPhoto: "Фото не выбрано",
    useDefault: "Стандартное фото Spartan",
    addSpartan: "Добавить мероприятие",
    createEvent: "Создать событие",
    newEvent: "Новое событие",
    close: "Закрыть",
    forWhom: "Кому",
    forAll: "Всем",
    created: "Созданные события",
    dayFree: "Отдых. Событий не запланировано.",
    days: ["ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ", "ВС"],
    daysFull: ["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"],
    months: ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
    monthsGen: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
    names: { trainer: "Тренер", englishTeacher: "Учитель английского", vocalTeacher: "Учитель вокала", admin: "Админ" },
  },
};

const emptyProfile = {
  firstName: "",
  lastName: "",
  phone: "",
  email: "",
  birth: "",
  password: "",
  avatar: null,
  avatarZoom: 1,
  card: "",
  platform: "",
  paySystem: "",
  bank: "",
  locked: false,
};

/* ---------- icons ---------- */

function GlobeIcon({ color }) {
  return (
    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.6">
      <circle cx="12" cy="12" r="9" />
      <path d="M3 12h18M12 3c2.5 2.7 2.5 15.3 0 18M12 3c-2.5 2.7-2.5 15.3 0 18" />
    </svg>
  );
}

function ExitIcon({ color }) {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h3" />
      <path d="M15 8l4 4-4 4" />
      <path d="M19 12H9" />
    </svg>
  );
}

function CalendarIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <rect x="3" y="5" width="18" height="16" rx="2" />
      <path d="M8 3v4M12 3v4M16 3v4" />
      <path d="M7.5 12h1.5M11.2 12h1.6M15 12h1.5M7.5 16h1.5M11.2 16h1.6M15 16h1.5" />
    </svg>
  );
}

function GlobalCalendarIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <rect x="3" y="5" width="18" height="16" rx="2" />
      <path d="M8 3v4M16 3v4M3 10h18" />
      <circle cx="12" cy="15.5" r="3" />
    </svg>
  );
}

function EventIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <rect x="3" y="5" width="18" height="16" rx="2" />
      <path d="M8 3v4M12 3v4M16 3v4" />
      <path d="M12 10.5l1.3 2.7 3 .4-2.2 2.1.5 2.9-2.6-1.4-2.6 1.4.5-2.9-2.2-2.1 3-.4z" />
    </svg>
  );
}

function ProfileIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="12" cy="8" r="3.6" />
      <path d="M5 20c0-3.6 3.1-6 7-6s7 2.4 7 6" />
    </svg>
  );
}

function UsersIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="9" cy="8" r="3.2" />
      <path d="M2.5 20c0-3.4 2.9-5.6 6.5-5.6s6.5 2.2 6.5 5.6" />
      <path d="M16.5 5.4a3.2 3.2 0 0 1 0 6.1M18 14.8c2.1.6 3.5 2.3 3.5 4.6" />
    </svg>
  );
}

function CheckIcon({ color }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M4 12.5l5.5 5.5L20 7" />
    </svg>
  );
}

function HelpIcon({ color }) {
  return (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round">
      <circle cx="12" cy="12" r="9.5" />
      <path d="M9.4 9.2a2.7 2.7 0 0 1 5.2.9c0 1.8-2.6 2.2-2.6 3.9" />
      <path d="M12 17.4v.01" />
    </svg>
  );
}

function BookIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 6.5v13" />
      <path d="M12 6.5C10.4 5.2 7.8 4.6 3.5 4.5v13c4.3.1 6.9.7 8.5 2" />
      <path d="M12 6.5c1.6-1.3 4.2-1.9 8.5-2v13c-4.3.1-6.9.7-8.5 2" />
    </svg>
  );
}

function MusicIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 18V5l11-2v13" />
      <circle cx="6.5" cy="18" r="2.6" />
      <circle cx="17.5" cy="16" r="2.6" />
    </svg>
  );
}

function WalletIcon({ color }) {
  return (
    <svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 8.5A2.5 2.5 0 0 1 5.5 6H18a2 2 0 0 1 2 2v1" />
      <rect x="3" y="8.5" width="18" height="11.5" rx="2.5" />
      <path d="M21 12.5h-4a2 2 0 0 0 0 4h4" />
    </svg>
  );
}

function PinIcon({ color }) {
  return (
    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 21s7-5.6 7-11a7 7 0 1 0-14 0c0 5.4 7 11 7 11z" />
      <circle cx="12" cy="10" r="2.6" />
    </svg>
  );
}

function SearchIcon({ color }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round">
      <circle cx="11" cy="11" r="6.5" />
      <path d="M16 16l4.5 4.5" />
    </svg>
  );
}

function EditIcon({ color }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M4 20h4L19 9a2.5 2.5 0 0 0-3.5-3.5L4.5 16.5z" />
      <path d="M14.5 6.5L17.5 9.5" />
    </svg>
  );
}

function TrashIcon({ color }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M4 7h16M10 11v6M14 11v6" />
      <path d="M6 7l1 13h10l1-13M9 7V4h6v3" />
    </svg>
  );
}

function BanIcon({ color }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round">
      <circle cx="12" cy="12" r="9" />
      <path d="M5.6 5.6l12.8 12.8" />
    </svg>
  );
}

function UndoIcon({ color }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M4 10h10a5 5 0 0 1 0 10h-3" />
      <path d="M8 6L4 10l4 4" />
    </svg>
  );
}

function EyeIcon({ color }) {
  return (
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z" />
      <circle cx="12" cy="12" r="3" />
    </svg>
  );
}

function EyeOffIcon({ color }) {
  return (
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M2 12s3.6-7 10-7c2 0 3.7.6 5.1 1.4M22 12s-3.6 7-10 7c-2 0-3.7-.6-5.1-1.4" />
      <path d="M9.9 9.9a3 3 0 0 0 4.2 4.2" />
      <path d="M3 3l18 18" />
    </svg>
  );
}

function ZoomMark() {
  return (
    <svg width="30" height="30" viewBox="0 0 48 48">
      <rect width="48" height="48" rx="11" fill="#2D8CFF" />
      <path d="M11 18.5A2.5 2.5 0 0 1 13.5 16h11a2.5 2.5 0 0 1 2.5 2.5v11a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 11 29.5z" fill="#fff" />
      <path d="M29 21.5l7-4.2v13.4l-7-4.2z" fill="#fff" />
    </svg>
  );
}

function MeetMark() {
  return (
    <svg width="30" height="30" viewBox="0 0 48 48">
      <rect width="48" height="48" rx="11" fill="#fff" stroke="#E3E3E6" />
      <path d="M10 18.5A2.5 2.5 0 0 1 12.5 16H26v16H12.5A2.5 2.5 0 0 1 10 29.5z" fill="#00832D" />
      <path d="M26 16h5.5A2.5 2.5 0 0 1 34 18.5V24l-8 4z" fill="#FFBA00" />
      <path d="M26 24l8 4v1.5a2.5 2.5 0 0 1-2.5 2.5H26z" fill="#00AC47" />
      <path d="M34 21l5-3v12l-5-3z" fill="#2684FC" />
    </svg>
  );
}

function VisaMark() {
  return (
    <svg width="34" height="20" viewBox="0 0 48 28">
      <rect width="48" height="28" rx="4" fill="#1A1F71" />
      <text x="24" y="19" textAnchor="middle" fill="#fff" fontSize="12" fontWeight="700" fontStyle="italic" fontFamily="Helvetica, Arial">
        VISA
      </text>
    </svg>
  );
}

function MasterMark() {
  return (
    <svg width="34" height="20" viewBox="0 0 48 28">
      <rect width="48" height="28" rx="4" fill="#0A0A0A" />
      <circle cx="20" cy="14" r="8" fill="#EB001B" />
      <circle cx="28" cy="14" r="8" fill="#F79E1B" fillOpacity="0.9" />
    </svg>
  );
}

function PrivatMark() {
  return (
    <svg width="28" height="28" viewBox="0 0 100 100">
      <rect width="100" height="100" rx="10" fill="#7DB928" />
      <path d="M18 18h64v64H63V37H18z" fill="#fff" />
      <path d="M18 37c25 0 45 20 45 45H45c0-15-12-27-27-27z" fill="#7DB928" />
      <rect x="18" y="62" width="20" height="20" fill="#111" />
    </svg>
  );
}

function MonoMark() {
  return (
    <svg width="28" height="28" viewBox="0 0 100 100">
      <defs>
        <linearGradient id="monoBg" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0%" stopColor="#4A4E57" />
          <stop offset="100%" stopColor="#2A2D33" />
        </linearGradient>
      </defs>
      <rect width="100" height="100" rx="20" fill="url(#monoBg)" />
      <text
        x="50"
        y="60"
        textAnchor="middle"
        fill="#fff"
        fontSize="30"
        fontWeight="500"
        fontFamily="Helvetica Neue, Helvetica, Arial"
      >
        mono
      </text>
    </svg>
  );
}

/* ---------- hooks ---------- */

function useBrandFont() {
  useEffect(() => {
    if (typeof document === "undefined") return;
    if (document.getElementById("delvy-brand-font")) return;
    const link = document.createElement("link");
    link.id = "delvy-brand-font";
    link.rel = "stylesheet";
    link.href = "https://fonts.googleapis.com/css2?family=Anton&display=swap";
    document.head.appendChild(link);
  }, []);
}

function useSystemDark() {
  const [dark, setDark] = useState(false);
  useEffect(() => {
    if (typeof window === "undefined" || !window.matchMedia) return;
    const mq = window.matchMedia("(prefers-color-scheme: dark)");
    setDark(mq.matches);
    const onChange = (e) => setDark(e.matches);
    if (mq.addEventListener) mq.addEventListener("change", onChange);
    else mq.addListener(onChange);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener("change", onChange);
      else mq.removeListener(onChange);
    };
  }, []);
  return dark;
}

function useWide() {
  const [wide, setWide] = useState(false);
  useEffect(() => {
    if (typeof window === "undefined") return;
    const check = () => setWide(window.innerWidth >= 760);
    check();
    window.addEventListener("resize", check);
    window.addEventListener("orientationchange", check);
    return () => {
      window.removeEventListener("resize", check);
      window.removeEventListener("orientationchange", check);
    };
  }, []);
  return wide;
}

/* ---------- helpers ---------- */

function compressImage(file, maxSize, quality) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => {
      const img = new Image();
      img.onload = () => {
        try {
          let { width, height } = img;
          const scale = Math.min(1, maxSize / Math.max(width, height));
          width = Math.round(width * scale);
          height = Math.round(height * scale);

          const canvas = document.createElement("canvas");
          canvas.width = width;
          canvas.height = height;
          const ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0, width, height);
          resolve(canvas.toDataURL("image/jpeg", quality));
        } catch (err) {
          resolve(reader.result);
        }
      };
      img.onerror = () => resolve(reader.result);
      img.src = reader.result;
    };
    reader.readAsDataURL(file);
  });
}

function mapsUrl(place) {
  return "https://www.google.com/maps/search/?api=1&query=" + encodeURIComponent(place);
}

function isoOf(year, month, day) {
  return `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
}

function eachIso(fromStr, toStr) {
  if (!fromStr) return [];
  if (!toStr || toStr === fromStr) return [fromStr];
  const from = new Date(fromStr);
  const to = new Date(toStr);
  if (isNaN(from) || isNaN(to) || from > to) return [fromStr];
  const out = [];
  const cur = new Date(from);
  while (cur <= to) {
    out.push(isoOf(cur.getFullYear(), cur.getMonth(), cur.getDate()));
    cur.setDate(cur.getDate() + 1);
  }
  return out;
}

function monthIndex(y, m) {
  return y * 12 + m;
}

const RANGE_START = monthIndex(RANGE.start.y, RANGE.start.m);
const RANGE_END = monthIndex(RANGE.end.y, RANGE.end.m);

function clampMonthIndex(idx) {
  return Math.min(RANGE_END, Math.max(RANGE_START, idx));
}

function currentMonthIndex() {
  const now = new Date();
  return clampMonthIndex(monthIndex(now.getFullYear(), now.getMonth()));
}

function todayIsoString() {
  const now = new Date();
  return isoOf(now.getFullYear(), now.getMonth(), now.getDate());
}

function hexToRgba(hex, alpha) {
  const h = (hex || "").replace("#", "");
  const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
  const bigint = parseInt(full, 16);
  if (isNaN(bigint)) return hex;
  const r = (bigint >> 16) & 255;
  const g = (bigint >> 8) & 255;
  const b = bigint & 255;
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

function birthdayEntries(profiles, t) {
  const out = {};
  const now = new Date();
  const todayIso = isoOf(now.getFullYear(), now.getMonth(), now.getDate());

  const nextOccurrence = (birthStr) => {
    const d = new Date(birthStr);
    if (isNaN(d)) return null;
    const candidates = [RANGE.start.y, RANGE.end.y].map((year) => ({
      year,
      date: isoOf(year, d.getMonth(), d.getDate()),
    }));
    return candidates.find((c) => c.date >= todayIso) || candidates[candidates.length - 1];
  };

  Object.keys(profiles).forEach((uid) => {
    out[uid] = [];
    const b = profiles[uid].birth;
    if (b) {
      const next = nextOccurrence(b);
      if (next) {
        out[uid].push({
          id: `birth-${uid}-${next.year}`,
          type: "birthday",
          date: next.date,
          auto: true,
          label: t.birthday,
        });
      }
    }
  });
  return out;
}

// Чи минув запис. Для відпочинку враховується останній день.
function hasPassed(entry) {
  if (!entry || !entry.date) return false;
  const lastDay = entry.dateTo && entry.dateTo > entry.date ? entry.dateTo : entry.date;
  const end = entry.to || "23:59";
  const dt = new Date(`${lastDay}T${end}:00`);
  if (isNaN(dt)) return false;
  return dt.getTime() <= Date.now();
}

function dayInfo(list, iso) {
  const hits = (list || []).filter((e) => eachIso(e.date, e.dateTo).includes(iso));
  if (hits.length === 0) return null;
  const active = hits.find((e) => !e.cancelled);
  if (active) return { type: active.type, cancelled: false };
  return { type: hits[0].type, cancelled: true };
}

function formatCard(digits) {
  return (digits.match(/.{1,4}/g) || []).join(" ");
}

function detectPaySystem(digits) {
  if (!digits) return "";
  if (digits[0] === "4") return "visa";
  if (/^5[1-5]/.test(digits) || /^2[2-7]/.test(digits)) return "mastercard";
  return "";
}

/* ---------- sync ---------- */

const STORE_KEY = "delvy:state:v1";
const PING_KEY = "delvy:ping";
const SPARTAN_MARK = "spartan-default";

const RATES = { englishTeacher: 300, vocalTeacher: 0, trainer: 0 };
const PAY_TYPES = ["speaking", "english", "lesson"];

// ---------- real backend (Cloudflare Pages Functions + D1) ----------
// All requests go to same-origin /api/* routes (see functions/api/*.ts).
// Auth uses an httpOnly session cookie set by the server, so no token
// handling is needed here — `credentials: "include"` is enough.
const API_BASE = "/api";

async function api(path, options) {
  const opts = options || {};
  const res = await fetch(API_BASE + path, {
    method: opts.method || "GET",
    headers: { "Content-Type": "application/json" },
    credentials: "include",
    body: opts.body ? JSON.stringify(opts.body) : undefined,
  });
  let data = null;
  try {
    data = await res.json();
  } catch (e) {
    data = null;
  }
  if (!res.ok) {
    const err = new Error((data && data.error) || "request_failed");
    err.status = res.status;
    err.code = data && data.error;
    throw err;
  }
  return data;
}

function serializeState(profiles, adminProfile, entries, events, tracks, adjustments, rates, words) {
  const users = ["trainer", "englishTeacher", "vocalTeacher"];
  const p = {};
  const en = {};
  const adj = {};
  users.forEach((u) => {
    p[u] = profiles[u] || {};
    en[u] = entries[u] || [];
    adj[u] = (adjustments || {})[u] || [];
  });
  return JSON.stringify({
    profiles: p,
    adminProfile: adminProfile || {},
    entries: en,
    events: events || [],
    tracks: tracks || [],
    adjustments: adj,
    rates: rates || {},
    words: words || [],
  });
}

async function writeState(payload) {
  try {
    const res = await api("/state", { method: "PUT", body: payload });
    if (res && res.rejected) return false;
    return true;
  } catch (err) {
    return false;
  }
}

async function readState() {
  try {
    const pack = await api("/state");
    if (!pack) return null;

    // Порожня база — це нормальна відповідь, а не помилка. Раніше вона
    // поверталася як null, застосунок вважав сервер недоступним і назавжди
    // блокував збереження: нове нічого не записувалося.
    return { updatedAt: pack.updatedAt || 0, data: pack.data || {} };
  } catch (err) {
    // Справжня помилка: немає мережі, сесія протермінувалась тощо.
    return null;
  }
}

// скільки «корисних» записів у стані — захист від затирання порожнім
function weightOf(raw) {
  try {
    const d = typeof raw === "string" ? JSON.parse(raw) : raw;
    let n = 0;
    Object.values(d.entries || {}).forEach((arr) => {
      n += (arr || []).length;
    });
    n += (d.events || []).length;
    n += (d.tracks || []).length;
    Object.values(d.adjustments || {}).forEach((arr) => {
      n += (arr || []).length;
    });
    Object.values(d.profiles || {}).forEach((pr) => {
      if (pr && (pr.firstName || pr.lastName || pr.email || pr.phone)) n += 1;
    });
    if (d.adminProfile && (d.adminProfile.name || d.adminProfile.avatar)) n += 1;
    return n;
  } catch (err) {
    return 0;
  }
}

function useSharedState(profiles, adminProfile, entries, events, tracks, adjustments, rates, words, apply, enabled) {
  const [ready, setReady] = useState(false);

  const version = useRef(0);
  const snapshot = useRef("");
  const loaded = useRef(false);   // сервер прочитано хоча б раз
  const busy = useRef(false);
  const applyRef = useRef(apply);
  applyRef.current = apply;

  const current = serializeState(profiles, adminProfile, entries, events, tracks, adjustments, rates, words);

  const applyRemote = (pack) => {
    if (!pack || !pack.data) return;
    const body = serializeState(
      pack.data.profiles || {},
      pack.data.adminProfile,
      pack.data.entries || {},
      pack.data.events,
      pack.data.tracks,
      pack.data.adjustments,
      pack.data.rates,
      pack.data.words
    );
    version.current = Math.max(version.current, pack.updatedAt || 0);
    if (body === snapshot.current) return;
    snapshot.current = body;
    applyRef.current(pack.data);
  };

  // початкове завантаження: доки не прочитали сервер — НЕ зберігаємо нічого
  useEffect(() => {
    if (!enabled) return;
    let alive = true;
    let attempt = 0;

    const load = async () => {
      const pack = await readState();
      if (!alive) return;

      if (pack) {
        applyRemote(pack);
        loaded.current = true;
        setReady(true);
        return;
      }

      // Сервер не відповів — пробуємо ще, з наростаючою паузою.
      // Поки не прочитали, нічого не пишемо, щоб не затерти чужі дані.
      attempt += 1;
      setTimeout(load, Math.min(1500 * attempt, 15000));
    };

    load();

    return () => {
      alive = false;
    };
  }, [enabled]);

  // збереження
  useEffect(() => {
    if (!enabled || !ready) return;
    if (!loaded.current) return;              // без успішного читання не пишемо
    if (current === snapshot.current) return;

    // захист: не даємо порожньому стану стерти наповнений
    const before = weightOf(snapshot.current || "{}");
    const after = weightOf(current);
    if (before > 0 && after === 0) return;

    let cancelled = false;

    const save = async (attempt) => {
      if (cancelled || busy.current) return;
      busy.current = true;
      const stamp = Date.now();
      const ok = await writeState({ updatedAt: stamp, data: JSON.parse(current) });
      busy.current = false;

      if (ok) {
        snapshot.current = current;
        version.current = stamp;
      } else if (!cancelled && attempt < 6) {
        setTimeout(() => save(attempt + 1), 2000 * (attempt + 1));
      }
    };

    const timer = setTimeout(() => save(0), 700);

    return () => {
      cancelled = true;
      clearTimeout(timer);
    };
  }, [current, ready, enabled]);

  // підтягування
  useEffect(() => {
    if (!enabled || !ready) return;
    let alive = true;

    const pull = async () => {
      if (!alive || busy.current) return;
      if (typeof document !== "undefined" && document.visibilityState === "hidden") return;
      const pack = await readState();
      if (!alive || !pack) return;
      if (!loaded.current) {
        loaded.current = true;
        applyRemote(pack);
        return;
      }
      if ((pack.updatedAt || 0) > version.current) applyRemote(pack);
    };

    pull();
    const id = setInterval(pull, 6000);
    const onWake = () => pull();
    window.addEventListener("focus", onWake);
    window.addEventListener("online", onWake);
    document.addEventListener("visibilitychange", onWake);

    return () => {
      alive = false;
      clearInterval(id);
      window.removeEventListener("focus", onWake);
      window.removeEventListener("online", onWake);
      document.removeEventListener("visibilitychange", onWake);
    };
  }, [ready, enabled]);
}

/* ---------- root ---------- */

function DelvyCalendarSystem() {
  const [lang, setLang] = useState("uk");
  const [user, setUser] = useState(null);
  const [authChecked, setAuthChecked] = useState(false);
  const [mode, setMode] = useState("login"); // "login" | "register"
  const [email, setEmail] = useState("");
  const [pass, setPass] = useState("");
  const [pass2, setPass2] = useState("");
  const [regFirstName, setRegFirstName] = useState("");
  const [regLastName, setRegLastName] = useState("");
  const [regRole, setRegRole] = useState("trainer");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const [info, setInfo] = useState("");

  useBrandFont();
  const sysDark = useSystemDark();
  const wide = useWide();

  const [profiles, setProfiles] = useState({
    trainer: { ...emptyProfile },
    englishTeacher: { ...emptyProfile },
    vocalTeacher: { ...emptyProfile },
  });

  const [adminProfile, setAdminProfile] = useState({ name: "Tim", birth: "", avatar: null, avatarZoom: 1 });

  const [entries, setEntries] = useState({
    trainer: [],
    englishTeacher: [],
    vocalTeacher: [],
  });

  const [events, setEvents] = useState([]);
  const [tracks, setTracks] = useState([]);
  const [words, setWords] = useState([]);
  const [adjustments, setAdjustments] = useState({ trainer: [], englishTeacher: [], vocalTeacher: [] });
  const [rates, setRates] = useState({ ...RATES });

  // Паролі, які користувач щойно ввів при реєстрації/вході. Сервер зберігає
  // лише хеш, тож єдиний момент, коли ми бачимо пароль — це форма входу.
  // Тримаємо його тут, щоб віддалений стан не затер локально впійманий пароль.
  const pendingPw = useRef({});

  const mergePw = (map) => {
    const next = { ...map };
    Object.keys(pendingPw.current).forEach((role) => {
      const pw = pendingPw.current[role];
      if (!pw) return;
      const stored = ((next[role] || {}).password || "").trim();
      if (stored) {
        // У спільному стані вже є пароль (синхронізувався або адмін змінив
        // його вручну) — він головніший, локальну копію більше не нав'язуємо.
        delete pendingPw.current[role];
        return;
      }
      next[role] = { ...(next[role] || emptyProfile), password: pw };
    });
    return next;
  };

  const applyRemote = (data) => {
    if (!data) return;
    if (data.profiles) setProfiles((prev) => mergePw({ ...prev, ...data.profiles }));
    if (data.adminProfile) setAdminProfile(data.adminProfile);
    if (data.entries) setEntries((prev) => ({ ...prev, ...data.entries }));
    if (Array.isArray(data.events)) setEvents(data.events);
    if (Array.isArray(data.tracks)) setTracks(data.tracks);
    if (Array.isArray(data.words)) setWords(data.words);
    if (data.adjustments) setAdjustments((prev) => ({ ...prev, ...data.adjustments }));
    if (data.rates) setRates((prev) => ({ ...prev, ...data.rates }));
  };

  useSharedState(profiles, adminProfile, entries, events, tracks, adjustments, rates, words, applyRemote, !!user);

  // Defensive guard: everything downstream (RIGHTS[user.id], profiles[user.id],
  // etc) assumes user.id is one of these four values. If a corrupted/legacy
  // account ever slips through (e.g. a bad id from a data-migration issue),
  // this stops it from crashing the whole app with a blank white screen.
  const isValidUser = (u) => !!u && !!u.id && !!RIGHTS[u.id];

  // Restore session on load (server checks the httpOnly cookie).
  useEffect(() => {
    let alive = true;
    (async () => {
      try {
        const me = await api("/me");
        if (alive && me && me.user) {
          if (isValidUser(me.user)) {
            setUser(me.user);
          } else {
            // Corrupted account — don't let it through, and don't leave a
            // dangling session cookie behind either.
            api("/logout", { method: "POST" }).catch(() => {});
            setErr(L[lang].serverError);
          }
        }
      } catch (err) {
        // not logged in — fine
      } finally {
        if (alive) setAuthChecked(true);
      }
    })();
    return () => {
      alive = false;
    };
  }, []);

  const t = L[lang];
  // Адмін не входить у `profiles` (він окремо, в adminProfile), тому його
  // день народження раніше ніде не з'являвся. Додаємо його як псевдо-акаунт
  // "admin", щоб тренер/вчителі теж бачили його у вкладці "Усі".
  const autoBirth = birthdayEntries({ ...profiles, admin: adminProfile }, t);
  const adminBirth = (autoBirth.admin || []).map((e) => ({
    ...e,
    owner: "admin",
    label: adminProfile.name ? `${t.birthday} · ${adminProfile.name}` : t.birthday,
  }));

  // ДН адміна підмішується в календар кожного акаунта (він auto, тож його
  // не можна редагувати/скасувати і він не потрапляє в розрахунок оплати).
  const listFor = (uid) =>
    uid === "admin"
      ? adminBirth
      : [...(entries[uid] || []), ...(autoBirth[uid] || []), ...adminBirth];

  const resetAuthForm = () => {
    setPass("");
    setPass2("");
    setErr("");
    setInfo("");
  };

  const login = async () => {
    if (!email.trim() || !pass) {
      setErr(t.fillAll);
      return;
    }
    setBusy(true);
    setErr("");
    try {
      const res = await api("/login", { method: "POST", body: { email: email.trim().toLowerCase(), password: pass } });
      if (!isValidUser(res.user)) {
        setErr(t.serverError);
        return;
      }
      if (REGISTERABLE_ROLES.includes(res.user.id)) {
        // Записуємо ДО setUser: далі вмикається синхронізація, вантажиться
        // віддалений стан, і без pendingPw він затирав щойно впійманий пароль.
        pendingPw.current[res.user.id] = pass;
        setProfiles((prev) => ({
          ...prev,
          [res.user.id]: { ...(prev[res.user.id] || emptyProfile), password: pass },
        }));
      }
      setUser(res.user);
      resetAuthForm();
    } catch (e) {
      // 401 у будь-якому вигляді — це саме невдалий вхід, а не поломка сервера.
      const authFail =
        e.code === "invalid_credentials" ||
        e.code === "unauthorized" ||
        (e.code || "").indexOf("debug_") === 0;
      setErr(authFail ? t.error : t.serverError);
    } finally {
      setBusy(false);
    }
  };

  const register = async () => {
    if (!email.trim() || !pass || !pass2 || !regFirstName.trim() || !regLastName.trim()) {
      setErr(t.fillAll);
      return;
    }
    if (pass !== pass2) {
      setErr(t.error);
      return;
    }
    setBusy(true);
    setErr("");
    try {
      await api("/register", {
        method: "POST",
        body: {
          email: email.trim().toLowerCase(),
          password: pass,
          role: regRole,
          firstName: regFirstName.trim(),
          lastName: regLastName.trim(),
        },
      });
      pendingPw.current[regRole] = pass;
      setProfiles((prev) => ({
        ...prev,
        [regRole]: {
          ...(prev[regRole] || emptyProfile),
          email: email.trim().toLowerCase(),
          firstName: regFirstName.trim(),
          lastName: regLastName.trim(),
          password: pass,
        },
      }));
      setMode("login");
      resetAuthForm();
      setInfo(t.regSuccess);
    } catch (e) {
      setErr(e.code === "role_taken" ? t.roleTaken : t.serverError);
    } finally {
      setBusy(false);
    }
  };

  const logout = async () => {
    try {
      await api("/logout", { method: "POST" });
    } catch (e) {
      // ignore
    }
    setUser(null);
    setEmail("");
    resetAuthForm();
  };

  const addEntry = (uid, entry) => setEntries((prev) => ({ ...prev, [uid]: [...prev[uid], entry] }));

  const removeEntry = (uid, id) =>
    setEntries((prev) => ({ ...prev, [uid]: prev[uid].filter((e) => e.id !== id) }));

  const updateEntry = (uid, entry) =>
    setEntries((prev) => ({
      ...prev,
      [uid]: prev[uid].map((e) => (e.id === entry.id ? entry : e)),
    }));

  const addWords = (rows, by, pending) =>
    setWords((prev) => [
      ...prev,
      ...rows.map((r) => ({
        ...r,
        id: Date.now() + "-" + Math.random().toString(36).slice(2, 7),
        addedAt: Date.now(),
        by,
        pending: Boolean(pending),
      })),
    ]);

  const editWord = (w) => setWords((prev) => prev.map((x) => (x.id === w.id ? w : x)));
  const removeWord = (id) => setWords((prev) => prev.filter((x) => x.id !== id));

  const toggleCancel = (uid, id, by) =>
    setEntries((prev) => ({
      ...prev,
      [uid]: prev[uid].map((e) =>
        e.id === id
          ? {
              ...e,
              cancelled: !e.cancelled,
              cancelledBy: !e.cancelled ? by : null,
              cancelledAt: !e.cancelled ? Date.now() : null,
            }
          : e
      ),
    }));

  if (user && user.role === "admin") {
    return (
      <AdminPanel
        t={t}
        lang={lang}
        setLang={setLang}
        wide={wide}
        profiles={profiles}
        setProfiles={setProfiles}
        adminProfile={adminProfile}
        setAdminProfile={setAdminProfile}
        entries={entries}
        setEntries={setEntries}
        listFor={listFor}
        addEntry={addEntry}
        updateEntry={updateEntry}
        removeEntry={removeEntry}
        toggleCancel={toggleCancel}
        events={events}
        setEvents={setEvents}
        tracks={tracks}
        setTracks={setTracks}
        adjustments={adjustments}
        setAdjustments={setAdjustments}
        rates={rates}
        setRates={setRates}
        words={words}
        onRequestWords={(rows) => addWords(rows, "admin", true)}
        onRemoveWord={removeWord}
      />
    );
  }

  if (user) {
    return (
      <UserPortal
        t={t}
        lang={lang}
        setLang={setLang}
        onLogout={logout}
        wide={wide}
        userId={user.id}
        profile={profiles[user.id]}
        setProfile={(p) => setProfiles((prev) => ({ ...prev, [user.id]: p }))}
        adminProfile={adminProfile}
        list={listFor(user.id)}
        listFor={listFor}
        onAdd={(e) => addEntry(user.id, e)}
        onEdit={(e) => updateEntry(user.id, e)}
        onCancel={(id) => toggleCancel(user.id, id, user.id)}
        events={events}
        tracks={tracks}
        adjustments={adjustments[user.id] || []}
        rate={rates[user.id] || 0}
        words={words}
        onAddWords={(rows) => addWords(rows, user.id)}
        onEditWord={editWord}
        onRemoveWord={removeWord}
        onAddAdjust={(a) =>
          setAdjustments((prev) => ({ ...prev, [user.id]: [...(prev[user.id] || []), a] }))
        }
        onRemoveAdjust={(id) =>
          setAdjustments((prev) => ({
            ...prev,
            [user.id]: (prev[user.id] || []).filter((x) => x.id !== id),
          }))
        }
        onTrackEdit={(tr) => setTracks((prev) => prev.map((x) => (x.id === tr.id ? tr : x)))}
      />
    );
  }

  const theme = sysDark ? THEMES.dark : THEMES.light;

  return (
    <div style={{ ...S.page, ...theme }}>
      <LangBar lang={lang} setLang={setLang} accent="var(--fg)" />
      <div style={S.loginCenter}>
        <div style={{ width: "100%", maxWidth: 320 }}>
          <h1 style={S.brand}>Delvy&apos;s System</h1>
          <p style={S.brandSub}>{t.subtitle}</p>

          {!authChecked ? (
            <div style={S.form}>
              <p style={S.actsText}>{t.loading}</p>
            </div>
          ) : mode === "login" ? (
            <div style={S.form}>
              <label style={S.label}>{t.emailField}</label>
              <input
                type="email"
                value={email}
                placeholder="name@example.com"
                onChange={(e) => setEmail(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && login()}
                style={S.input}
                autoCapitalize="none"
              />
              <label style={S.label}>{t.password}</label>
              <input
                type="password"
                value={pass}
                placeholder="••••••••"
                onChange={(e) => setPass(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && login()}
                style={S.input}
              />
              <div style={S.actsBox}>
                <p style={S.actsText}>{t.acts1}</p>
                <p style={S.actsText}>{t.acts2}</p>
              </div>
              {info ? <p style={{ ...S.actsText, color: "#25A244" }}>{info}</p> : null}
              {err ? <p style={S.err}>{err}</p> : null}
              <button onClick={login} style={S.loginBtn} disabled={busy}>
                {busy ? t.loading : t.login}
              </button>
              <button
                onClick={() => {
                  setMode("register");
                  resetAuthForm();
                }}
                style={{ ...S.loginBtn, background: "transparent", color: "var(--fg)", border: "1px solid var(--line)" }}
              >
                {t.noAccount}
              </button>
            </div>
          ) : (
            <div style={S.form}>
              <label style={S.label}>{t.role}</label>
              <select value={regRole} onChange={(e) => setRegRole(e.target.value)} style={S.input}>
                <option value="trainer">{t.roleTrainer}</option>
                <option value="englishTeacher">{t.roleEnglishTeacher}</option>
                <option value="vocalTeacher">{t.roleVocalTeacher}</option>
              </select>
              <label style={S.label}>{t.regFirstName}</label>
              <input value={regFirstName} onChange={(e) => setRegFirstName(e.target.value)} style={S.input} />
              <label style={S.label}>{t.regLastName}</label>
              <input value={regLastName} onChange={(e) => setRegLastName(e.target.value)} style={S.input} />
              <label style={S.label}>{t.emailField}</label>
              <input
                type="email"
                value={email}
                placeholder="name@example.com"
                onChange={(e) => setEmail(e.target.value)}
                style={S.input}
                autoCapitalize="none"
              />
              <label style={S.label}>{t.password}</label>
              <input type="password" value={pass} onChange={(e) => setPass(e.target.value)} style={S.input} />
              <label style={S.label}>{t.password}</label>
              <input type="password" value={pass2} onChange={(e) => setPass2(e.target.value)} style={S.input} />
              {err ? <p style={S.err}>{err}</p> : null}
              <button onClick={register} style={S.loginBtn} disabled={busy}>
                {busy ? t.loading : t.register}
              </button>
              <button
                onClick={() => {
                  setMode("login");
                  resetAuthForm();
                }}
                style={{ ...S.loginBtn, background: "transparent", color: "var(--fg)", border: "1px solid var(--line)" }}
              >
                {t.haveAccount}
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- chrome ---------- */

function LangBar({ lang, setLang, accent, onLogout, note, noteStyle }) {
  const a = accent || YELLOW;
  const opts = [
    ["uk", "УКР"],
    ["ru", "РУС"],
    ["en", "ENG"],
  ];
  return (
    <div style={S.topBar}>
      <div style={S.langRow}>
        <GlobeIcon color="var(--muted)" />
        {opts.map(([code, label]) => {
          const on = lang === code;
          return (
            <button
              key={code}
              onClick={() => setLang(code)}
              style={{ ...S.langBtn, borderColor: on ? a : "transparent", color: on ? a : "var(--muted)" }}
            >
              {label}
            </button>
          );
        })}
      </div>

      {onLogout ? (
        <div style={S.exitRow}>
          {note ? <span style={{ ...S.topNote, ...(noteStyle || {}) }}>{note}</span> : <span />}
          <button onClick={onLogout} style={S.exitBtn}>
            <ExitIcon color="var(--muted)" />
          </button>
        </div>
      ) : null}
    </div>
  );
}

function TabBar({ t, tab, setTab, tabs, accent, barStyle, inactiveColor }) {
  const A = accent || YELLOW;
  const icons = {
    schedule: CalendarIcon,
    all: GlobalCalendarIcon,
    events: EventIcon,
    pay: WalletIcon,
    playlist: MusicIcon,
    accounts: UsersIcon,
    account: ProfileIcon,
    me: ProfileIcon,
    usi: GlobalCalendarIcon,
    dict: BookIcon,
  };
  const labels = {
    schedule: t.schedule,
    all: t.all,
    events: t.events,
    pay: t.pay,
    playlist: t.playlist,
    accounts: t.accounts,
    account: t.account,
    me: t.myProfile,
    usi: t.everyone,
    dict: t.dict,
  };

  return (
    <div style={{ ...S.tabBar, ...(barStyle || {}) }}>
      <div style={S.tabInner}>
        {tabs.map((id) => {
          const on = tab === id;
          const Icon = icons[id];
          const color = on ? A : inactiveColor || "var(--muted)";
          return (
            <button key={id} onClick={() => setTab(id)} style={{ ...S.tabBtn, color: color }}>
              <Icon color={color} />
              <span style={S.tabLabel}>{labels[id]}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

/* ---------- calendar ---------- */

function monthGrid(year, month) {
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const rawFirst = new Date(year, month, 1).getDay();
  const first = (rawFirst + 6) % 7;
  const cells = [];
  for (let i = 0; i < first; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);
  return cells;
}

function CalendarView({ t, list, events, accent, wide, legendTypes, brand, brandSub, brandStyle, brandTop, brandTopStyle, countLabel, showEvents, dayHeadColor, dayPanelStyle }) {
  const A = accent || YELLOW;
  const [cursor, setCursor] = useState(() => currentMonthIndex());
  const [picked, setPicked] = useState(null);
  const [todayIso, setTodayIso] = useState(() => todayIsoString());

  // Тримаємо календар синхронізованим з реальною датою: якщо додаток
  // залишається відкритим і настає нова доба чи новий місяць, "сьогодні"
  // і (якщо користувач саме дивився на поточний місяць, а не гортав
  // календар вручну) сам місяць автоматично підхоплюються без перезавантаження.
  const currentMonthRef = useRef(currentMonthIndex());
  useEffect(() => {
    const sync = () => {
      const nowIso = todayIsoString();
      setTodayIso((prev) => (prev === nowIso ? prev : nowIso));
      const nowIdx = currentMonthIndex();
      if (nowIdx !== currentMonthRef.current) {
        setCursor((prevCursor) => (prevCursor === currentMonthRef.current ? nowIdx : prevCursor));
        currentMonthRef.current = nowIdx;
      }
    };
    sync();
    const id = setInterval(sync, 60000);
    window.addEventListener("focus", sync);
    document.addEventListener("visibilitychange", sync);
    return () => {
      clearInterval(id);
      window.removeEventListener("focus", sync);
      document.removeEventListener("visibilitychange", sync);
    };
  }, []);

  const year = Math.floor(cursor / 12);
  const month = cursor % 12;

  const cells = monthGrid(year, month);
  const useEvents = showEvents === false ? [] : events || [];
  const eventDays = useEvents.map((e) => e.date);

  // День народження — не активність: у календарі показується, але ніде не рахується.
  let count = 0;
  cells.forEach((d) => {
    if (!d) return;
    const info = dayInfo(list, isoOf(year, month, d));
    if (info && info.type !== "birthday") count += 1;
  });

  const canPrev = cursor > RANGE_START;
  const canNext = cursor < RANGE_END;

  const presentTypes = new Set();
  cells.forEach((d) => {
    if (!d) return;
    const iso = isoOf(year, month, d);
    (list || []).forEach((e) => {
      if (e.cancelled) return;
      if (eachIso(e.date, e.dateTo).includes(iso)) presentTypes.add(e.type);
    });
  });

  const legend = (legendTypes || []).filter(
    (k) => k !== "birthday" && k !== "rest" && presentTypes.has(k)
  );

  return (
    <div>
      {brand ? (
        <div style={S.brandBlock}>
          {brandTop ? <div style={{ ...S.brandTop, ...(brandTopStyle || {}) }}>{brandTop}</div> : null}
          <div style={{ ...S.brandMark, ...(brandStyle || {}) }}>{brand}</div>
          {brandSub ? <div style={S.brandName}>{brandSub}</div> : null}
        </div>
      ) : null}

      <div style={{ ...S.monthRow, marginTop: brand ? 26 : 14 }}>
        <h2 style={S.monthTitle}>
          {t.months[month]} {year}
        </h2>
        <div style={S.navRow}>
          <button
            onClick={() => {
              if (!canPrev) return;
              setCursor(cursor - 1);
              setPicked(null);
            }}
            style={{ ...S.navBtn, borderColor: A, color: A, opacity: canPrev ? 1 : 0.25 }}
          >
            ‹
          </button>
          <button
            onClick={() => {
              if (!canNext) return;
              setCursor(cursor + 1);
              setPicked(null);
            }}
            style={{ ...S.navBtn, borderColor: A, color: A, opacity: canNext ? 1 : 0.25 }}
          >
            ›
          </button>
        </div>
      </div>

      <div style={S.countPill}>
        {countLabel || t.thisMonth}: {count}
      </div>

      <div style={S.weekRow}>
        {t.days.map((d) => (
          <div key={d} style={S.weekCell}>
            {d}
          </div>
        ))}
      </div>

      <div style={S.grid}>
        {cells.map((d, i) => {
          if (!d) return <div key={i} style={S.emptyCell} />;
          const iso = isoOf(year, month, d);
          const info = dayInfo(list, iso);
          const isToday = iso === todayIso;
          const isPicked = picked === iso;

          // Кожне окреме завдання дня отримує власний кольоровий індикатор,
          // а не одну спільну обводку клітинки на всі завдання відразу.
          const dayTasks = (list || []).filter(
            (e) => e.type !== "birthday" && eachIso(e.date, e.dateTo).includes(iso)
          );
          const dayEventsHere = useEvents.filter((e) => e.date === iso);
          const dots = [
            ...dayTasks.map((e) => (e.cancelled ? RED : ACT[e.type].color)),
            ...dayEventsHere.map(() => ACT.event.color),
          ];
          const hasBirthday = (list || []).some(
            (e) => e.type === "birthday" && !e.cancelled && eachIso(e.date, e.dateTo).includes(iso)
          );

          const MAX_DOTS = 4;
          const shownDots = dots.slice(0, MAX_DOTS);
          const extraDots = dots.length - shownDots.length;

          return (
            <div
              key={i}
              onClick={() => setPicked(isPicked ? null : iso)}
              style={{
                ...S.dayCell,
                cursor: "pointer",
                backgroundColor: isToday ? hexToRgba(A, 0.14) : "var(--surface)",
                borderColor: isPicked ? A : "var(--line)",
                borderWidth: isPicked ? 2 : 1.5,
                boxShadow: isPicked ? `0 0 0 1px ${A}` : "none",
                outline: isToday ? `1.5px solid ${A}` : "none",
                outlineOffset: -1,
                color: isToday ? A : "var(--on-surface)",
                fontWeight: isToday ? 800 : 600,
                fontSize: wide ? 15 : 13,
                textDecoration: info && info.cancelled ? "line-through" : "none",
              }}
            >
              <span>{d}</span>
              {hasBirthday ? (
                <span style={{ ...S.hbTag, color: ACT.birthday.color }}>{t.hb}</span>
              ) : null}
              {dots.length ? (
                <span style={S.dotsRow}>
                  {shownDots.map((color, di) => (
                    <span key={di} style={{ ...S.dayDot, backgroundColor: color }} />
                  ))}
                  {extraDots > 0 ? <span style={S.dotsMore}>+{extraDots}</span> : null}
                </span>
              ) : null}
            </div>
          );
        })}
      </div>

      {picked ? (
        <DayDetails
          t={t}
          iso={picked}
          list={list}
          events={useEvents}
          accent={A}
          headColor={dayHeadColor}
          panelStyle={dayPanelStyle}
        />
      ) : null}

      {legend.length || presentTypes.has("birthday") ? (
        <div style={S.legendRow}>
          {legend.map((k) => (
            <div key={k} style={S.legendItem}>
              <span style={{ ...S.legendDot, backgroundColor: ACT[k].color }} />
              <span style={S.legendLabel}>{t[k]}</span>
            </div>
          ))}
          {presentTypes.has("birthday") ? (
            <div style={S.legendItem}>
              <span style={{ ...S.legendDot, backgroundColor: ACT.birthday.color }} />
              <span style={S.legendLabel}>{t.hb}</span>
            </div>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}

function MoonIcon({ color }) {
  return (
    <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
      <path d="M20 14.5A8.5 8.5 0 0 1 9.5 4a8.5 8.5 0 1 0 10.5 10.5z" />
    </svg>
  );
}

function DayDetails({ t, iso, list, events, accent, headColor, panelStyle }) {
  const d = new Date(iso);
  const wd = (d.getDay() + 6) % 7;
  const heading = `${t.daysFull[wd]}, ${d.getDate()} ${t.monthsGen[d.getMonth()]}`;

  const items = (list || []).filter((e) => eachIso(e.date, e.dateTo).includes(iso));
  const evs = (events || []).filter((e) => e.date === iso);

  const empty = items.length === 0 && evs.length === 0;

  return (
    <div style={{ ...S.dayPanel, ...(panelStyle || {}) }}>
      <div style={{ ...S.dayPanelHead, color: headColor || "var(--muted)" }}>{heading}</div>

      {empty ? (
        <div style={S.dayEmpty}>
          <MoonIcon color="var(--muted)" />
          <span>{t.dayFree}</span>
        </div>
      ) : null}

      {items.map((e) => {
        const c = e.cancelled ? RED : ACT[e.type].color;
        return (
          <div key={e.id} style={{ ...S.dayItem, borderLeftColor: c }}>
            <div style={S.dayItemTop}>
              <span style={{ ...S.legendDot, backgroundColor: c }} />
              <span style={{ ...S.dayItemTitle, textDecoration: e.cancelled ? "line-through" : "none" }}>
                {e.label || e.title || (e.type === "birthday" ? t.hb : t[e.type])}
              </span>
              {e.from ? (
                <span style={S.entryTime}>
                  {e.from}
                  {e.to ? `–${e.to}` : ""}
                </span>
              ) : null}
            </div>
            {e.km ? <div style={S.entrySub}>{e.km} км</div> : null}
            {e.platform ? (
              <div style={S.entrySub}>{e.platform === "zoom" ? "Zoom" : "Google Meet"}</div>
            ) : null}
            {e.place ? (
              <a href={mapsUrl(e.place)} target="_blank" rel="noreferrer" style={{ ...S.mapLink, color: c }}>
                <PinIcon color={c} />
                <span>{e.place}</span>
              </a>
            ) : null}
            {e.cancelled ? <div style={S.cancelBanner}>{t.cancelled}</div> : null}
          </div>
        );
      })}

      {evs.map((e) => (
        <div key={e.id} style={{ ...S.dayItem, borderLeftColor: ACT.event.color }}>
          <div style={S.dayItemTop}>
            <span style={{ ...S.legendDot, backgroundColor: ACT.event.color }} />
            <span style={S.dayItemTitle}>{e.title}</span>
          </div>
          {e.place ? (
            <a href={mapsUrl(e.place)} target="_blank" rel="noreferrer" style={{ ...S.mapLink, color: ACT.event.color }}>
              <PinIcon color={ACT.event.color} />
              <span>{e.place}</span>
            </a>
          ) : null}
        </div>
      ))}
    </div>
  );
}

/* ---------- entry list ---------- */

function EntryList({ t, list, rights, onCancel, onRemove, onEdit }) {
  // Заплановане — тільки те, що попереду: минуле лишається в календарі й в оплаті.
  const upcoming = (list || []).filter((e) => !hasPassed(e));
  if (upcoming.length === 0) return null;

  const sorted = [...upcoming].sort((a, b) => (a.date > b.date ? 1 : -1));

  return (
    <div style={{ marginTop: 26 }}>
      <div style={S.plannedHead}>
        {t.planned}
        <span style={S.plannedHint}>
          {" "}
          · {rights && (rights.cancel || rights.remove) ? t.plannedHint : t.viewOnly}
        </span>
      </div>

      {sorted.map((e) => {
        const c = e.cancelled ? RED : ACT[e.type].color;
        return (
          <div key={e.id} style={{ ...S.entryCard, borderLeftColor: c }}>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={S.entryTop}>
                <span style={{ ...S.legendDot, backgroundColor: c }} />
                <span style={{ ...S.entryDate, textDecoration: e.cancelled ? "line-through" : "none" }}>
                  {e.date}
                  {e.dateTo && e.dateTo !== e.date ? ` → ${e.dateTo}` : ""}
                </span>
                {e.from ? (
                  <span style={S.entryTime}>
                    {e.from}
                    {e.to ? `–${e.to}` : ""}
                  </span>
                ) : null}
                {e.type === "birthday" ? <span style={S.entryTime}>{t.hb}</span> : null}
              </div>

              <div style={{ ...S.entryTitle, textDecoration: e.cancelled ? "line-through" : "none" }}>
                {e.label || e.title || t[e.type]}
              </div>
              {e.title && e.label ? <div style={S.entrySub}>{e.title}</div> : null}
              {e.km ? <div style={S.entrySub}>{e.km} км</div> : null}
            {e.platform ? (
              <div style={S.entrySub}>{e.platform === "zoom" ? "Zoom" : "Google Meet"}</div>
            ) : null}
              {e.platform ? (
                <div style={S.entrySub}>{e.platform === "zoom" ? "Zoom" : "Google Meet"}</div>
              ) : null}
              {e.auto ? <div style={S.entrySub}>{t.birthAuto}</div> : null}

              {e.place ? (
                <a href={mapsUrl(e.place)} target="_blank" rel="noreferrer" style={{ ...S.mapLink, color: c }}>
                  <PinIcon color={c} />
                  <span>{e.place}</span>
                </a>
              ) : null}

              {e.cancelled ? <div style={S.cancelBanner}>{t.cancelled}</div> : null}
            </div>

            {!e.auto ? (
              <div style={S.entryActions}>
                {onEdit ? (
                  <button onClick={() => onEdit(e)} style={S.iconBtn}>
                    <EditIcon color="var(--muted)" />
                  </button>
                ) : null}
                {rights && rights.cancel ? (
                  <button onClick={() => onCancel(e.id)} style={S.iconBtn}>
                    {e.cancelled ? <UndoIcon color="var(--muted)" /> : <BanIcon color={RED} />}
                  </button>
                ) : null}
                {rights && rights.remove ? (
                  <button onClick={() => onRemove(e.id)} style={S.iconBtn}>
                    <TrashIcon color="#e0607a" />
                  </button>
                ) : null}
              </div>
            ) : null}
          </div>
        );
      })}
    </div>
  );
}

/* ---------- entry form ---------- */

function EntryForm({ t, types, onAdd, titleLabel, presetOnly, lockLabel, keep, setKeep, showReset, platform }) {
  const [type, setType] = useState(types[0]);
  const [preset, setPreset] = useState(SESSION_PRESETS[0]);
  const [lessonPreset, setLessonPreset] = useState(LESSON_PRESETS[0]);
  const [speakPreset, setSpeakPreset] = useState(SPEAKING_PRESETS[0]);
  const [engPreset, setEngPreset] = useState(ENGLISH_PRESETS[0]);
  const [manual, setManual] = useState(false);
  const [title, setTitle] = useState("");
  const [label, setLabel] = useState("");
  const [place, setPlace] = useState("");
  const [km, setKm] = useState("");
  const [groupPlace, setGroupPlace] = useState(GROUP_LOCATIONS[0]);
  const [cyclePreset, setCyclePreset] = useState(CYCLE_PRESETS[0]);

  const date = keep ? keep.date : "";
  const dateTo = keep ? keep.dateTo : "";
  const from = keep ? keep.from : "17:00";
  const to = keep ? keep.to : "18:00";

  const setDate = (v) => setKeep({ ...keep, date: v });
  const setDateTo = (v) => setKeep({ ...keep, dateTo: v });
  const setFrom = (v) => setKeep({ ...keep, from: v });
  const setTo = (v) => setKeep({ ...keep, to: v });

  useEffect(() => {
    if (!types.includes(type)) setType(types[0]);
  }, [types]);

  const c = ACT[type].color;
  const timed = ["sport", "group", "cycle", "lesson", "run", "speaking", "english", VOLUNTEER_TYPE].includes(type);

  const reset = () => {
    setTitle("");
    setLabel("");
    setPlace("");
    setKm("");
    setKeep({ date: "", dateTo: "", from: "17:00", to: "18:00" });
  };

  const pickType = (k) => {
    setType(k);
    setKeep({ ...keep, date: "", dateTo: "" });
  };

  const submit = () => {
    if (!date) return;
    const entry = { id: Date.now() + "-" + Math.random().toString(36).slice(2, 7), type, date, cancelled: false };

    if (type === "sport") {
      entry.title = manual ? title.trim() : preset;
      entry.label = label.trim();
      entry.from = from;
      entry.to = to;
    }
    if (type === "lesson") {
      entry.title = manual ? title.trim() : lessonPreset;
      entry.label = label.trim();
      entry.from = from;
      entry.to = to;
    }
    if (type === "speaking" || type === "english") {
      const presetVal = type === "speaking" ? speakPreset : engPreset;
      entry.title = manual && !presetOnly ? title.trim() : presetVal;
      entry.label = lockLabel ? t[type] : label.trim() || t[type];
      if (platform) entry.platform = platform;
      entry.from = from;
      entry.to = to;
    }
    if (type === "group") {
      entry.title = title.trim();
      entry.place = groupPlace;
      entry.from = from;
      entry.to = to;
    }
    if (type === "cycle") {
      entry.title = cyclePreset;
      entry.label = t.cycleLabel;
      entry.place = CYCLE_LOCATION;
      entry.from = from;
      entry.to = to;
    }
    if (type === "run") {
      entry.place = place.trim();
      entry.km = km.trim();
      entry.from = from;
      entry.to = to;
    }
    if (type === VOLUNTEER_TYPE) {
      entry.title = t.volunteer;
      entry.label = t.volunteer;
      entry.place = place.trim();
      entry.from = from;
      entry.to = to;
    }
    if (type === "rest") {
      entry.dateTo = dateTo || date;
    }

    onAdd(entry);
    reset();
  };

  return (
    <div style={{ marginTop: 18 }}>
      <div style={S.fieldLabel}>{t.type}</div>
      <div style={{ ...S.typeGrid, gridTemplateColumns: `repeat(${types.length}, minmax(0, 1fr))` }}>
        {types.map((k) => {
          const on = type === k;
          const kc = ACT[k].color;
          return (
            <button
              key={k}
              onClick={() => pickType(k)}
              style={{
                ...S.typeCard,
                borderColor: on ? kc : "var(--line)",
                backgroundColor: on ? kc + "33" : "transparent",
                boxShadow: on ? `0 0 0 1px ${kc}` : "none",
                color: on ? "var(--fg)" : "var(--muted)",
              }}
            >
              <span style={S.typeEmoji}>{ACT[k].emoji}</span>
              <span style={S.typeText}>{t[k]}</span>
            </button>
          );
        })}
      </div>

      {type === "sport" ? (
        <>
          <div style={S.segRow}>
            <button
              onClick={() => setManual(false)}
              style={{ ...S.segBtn, backgroundColor: !manual ? c : "transparent", color: !manual ? "#000" : "var(--muted)" }}
            >
              {t.choosePreset}
            </button>
            <button
              onClick={() => setManual(true)}
              style={{ ...S.segBtn, backgroundColor: manual ? c : "transparent", color: manual ? "#000" : "var(--muted)" }}
            >
              {t.manual}
            </button>
          </div>

          {manual ? (
            <Field label={titleLabel} value={title} onChange={setTitle} placeholder={t.titlePh} />
          ) : (
            <div style={S.fieldWrap}>
              <label style={S.fieldLabel}>{titleLabel}</label>
              <select value={preset} onChange={(e) => setPreset(e.target.value)} style={S.fieldInput}>
                {SESSION_PRESETS.map((p) => (
                  <option key={p} value={p}>
                    {p}
                  </option>
                ))}
              </select>
            </div>
          )}

          <Field label={t.labelSub} value={label} onChange={setLabel} placeholder={t.sport} />
        </>
      ) : null}

      {type === "cycle" ? (
        <>
          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.titleTrainer}</label>
            <select value={cyclePreset} onChange={(e) => setCyclePreset(e.target.value)} style={S.fieldInput}>
              {CYCLE_PRESETS.map((pv) => (
                <option key={pv} value={pv}>
                  {pv}
                </option>
              ))}
            </select>
          </div>

          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.labelSub}</label>
            <div style={{ ...S.fixedLabel, borderColor: c, color: c }}>{t.cycleLabel}</div>
          </div>

          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.place}</label>
            <a
              href={mapsUrl(CYCLE_LOCATION)}
              target="_blank"
              rel="noreferrer"
              style={{ ...S.placeOption, borderColor: c, color: c, textDecoration: "none" }}
            >
              <PinIcon color={c} />
              <span style={S.placeText}>{CYCLE_LOCATION}</span>
            </a>
          </div>
        </>
      ) : null}

      {type === "group" ? (
        <>
          <Field label={t.groupName} value={title} onChange={setTitle} placeholder={t.groupPh} />
          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.place}</label>
            <div style={S.placeList}>
              {GROUP_LOCATIONS.map((loc) => {
                const on = groupPlace === loc;
                return (
                  <button
                    key={loc}
                    onClick={() => setGroupPlace(loc)}
                    style={{
                      ...S.placeOption,
                      borderColor: on ? c : "var(--line)",
                      boxShadow: on ? `0 0 0 1px ${c}` : "none",
                      color: on ? "var(--fg)" : "var(--muted)",
                    }}
                  >
                    <PinIcon color={on ? c : "var(--muted)"} />
                    <span style={S.placeText}>{loc}</span>
                  </button>
                );
              })}
            </div>
          </div>
        </>
      ) : null}

      {type === "lesson" ? (
        <>
          <div style={S.segRow}>
            <button
              onClick={() => setManual(false)}
              style={{ ...S.segBtn, backgroundColor: !manual ? c : "transparent", color: !manual ? "#000" : "var(--muted)" }}
            >
              {t.choosePreset}
            </button>
            <button
              onClick={() => setManual(true)}
              style={{ ...S.segBtn, backgroundColor: manual ? c : "transparent", color: manual ? "#000" : "var(--muted)" }}
            >
              {t.manual}
            </button>
          </div>

          {manual ? (
            <Field label={titleLabel} value={title} onChange={setTitle} placeholder={t.lessonPh} />
          ) : (
            <div style={S.fieldWrap}>
              <label style={S.fieldLabel}>{titleLabel}</label>
              <select value={lessonPreset} onChange={(e) => setLessonPreset(e.target.value)} style={S.fieldInput}>
                {LESSON_PRESETS.map((pv) => (
                  <option key={pv} value={pv}>
                    {pv}
                  </option>
                ))}
              </select>
            </div>
          )}

          <Field label={t.labelSub} value={label} onChange={setLabel} placeholder={t.lesson} />
        </>
      ) : null}

      {type === "speaking" || type === "english" ? (
        <>
          {presetOnly ? null : (
            <div style={S.segRow}>
              <button
                onClick={() => setManual(false)}
                style={{ ...S.segBtn, backgroundColor: !manual ? c : "transparent", color: !manual ? "#fff" : "var(--muted)" }}
              >
                {t.choosePreset}
              </button>
              <button
                onClick={() => setManual(true)}
                style={{ ...S.segBtn, backgroundColor: manual ? c : "transparent", color: manual ? "#fff" : "var(--muted)" }}
              >
                {t.manual}
              </button>
            </div>
          )}

          {manual && !presetOnly ? (
            <Field label={titleLabel} value={title} onChange={setTitle} placeholder={t.lessonPh} />
          ) : (
            <div style={S.fieldWrap}>
              <label style={S.fieldLabel}>{titleLabel}</label>
              <select
                value={type === "speaking" ? speakPreset : engPreset}
                onChange={(e) => (type === "speaking" ? setSpeakPreset(e.target.value) : setEngPreset(e.target.value))}
                style={S.fieldInput}
              >
                {(type === "speaking" ? SPEAKING_PRESETS : ENGLISH_PRESETS).map((pv) => (
                  <option key={pv} value={pv}>
                    {pv}
                  </option>
                ))}
              </select>
            </div>
          )}

          {lockLabel ? (
            <div style={S.fieldWrap}>
              <label style={S.fieldLabel}>{t.labelSub}</label>
              <div style={{ ...S.fixedLabel, borderColor: c, color: c }}>{t[type]}</div>
            </div>
          ) : (
            <Field label={t.labelSub} value={label} onChange={setLabel} placeholder={t[type]} />
          )}
        </>
      ) : null}

      {type === "run" ? (
        <>
          <Field label={t.place} value={place} onChange={setPlace} placeholder={t.placePh} />
          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.km}</label>
            <input
              type="text"
              inputMode="numeric"
              value={km}
              placeholder={t.kmPh}
              onChange={(e) => setKm(e.target.value.replace(/[^\d]/g, "").slice(0, 3))}
              style={S.fieldInput}
            />
          </div>
        </>
      ) : null}

      {type === VOLUNTEER_TYPE ? (
        <Field label={t.place} value={place} onChange={setPlace} placeholder={t.volunteerPh} />
      ) : null}

      {type === "rest" ? (
        <div style={S.twoFields}>
          <Field label={t.dateFrom} value={date} onChange={setDate} type="date" />
          <Field label={t.dateTo} value={dateTo} onChange={setDateTo} type="date" />
        </div>
      ) : (
        <Field label={t.date} value={date} onChange={setDate} type="date" />
      )}

      {timed ? (
        <div style={S.twoFields}>
          <Field label={t.from} value={from} onChange={setFrom} type="time" />
          <Field label={t.to} value={to} onChange={setTo} type="time" />
        </div>
      ) : null}

      {type === "birthday" ? <div style={S.allDayNote}>{t.allDay}</div> : null}

      {showReset ? (
        <button
          onClick={() => setKeep({ ...keep, date: "", dateTo: "" })}
          style={{ ...S.ghostBtn, width: "100%", marginTop: 4 }}
        >
          {t.resetDate}
        </button>
      ) : null}

      <button onClick={submit} style={{ ...S.primaryBtn, backgroundColor: c, color: "#000" }}>
        + {t.addToSchedule}
      </button>
    </div>
  );
}

function EntryEditor({ t, entry, onSave, onClose, lockLabel }) {
  const [draft, setDraft] = useState(entry);
  const c = ACT[entry.type].color;
  const set = (k, v) => setDraft({ ...draft, [k]: v });
  const timed = ["sport", "group", "cycle", "lesson", "run", "speaking", "english", "volunteer"].includes(entry.type);

  return (
    <div style={S.editorBox}>
      <div style={S.editorHead}>
        <span style={{ ...S.legendDot, backgroundColor: c }} />
        <span style={S.editorTitle}>{t.edit}</span>
        <button onClick={onClose} style={{ ...S.iconBtn, marginLeft: "auto" }}>
          ×
        </button>
      </div>

      {["sport", "lesson", "group", "cycle", "speaking", "english"].includes(entry.type) ? (
        <Field label={t.titleTrainer} value={draft.title} onChange={(v) => set("title", v)} />
      ) : null}

      {["sport", "lesson"].includes(entry.type) ? (
        <Field label={t.labelSub} value={draft.label} onChange={(v) => set("label", v)} />
      ) : null}

      {["speaking", "english"].includes(entry.type) ? (
        lockLabel ? (
          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.labelSub}</label>
            <div style={{ ...S.fixedLabel, borderColor: c, color: c }}>{t[entry.type]}</div>
          </div>
        ) : (
          <Field label={t.labelSub} value={draft.label} onChange={(v) => set("label", v)} />
        )
      ) : null}

      {entry.type === "run" || entry.type === "volunteer" ? (
        <Field label={t.place} value={draft.place} onChange={(v) => set("place", v)} />
      ) : null}

      {entry.type === "group" ? (
        <div style={S.fieldWrap}>
          <label style={S.fieldLabel}>{t.place}</label>
          <div style={S.placeList}>
            {GROUP_LOCATIONS.map((loc) => {
              const on = draft.place === loc;
              return (
                <button
                  key={loc}
                  onClick={() => set("place", loc)}
                  style={{
                    ...S.placeOption,
                    borderColor: on ? c : "var(--line)",
                    boxShadow: on ? `0 0 0 1px ${c}` : "none",
                    color: on ? "var(--fg)" : "var(--muted)",
                  }}
                >
                  <PinIcon color={on ? c : "var(--muted)"} />
                  <span style={S.placeText}>{loc}</span>
                </button>
              );
            })}
          </div>
        </div>
      ) : null}

      {entry.type === "run" ? (
        <div style={S.fieldWrap}>
          <label style={S.fieldLabel}>{t.km}</label>
          <input
            type="text"
            inputMode="numeric"
            value={draft.km || ""}
            onChange={(e) => set("km", e.target.value.replace(/[^\d]/g, "").slice(0, 3))}
            style={S.fieldInput}
          />
        </div>
      ) : null}

      {entry.type === "rest" ? (
        <div style={S.twoFields}>
          <Field label={t.dateFrom} value={draft.date} onChange={(v) => set("date", v)} type="date" />
          <Field label={t.dateTo} value={draft.dateTo} onChange={(v) => set("dateTo", v)} type="date" />
        </div>
      ) : (
        <Field label={t.date} value={draft.date} onChange={(v) => set("date", v)} type="date" />
      )}

      {timed ? (
        <div style={S.twoFields}>
          <Field label={t.from} value={draft.from} onChange={(v) => set("from", v)} type="time" />
          <Field label={t.to} value={draft.to} onChange={(v) => set("to", v)} type="time" />
        </div>
      ) : null}

      <button onClick={() => onSave(draft)} style={{ ...S.primaryBtn, backgroundColor: c, color: "#000" }}>
        {t.saveEdit}
      </button>
    </div>
  );
}

/* ---------- shared calendar ---------- */

function TypeSummary({ t, list }) {
  const order = ["sport", "group", "cycle", "run", "lesson", "english", "speaking", "rest"];
  const counts = {};
  (list || []).forEach((e) => {
    if (e.cancelled) return;
    if (e.type === "birthday") return;   // ДР не рахуємо
    counts[e.type] = (counts[e.type] || 0) + 1;
  });

  const cancelled = (list || []).filter((e) => e.cancelled).length;
  const shown = order.filter((k) => counts[k]);

  if (shown.length === 0 && !cancelled) return null;

  return (
    <div style={S.summaryRow}>
      {shown.map((k) => (
        <div key={k} style={{ ...S.summaryChip, borderColor: ACT[k].color }}>
          <span style={{ ...S.legendDot, backgroundColor: ACT[k].color }} />
          <span style={S.summaryLabel}>{k === "birthday" ? t.hb : t[k]}</span>
          <span style={S.summaryCount}>{counts[k]}</span>
        </div>
      ))}
      {cancelled ? (
        <div style={{ ...S.summaryChip, borderColor: RED }}>
          <span style={{ ...S.legendDot, backgroundColor: RED }} />
          <span style={S.summaryLabel}>{t.cancelIt}</span>
          <span style={S.summaryCount}>{cancelled}</span>
        </div>
      ) : null}
    </div>
  );
}

function SharedCalendar({ t, listFor, events, accent, wide }) {
  const ids = ["trainer", "englishTeacher", "vocalTeacher"];
  const [section, setSection] = useState("all");

  const collect = () => {
    const out = [];
    const seen = new Set();
    const pick = section === "all" ? ids : [section];
    pick.forEach((uid) =>
      listFor(uid).forEach((e) => {
        // ДН адміна лежить у списку кожного акаунта і вже має owner "admin" —
        // не підписуємо його роллю і показуємо один раз.
        const owner = e.owner || uid;
        const key = owner + ":" + e.id;
        if (seen.has(key)) return;
        seen.add(key);
        out.push({ ...e, owner });
      })
    );
    return out;
  };

  const all = collect();
  const upcoming = all.filter((e) => !hasPassed(e));

  const legendFor = () => {
    if (section === "trainer") return ["sport", "group", "cycle", "run"];
    if (section === "vocalTeacher") return ["lesson"];
    if (section === "englishTeacher") return ["english", "speaking"];
    return ["sport", "group", "cycle", "run", "lesson", "english", "speaking"];
  };

  const tabs = [["all", t.all]].concat(ids.map((id) => [id, t.names[id]]));

  return (
    <div>
      <div style={{ ...S.ownerRow, marginTop: 16, marginBottom: 6 }}>
        {tabs.map(([id, label]) => {
          const on = section === id;
          return (
            <button
              key={id}
              onClick={() => setSection(id)}
              style={{
                ...S.switchBtn,
                backgroundColor: on ? accent : "transparent",
                color: on ? "var(--bg)" : "var(--muted)",
                borderColor: on ? accent : "var(--line)",
              }}
            >
              {label}
            </button>
          );
        })}
      </div>

      <CalendarView
        key={section}
        t={t}
        list={all}
        events={events}
        accent={accent}
        wide={wide}
        legendTypes={legendFor()}
      />

      <div style={{ marginTop: 26 }}>
        <div style={S.plannedHead}>
          {section === "all" ? t.all : t.names[section]} · {upcoming.length}
        </div>

        <TypeSummary t={t} list={upcoming} />
        {[...upcoming]
          .sort((a, b) => (a.date > b.date ? 1 : -1))
          .map((e) => {
            const c = e.cancelled ? RED : ACT[e.type].color;
            return (
              <div key={e.owner + e.id} style={{ ...S.entryCard, borderLeftColor: c }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={S.entryTop}>
                    <span style={{ ...S.legendDot, backgroundColor: c }} />
                    <span style={{ ...S.entryDate, textDecoration: e.cancelled ? "line-through" : "none" }}>
                      {e.date}
                      {e.dateTo && e.dateTo !== e.date ? ` → ${e.dateTo}` : ""}
                    </span>
                    {e.from ? (
                      <span style={S.entryTime}>
                        {e.from}
                        {e.to ? `–${e.to}` : ""}
                      </span>
                    ) : null}
                    <span style={S.ownerTag}>{t.names[e.owner]}</span>
                  </div>
                  <div style={{ ...S.entryTitle, textDecoration: e.cancelled ? "line-through" : "none" }}>
                    {e.label || e.title || (e.type === "birthday" ? t.hb : t[e.type])}
                  </div>
                  {e.cancelled ? <div style={S.cancelBanner}>{t.cancelled}</div> : null}
                </div>
              </div>
            );
          })}
      </div>
    </div>
  );
}

// "Усі" — об'єднаний перегляд лише "Відпочинок" + "День народження" для всіх
// трьох акаунтів разом (не по одному, як в "Загальний"/SharedCalendar).
function RestBirthdayCalendar({ t, listFor, accent, wide }) {
  const ids = ["trainer", "englishTeacher", "vocalTeacher"];
  const all = [];
  const seen = new Set();
  ids.forEach((uid) =>
    listFor(uid).forEach((e) => {
      if (e.type !== "rest" && e.type !== "birthday") return;
      // ДН адміна лежить у списку кожного акаунта — показуємо його один раз.
      const key = (e.owner || uid) + ":" + e.id;
      if (seen.has(key)) return;
      seen.add(key);
      all.push({ ...e, owner: e.owner || uid });
    })
  );

  return (
    <div>
      <CalendarView t={t} list={all} events={[]} accent={accent} wide={wide} legendTypes={["birthday", "rest"]} />

      <div style={{ marginTop: 26 }}>
        <div style={S.plannedHead}>
          {t.everyone} · {all.length}
        </div>

        {all.length === 0 ? (
          <div style={S.emptyState}>
            <p style={S.emptyTitle}>{t.dayFree}</p>
          </div>
        ) : null}

        {[...all]
          .sort((a, b) => (a.date > b.date ? 1 : -1))
          .map((e) => {
            const c = e.cancelled ? RED : ACT[e.type].color;
            return (
              <div key={e.owner + e.id} style={{ ...S.entryCard, borderLeftColor: c }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={S.entryTop}>
                    <span style={{ ...S.legendDot, backgroundColor: c }} />
                    <span style={{ ...S.entryDate, textDecoration: e.cancelled ? "line-through" : "none" }}>
                      {e.date}
                      {e.dateTo && e.dateTo !== e.date ? ` → ${e.dateTo}` : ""}
                    </span>
                    <span style={S.ownerTag}>{t.names[e.owner]}</span>
                  </div>
                  <div style={{ ...S.entryTitle, textDecoration: e.cancelled ? "line-through" : "none" }}>
                    {e.type === "birthday" ? t.hb : t.rest}
                  </div>
                  {e.cancelled ? <div style={S.cancelBanner}>{t.cancelled}</div> : null}
                </div>
              </div>
            );
          })}
      </div>
    </div>
  );
}

/* ---------- user portal ---------- */

function UserPortal({ t, lang, setLang, onLogout, wide, userId, profile, setProfile, adminProfile, list, listFor, onAdd, onEdit, onCancel, events, tracks, onTrackEdit, adjustments, onAddAdjust, onRemoveAdjust, rate, words, onAddWords, onEditWord, onRemoveWord }) {
  const [tab, setTab] = useState("schedule");
  const [editing, setEditing] = useState(null);
  const [keep, setKeep] = useState({ date: "", dateTo: "", from: "17:00", to: "18:00" });
  const isTrainer = userId === "trainer";
  const isVocal = userId === "vocalTeacher";
  const isEnglishUser = userId === "englishTeacher";
  const accent = isTrainer ? YELLOW : isVocal ? VIOLET : isEnglishUser ? "#25A244" : PLAIN;
  const isEnglish = userId === "englishTeacher";
  const theme = isVocal ? THEMES.rose : isEnglish ? THEMES.green : THEMES.dark;
  const rights = RIGHTS[userId];
  const types = isTrainer ? TRAINER_TYPES : isVocal ? VOCAL_TYPES : ENGLISH_TYPES;
  const legendTypes = isTrainer
    ? ["sport", "group", "cycle", "run"]
    : isVocal
    ? ["lesson"]
    : ["english", "speaking"];
  const hasEvents = isTrainer || isVocal;
  const tabs = isTrainer
    ? ["schedule", "events", "account"]
    : isVocal
    ? ["schedule", "events", "playlist", "pay", "account"]
    : ["schedule", "dict", "pay", "account"];
  const myEvents = hasEvents
    ? (events || []).filter((e) => !e.owner || e.owner === "all" || e.owner === userId)
    : [];

  return (
    <div style={{ ...S.page, ...theme }}>
      <LangBar
        lang={lang}
        setLang={setLang}
        accent={accent}
        onLogout={onLogout}
        note={
          tab === "schedule" ? (isVocal ? "Студія сольного та хорового співу" : isEnglishUser ? "lessons" : null) : null
        }
        noteStyle={
          isVocal
            ? { color: "#111111", fontWeight: 600 }
            : isEnglishUser
            ? { color: "#111111", fontWeight: 600 }
            : undefined
        }
      />

      <div style={{ ...S.body, maxWidth: wide ? 900 : "100%" }}>
        {tab === "schedule" && (
          <div style={wide && (rights.add || rights.edit) ? S.twoCol : undefined}>
            <div>
              <CalendarView
                t={t}
                list={list}
                events={myEvents}
                accent={accent}
                wide={wide}
                legendTypes={legendTypes}
                brand={isTrainer ? "REFORMA" : isVocal ? "КРИЛА" : isEnglishUser ? "ENGLISH" : null}
                countLabel={isVocal || isEnglishUser ? t.lessonsMonth : undefined}
                showEvents={!isVocal && !isEnglishUser}
                dayHeadColor={isVocal ? VIOLET : isEnglishUser ? "#14622C" : undefined}
                dayPanelStyle={
                  isVocal
                    ? { backgroundColor: "#FFFFFF", border: "1px solid #DDDDE1" }
                    : isEnglishUser
                    ? { backgroundColor: "#EDF6EF", border: "1px solid #DCEBDF" }
                    : undefined
                }
                brandStyle={
                  isVocal
                    ? {
                        fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
                        fontWeight: "bold",
                        fontSize: 30,
                        letterSpacing: "0px",
                        color: VIOLET,
                        textShadow: "none",
                      }
                    : isEnglishUser
                    ? { color: "#111111", textShadow: "none" }
                    : undefined
                }
                brandSub={
                  isTrainer || isVocal || isEnglishUser
                    ? [profile.firstName, profile.lastName].filter(Boolean).join(" ")
                    : null
                }
              />
              <EntryList
                t={t}
                list={list}
                rights={rights}
                onCancel={onCancel}
                onEdit={rights.edit ? (e) => setEditing(e) : undefined}
              />
            </div>
            {rights.add || rights.edit ? (
              <div>
                {editing ? (
                  <EntryEditor
                    t={t}
                    entry={editing}
                    onClose={() => setEditing(null)}
                    onSave={(next) => {
                      onEdit(next);
                      setEditing(null);
                    }}
                  />
                ) : !rights.add ? null : (
                  <EntryForm
                    t={t}
                    types={types}
                    onAdd={onAdd}
                    titleLabel={t.titleTeacher}
                    presetOnly={isEnglishUser}
                    lockLabel={isEnglishUser}
                    keep={keep}
                    setKeep={setKeep}
                    platform={isEnglishUser ? profile.platform : undefined}
                  />
                )}
              </div>
            ) : null}
          </div>
        )}

        {tab === "all" && <SharedCalendar t={t} listFor={listFor} events={events} accent={accent} wide={wide} />}

        {tab === "events" && <EventsView t={t} events={myEvents} wide={wide} color={isVocal ? ICE : undefined} />}

        {tab === "playlist" && (
          <PlaylistView
            t={t}
            tracks={tracks || []}
            accent={accent}
            wide={wide}
            canProgress
            onEdit={onTrackEdit}
          />
        )}

        {tab === "pay" && (
          <PayView
            t={t}
            userId={userId}
            list={list}
            adjustments={adjustments}
            accent={accent}
            rate={rate || 0}
            who={userId}
            onAddAdjust={onAddAdjust}
            onRemoveAdjust={onRemoveAdjust}
          />
        )}

        {tab === "account" && (
          <div style={wide ? S.twoCol : undefined}>
            <AccountView
              t={t}
              userId={userId}
              profile={profile}
              setProfile={setProfile}
              canEdit={!profile.locked}
              accent={accent}
            />
            <AdminCard t={t} adminProfile={adminProfile} accent={accent} />
          </div>
        )}

        {tab === "dict" && (
          <DictionaryView
            t={t}
            words={words || []}
            lessons={(list || []).filter((e) => ["english", "speaking"].includes(e.type))}
            accent={accent}
            wide={wide}
            onAdd={onAddWords}
            onEdit={onEditWord}
            onRemove={onRemoveWord}
          />
        )}

      </div>

      <TabBar
        t={t}
        tab={tab}
        setTab={setTab}
        tabs={tabs}
        accent={isEnglish ? "#1E8C3A" : accent}
        barStyle={
          isVocal
            ? { backgroundColor: "#FFFFFF", borderTop: "1px solid #F0E4EC" }
            : isEnglish
            ? { backgroundColor: "#FFFFFF", borderTop: "1px solid #D9EFDF" }
            : undefined
        }
        inactiveColor={isVocal ? "#A78BE0" : isEnglish ? "#7FA98C" : undefined}
      />
    </div>
  );
}

function AdminCard({ t, adminProfile, accent }) {
  const initial = (adminProfile.name || "").trim().slice(0, 1).toUpperCase();
  const p = adminProfile.avatarPos || { x: 0, y: 0 };
  return (
    <div style={{ ...S.adminCard, borderColor: accent }}>
      <div style={{ ...S.adminAvatar, borderColor: accent }}>
        {adminProfile.avatar ? (
          <img
            src={adminProfile.avatar}
            alt="admin"
            style={{
              ...S.avatarImg,
              transform: `translate(${p.x}px, ${p.y}px) scale(${adminProfile.avatarZoom || 1})`,
            }}
          />
        ) : initial ? (
          <span style={{ ...S.avatarInitial, color: accent }}>{initial}</span>
        ) : (
          <ProfileIcon color={accent} />
        )}
      </div>
      <div>
        <div style={S.adminNameText}>{adminProfile.name || "—"}</div>
        <div style={{ ...S.adminBadge, backgroundColor: accent, color: "var(--bg)" }}>{t.adminBadge}</div>
      </div>
    </div>
  );
}

/* ---------- events ---------- */

function EventsView({ t, events, wide, color }) {
  if (!events || events.length === 0) {
    return (
      <div style={S.emptyState}>
        <p style={S.emptyTitle}>{t.noEvents}</p>
        <p style={S.emptyHint}>{t.eventsHint}</p>
      </div>
    );
  }

  const sorted = [...events].sort((a, b) => (a.date > b.date ? 1 : -1));

  return (
    <div style={wide ? S.twoCol : undefined}>
      {sorted.map((e) => (
        <EventCard key={e.id} t={t} e={e} color={color} />
      ))}
    </div>
  );
}

function resolveImage(src) {
  return src === SPARTAN_MARK ? SPARTAN_IMG : src;
}

function EventCard({ t, e, onRemove, onEdit, ownerLabel, color }) {
  const C = color || ACT.event.color;
  return (
    <div style={S.spartanCard}>
      {e.image ? (
        <div style={S.spartanImgWrap}>
          <img src={resolveImage(e.image)} alt={e.title} style={S.spartanImg} />
          <div style={{ ...S.spartanRibbon, backgroundColor: C }}>{e.title}</div>
        </div>
      ) : null}

      <div style={S.spartanBody}>
        <div style={S.entryTop}>
          <span style={{ ...S.legendDot, backgroundColor: C }} />
          <span style={S.entryDate}>{e.date}</span>
          {ownerLabel ? <span style={S.ownerTag}>{ownerLabel}</span> : null}
        </div>
        {!e.image ? <div style={S.entryTitle}>{e.title}</div> : null}
        {e.place ? (
          <a href={mapsUrl(e.place)} target="_blank" rel="noreferrer" style={{ ...S.mapLink, color: C }}>
            <PinIcon color={C} />
            <span>{e.place}</span>
          </a>
        ) : null}
      </div>

      {onEdit || onRemove ? (
        <div style={S.cardActions}>
          {onEdit ? (
            <button onClick={onEdit} style={S.iconBtn}>
              <EditIcon color="var(--muted)" />
            </button>
          ) : null}
          {onRemove ? (
            <button onClick={() => onRemove(e.id)} style={S.iconBtn}>
              <TrashIcon color="#e0607a" />
            </button>
          ) : null}
        </div>
      ) : null}
    </div>
  );
}

/* ---------- account ---------- */

function AccountView({ t, userId, profile, setProfile, canEdit, accent, isAdmin }) {
  const A = accent || YELLOW;
  const [draft, setDraft] = useState(profile);
  const [msg, setMsg] = useState("");
  const [pwMsg, setPwMsg] = useState("");
  const [pwErr, setPwErr] = useState("");
  const [pwBusy, setPwBusy] = useState(false);
  const [showPw, setShowPw] = useState(false);

  const needsCard = userId === "englishTeacher" || userId === "vocalTeacher";

  useEffect(() => {
    setDraft(profile);
    setPwMsg("");
    setPwErr("");
    setShowPw(false);
  }, [profile]);

  const set = (field, value) => setDraft({ ...draft, [field]: value });

  const save = () => {
    const shouldLock = profile.locked ? true : Boolean(draft.firstName && draft.lastName);
    setProfile({ ...draft, locked: shouldLock });
    setMsg(t.saved);
    setTimeout(() => setMsg(""), 1800);
  };

  const savePassword = async () => {
    const value = (draft.password || "").trim();
    if (!value) return;
    setPwBusy(true);
    setPwMsg("");
    setPwErr("");

    // Без email немає до якого акаунта прив'язати пароль — отже, і входити
    // з ним нікуди. Не робимо вигляд, що все збережено.
    const mail = (draft.email || "").trim().toLowerCase();
    if (!mail) {
      setPwErr(t.passwordNoAccount);
      setPwBusy(false);
      return;
    }

    try {
      await api("/admin/set-password", {
        method: "POST",
        body: { email: mail, role: userId, password: value },
      });
      // Тільки після підтвердження сервера кладемо пароль у спільний стан —
      // так у картці завжди той пароль, яким реально можна увійти.
      setProfile({ ...profile, password: value });
      setPwMsg(t.passwordSaved);
      setTimeout(() => setPwMsg(""), 2600);
    } catch (e) {
      setPwErr(e.code === "not_found" || e.status === 404 ? t.passwordNoAccount : t.passwordLocalOnly);
    } finally {
      setPwBusy(false);
    }
  };

  return (
    <div style={S.accountWrap}>
      <AvatarPicker
        t={t}
        value={draft.avatar}
        zoom={draft.avatarZoom}
        position={draft.avatarPos}
        name={draft.firstName}
        onChange={(v) => setDraft({ ...draft, avatar: v })}
        onZoom={(z) => setDraft({ ...draft, avatarZoom: z })}
        onPos={(p) => setDraft({ ...draft, avatarPos: p })}
        onPick={(v) => setDraft({ ...draft, avatar: v, avatarPos: { x: 0, y: 0 } })}
        onRemove={() => {
          const next = { ...draft, avatar: null, avatarZoom: 1, avatarPos: { x: 0, y: 0 } };
          setDraft(next);
          setProfile(next);
        }}
        onSave={() => setProfile(draft)}
        disabled={!canEdit}
        accent={A}
      />

      {!canEdit ? <div style={S.lockedNote}>{t.locked}</div> : null}

      <Field label={t.firstName} value={draft.firstName} onChange={(v) => set("firstName", v)} disabled={!canEdit} />
      <Field label={t.lastName} value={draft.lastName} onChange={(v) => set("lastName", v)} disabled={!canEdit} />
      <PhoneField t={t} value={draft.phone} onChange={(v) => set("phone", v)} disabled={!canEdit} />
      <Field label={t.email} value={draft.email} onChange={(v) => set("email", v)} disabled={!canEdit} type="email" />
      <Field label={t.birth} value={draft.birth} onChange={(v) => set("birth", v)} disabled={!canEdit} type="date" />

      {isAdmin ? (
        <div style={S.fieldWrap}>
          <label style={S.fieldLabel}>{t.newPassword}</label>
          <div style={S.pwRow}>
            <input
              type={showPw ? "text" : "password"}
              value={draft.password || ""}
              onChange={(e) => set("password", e.target.value)}
              placeholder={t.passwordPh}
              style={{ ...S.fieldInput, flex: 1 }}
              autoComplete="off"
            />
            <button
              type="button"
              onClick={() => setShowPw(!showPw)}
              style={S.eyeBtn}
              aria-label="toggle password visibility"
            >
              {showPw ? <EyeOffIcon color="var(--muted)" /> : <EyeIcon color="var(--muted)" />}
            </button>
          </div>
          <p style={S.pinchHint}>{t.passwordHint}</p>
          <button
            onClick={savePassword}
            disabled={pwBusy || !(draft.password || "").trim()}
            style={{ ...S.ghostBtn, opacity: pwBusy || !(draft.password || "").trim() ? 0.6 : 1 }}
          >
            {t.setPassword}
          </button>
          {pwMsg ? <p style={{ ...S.savedMsg, color: A }}>{pwMsg}</p> : null}
          {pwErr ? <p style={{ ...S.savedMsg, color: RED }}>{pwErr}</p> : null}
        </div>
      ) : null}

      {userId === "englishTeacher" ? (
        <div style={S.fieldWrap}>
          <label style={S.fieldLabel}>{t.platform}</label>
          <div style={S.pickRow}>
            <PickCard
              active={draft.platform === "zoom"}
              disabled={!canEdit}
              accent={A}
              onClick={() => canEdit && set("platform", draft.platform === "zoom" ? "" : "zoom")}
              icon={<ZoomMark />}
              label="Zoom"
            />
            <PickCard
              active={draft.platform === "meet"}
              disabled={!canEdit}
              accent={A}
              onClick={() => canEdit && set("platform", draft.platform === "meet" ? "" : "meet")}
              icon={<MeetMark />}
              label="Google Meet"
            />
          </div>
        </div>
      ) : null}

      {needsCard ? (
        <>
          <CardField
            t={t}
            value={draft.card}
            onChange={(v) => setDraft({ ...draft, card: v, paySystem: detectPaySystem(v) || draft.paySystem })}
            disabled={!canEdit}
          />

          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.paySystem}</label>
            <div style={S.pickRow}>
              <PickCard active={draft.paySystem === "visa"} accent={A} icon={<VisaMark />} label="Visa" />
              <PickCard
                active={draft.paySystem === "mastercard"}
                accent={A}
                icon={<MasterMark />}
                label="Mastercard"
              />
            </div>
          </div>

          <div style={S.fieldWrap}>
            <label style={S.fieldLabel}>{t.bank}</label>
            <div style={S.pickRow}>
              <PickCard
                active={draft.bank === "privat"}
                disabled={!canEdit}
                accent={A}
                onClick={() => canEdit && set("bank", draft.bank === "privat" ? "" : "privat")}
                icon={<PrivatMark />}
                label="ПриватБанк"
              />
              <PickCard
                active={draft.bank === "mono"}
                disabled={!canEdit}
                accent={A}
                onClick={() => canEdit && set("bank", draft.bank === "mono" ? "" : "mono")}
                icon={<MonoMark />}
                label="monobank"
              />
            </div>
          </div>
        </>
      ) : null}

      {canEdit ? (
        <button onClick={save} style={{ ...S.primaryBtn, backgroundColor: A, color: "var(--bg)" }}>
          {t.save}
        </button>
      ) : null}
      {msg ? <p style={{ ...S.savedMsg, color: A }}>{msg}</p> : null}
    </div>
  );
}

function AvatarPicker({ t, value, zoom, onChange, onZoom, onRemove, onSave, disabled, accent, name, position, onPos, onPick }) {
  const [savedMsg, setSavedMsg] = useState(false);
  const drag = useRef({ mode: null, dist: 0, zoomStart: 1, startX: 0, startY: 0, posStartX: 0, posStartY: 0 });

  const pick = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const data = await compressImage(file, 320, 0.75);
    if (onPick) {
      onPick(data);
    } else {
      onChange(data);
      if (onPos) onPos({ x: 0, y: 0 });
    }
    setSavedMsg(false);
    e.target.value = "";
  };

  const doSave = () => {
    if (onSave) onSave();
    setSavedMsg(true);
    setTimeout(() => setSavedMsg(false), 1800);
  };

  const z = zoom || 1;
  const pos = position || { x: 0, y: 0 };
  const initial = (name || "").trim().slice(0, 1).toUpperCase();

  const clampPos = (v, zz) => {
    const max = 15 + 44 * (zz - 1);
    return Math.max(-max, Math.min(max, v));
  };

  const touchDist = (touches) => {
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    return Math.sqrt(dx * dx + dy * dy);
  };

  const setPos = (x, y) => onPos && onPos({ x: clampPos(x, z), y: clampPos(y, z) });

  const onTouchStart = (e) => {
    if (disabled || !value) return;
    if (e.touches.length === 2) {
      drag.current.mode = "pinch";
      drag.current.dist = touchDist(e.touches);
      drag.current.zoomStart = z;
    } else if (e.touches.length === 1) {
      drag.current.mode = "pan";
      drag.current.startX = e.touches[0].clientX;
      drag.current.startY = e.touches[0].clientY;
      drag.current.posStartX = pos.x;
      drag.current.posStartY = pos.y;
    }
  };

  const onTouchMove = (e) => {
    if (disabled || !value) return;
    if (drag.current.mode === "pinch" && e.touches.length === 2) {
      e.preventDefault();
      const next = touchDist(e.touches);
      const scale = next / drag.current.dist;
      const nz = Math.min(2.5, Math.max(1, drag.current.zoomStart * scale));
      onZoom(Number(nz.toFixed(2)));
    } else if (drag.current.mode === "pan" && e.touches.length === 1) {
      e.preventDefault();
      const dx = e.touches[0].clientX - drag.current.startX;
      const dy = e.touches[0].clientY - drag.current.startY;
      setPos(drag.current.posStartX + dx, drag.current.posStartY + dy);
    }
  };

  const onTouchEnd = (e) => {
    if (e.touches.length === 0) {
      drag.current.mode = null;
    } else if (e.touches.length === 1) {
      drag.current.mode = "pan";
      drag.current.startX = e.touches[0].clientX;
      drag.current.startY = e.touches[0].clientY;
      drag.current.posStartX = pos.x;
      drag.current.posStartY = pos.y;
    }
  };

  const onMouseMove = (e) => {
    if (drag.current.mode !== "mouse") return;
    const dx = e.clientX - drag.current.startX;
    const dy = e.clientY - drag.current.startY;
    setPos(drag.current.posStartX + dx, drag.current.posStartY + dy);
  };

  const onMouseUp = () => {
    drag.current.mode = null;
    window.removeEventListener("mousemove", onMouseMove);
    window.removeEventListener("mouseup", onMouseUp);
  };

  const onMouseDown = (e) => {
    if (disabled || !value) return;
    e.preventDefault();
    drag.current.mode = "mouse";
    drag.current.startX = e.clientX;
    drag.current.startY = e.clientY;
    drag.current.posStartX = pos.x;
    drag.current.posStartY = pos.y;
    window.addEventListener("mousemove", onMouseMove);
    window.addEventListener("mouseup", onMouseUp);
  };

  return (
    <div style={S.avatarBox}>
      <div
        style={{
          ...S.avatar,
          borderColor: accent,
          touchAction: value && !disabled ? "none" : "auto",
          cursor: value && !disabled ? "grab" : "default",
        }}
        onTouchStart={onTouchStart}
        onTouchMove={onTouchMove}
        onTouchEnd={onTouchEnd}
        onMouseDown={onMouseDown}
      >
        {value ? (
          <img
            src={value}
            alt="avatar"
            draggable={false}
            style={{ ...S.avatarImg, transform: `translate(${pos.x}px, ${pos.y}px) scale(${z})` }}
          />
        ) : initial ? (
          <span style={{ ...S.avatarInitial, color: accent }}>{initial}</span>
        ) : (
          <span style={{ ...S.avatarPlus, color: accent }}>+</span>
        )}
      </div>

      {!disabled ? (
        <>
          {value ? (
            <div style={S.zoomRow}>
              <span style={S.zoomLabel}>{t.photoZoom}</span>
              <input
                type="range"
                min="1"
                max="2.5"
                step="0.05"
                value={z}
                onChange={(e) => onZoom(Number(e.target.value))}
                style={{ ...S.zoomInput, accentColor: accent }}
              />
            </div>
          ) : null}
          {value ? <p style={S.pinchHint}>{t.pinchHint}</p> : null}

          <div style={S.avatarBtns}>
            <label style={{ ...S.ghostBtn, cursor: "pointer" }}>
              {value ? t.photoReplace : t.photo}
              <input type="file" accept="image/*" onChange={pick} style={{ display: "none" }} />
            </label>
            {value ? (
              <button
                onClick={() => {
                  if (onRemove) {
                    onRemove();
                  } else {
                    onChange(null);
                    onZoom(1);
                    if (onPos) onPos({ x: 0, y: 0 });
                  }
                }}
                style={{ ...S.ghostBtn, color: "#c0392b", borderColor: "#e8c6c1" }}
              >
                {t.photoRemove}
              </button>
            ) : null}
            {value && onSave ? (
              <button onClick={doSave} style={{ ...S.ghostBtn, backgroundColor: accent, color: "var(--bg)" }}>
                {t.photoSave}
              </button>
            ) : null}
          </div>
          {savedMsg ? <p style={{ ...S.savedMsg, color: accent }}>{t.photoSaved}</p> : null}
        </>
      ) : null}
    </div>
  );
}

function PickCard({ active, disabled, accent, onClick, icon, label }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        ...S.pickBtn,
        borderColor: active ? accent : "var(--line)",
        boxShadow: active ? `0 0 0 1px ${accent}` : "none",
        opacity: disabled ? 0.55 : 1,
      }}
    >
      <span style={S.pickIcon}>{icon}</span>
      <span style={S.pickLabel}>{label}</span>
    </button>
  );
}

function CardField({ t, value, onChange, disabled }) {
  return (
    <div style={S.fieldWrap}>
      <label style={S.fieldLabel}>{t.card}</label>
      <input
        type="text"
        inputMode="numeric"
        value={formatCard(value || "")}
        disabled={disabled}
        placeholder="0000 0000 0000 0000"
        onChange={(e) => onChange(e.target.value.replace(/\D/g, "").slice(0, 16))}
        style={{ ...S.fieldInput, letterSpacing: "1.5px", opacity: disabled ? 0.55 : 1 }}
      />
      <div style={S.hint}>{t.cardHint}</div>
    </div>
  );
}

function PhoneField({ t, value, onChange, disabled }) {
  return (
    <div style={S.fieldWrap}>
      <label style={S.fieldLabel}>{t.phone}</label>
      <div style={{ ...S.phoneWrap, opacity: disabled ? 0.55 : 1 }}>
        <span style={S.phonePrefix}>+38</span>
        <input
          type="tel"
          inputMode="numeric"
          value={value || ""}
          disabled={disabled}
          onChange={(e) => onChange(e.target.value.replace(/\D/g, "").slice(0, 10))}
          placeholder="0XXXXXXXXX"
          style={S.phoneInput}
        />
      </div>
      <div style={S.hint}>{t.phoneHint}</div>
    </div>
  );
}

function Field({ label, value, onChange, disabled, type, placeholder }) {
  return (
    <div style={S.fieldWrap}>
      <label style={S.fieldLabel}>{label}</label>
      <input
        type={type || "text"}
        value={value || ""}
        disabled={disabled}
        placeholder={placeholder}
        onChange={(e) => onChange(e.target.value)}
        style={{ ...S.fieldInput, opacity: disabled ? 0.55 : 1 }}
      />
    </div>
  );
}

function googleUrl(q) {
  return "https://www.google.com/search?q=" + encodeURIComponent(q);
}

function PlaylistView({ t, tracks, accent, wide, onAdd, onEdit, onRemove, canProgress }) {
  const A = accent;
  const [creating, setCreating] = useState(false);
  const [editing, setEditing] = useState(null);
  const [eventEditing, setEventEditing] = useState(null);
  const [view, setView] = useState("work");

  const editable = Boolean(onAdd);
  const shown = tracks.filter((tr) => (view === "done" ? tr.done : !tr.done));

  return (
    <div>
      <div style={{ ...S.ownerRow, marginTop: 18, marginBottom: 14 }}>
        {[
          ["work", t.inWork],
          ["done", t.doneTab],
        ].map(([id, label]) => {
          const on = view === id;
          return (
            <button
              key={id}
              onClick={() => setView(id)}
              style={{
                ...S.switchBtn,
                backgroundColor: on ? A : "transparent",
                color: on ? "#fff" : "var(--muted)",
                borderColor: on ? A : "var(--line)",
              }}
            >
              {label}
            </button>
          );
        })}
      </div>

      <div style={S.plannedHead}>
        {t.playlist} · {shown.length}
      </div>

      {shown.length === 0 ? (
        <div style={S.emptyState}>
          <p style={S.emptyTitle}>{view === "done" ? t.noDone : t.noTracks}</p>
        </div>
      ) : null}

      <div style={{ ...(wide ? S.twoCol : {}), paddingBottom: editable ? 70 : 0 }}>
        {shown.map((tr) => (
          <div key={tr.id} style={{ ...S.trackCard, opacity: tr.done ? 0.75 : 1 }}>
            <div style={S.trackCover}>
              {tr.cover ? <img src={tr.cover} alt="" style={S.avatarImg} /> : <MusicIcon color={A} />}
            </div>

            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ ...S.trackTitle, textDecoration: tr.done ? "line-through" : "none" }}>
                {tr.title}
              </div>
              <div style={S.trackArtist}>{tr.artist}</div>
              {tr.event ? (
                <div style={{ ...S.eventTag, borderColor: A, color: A }}>{tr.event}</div>
              ) : null}

              <div style={S.trackLinks}>
                {tr.link ? (
                  <a href={tr.link} target="_blank" rel="noreferrer" style={{ ...S.trackLink, color: A }}>
                    {t.open}
                  </a>
                ) : null}
                <a
                  href={googleUrl(`${tr.title} ${tr.artist}`)}
                  target="_blank"
                  rel="noreferrer"
                  style={{ ...S.trackLink, color: "var(--muted)" }}
                >
                  {t.searchGoogle}
                </a>
              </div>
            </div>

            {canProgress || editable ? (
              <div style={S.entryActions}>
                {canProgress ? (
                  <button
                    onClick={() => onEdit({ ...tr, done: !tr.done })}
                    style={S.iconBtn}
                    title={tr.done ? t.markBack : t.markDone}
                  >
                    {tr.done ? <UndoIcon color="var(--muted)" /> : <CheckIcon color={A} />}
                  </button>
                ) : null}
                {canProgress && !editable ? (
                  <button onClick={() => setEventEditing(tr)} style={S.iconBtn}>
                    <EditIcon color="var(--muted)" />
                  </button>
                ) : null}
                {editable ? (
                  <button onClick={() => setEditing(tr)} style={S.iconBtn}>
                    <EditIcon color="var(--muted)" />
                  </button>
                ) : null}
                {editable ? (
                  <button onClick={() => onRemove(tr.id)} style={S.iconBtn}>
                    <TrashIcon color="#e0607a" />
                  </button>
                ) : null}
              </div>
            ) : null}
          </div>
        ))}
      </div>

      {editable ? (
        <button onClick={() => setCreating(true)} style={{ ...S.fabBtn, backgroundColor: A }}>
          + {t.addTrack}
        </button>
      ) : null}

      {creating ? (
        <Modal title={t.newTrack} onClose={() => setCreating(false)}>
          <TrackForm
            t={t}
            accent={A}
            onSubmit={(tr) => {
              onAdd(tr);
              setCreating(false);
            }}
            submitLabel={"+ " + t.addTrack}
          />
        </Modal>
      ) : null}

      {editing ? (
        <Modal title={t.edit} onClose={() => setEditing(null)}>
          <TrackForm
            t={t}
            accent={A}
            initial={editing}
            onSubmit={(tr) => {
              onEdit(tr);
              setEditing(null);
            }}
            submitLabel={t.saveEdit}
          />
        </Modal>
      ) : null}

      {eventEditing ? (
        <Modal title={t.forEvent} onClose={() => setEventEditing(null)}>
          <EventTagForm
            t={t}
            accent={A}
            track={eventEditing}
            onSave={(tr) => {
              onEdit(tr);
              setEventEditing(null);
            }}
          />
        </Modal>
      ) : null}
    </div>
  );
}

function EventTagForm({ t, track, onSave, accent }) {
  const [value, setValue] = useState(track.event || "");
  return (
    <div>
      <Field label={t.forEvent} value={value} onChange={setValue} placeholder={t.forEventPh} />
      <button
        onClick={() => onSave({ ...track, event: value.trim() })}
        style={{ ...S.primaryBtn, backgroundColor: accent, color: "#fff" }}
      >
        {t.saveEdit}
      </button>
    </div>
  );
}

function TrackForm({ t, initial, onSubmit, submitLabel, accent }) {
  const [draft, setDraft] = useState(
    initial || { title: "", artist: "", link: "", cover: null, event: "", done: false }
  );
  const set = (k, v) => setDraft({ ...draft, [k]: v });

  const pick = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const data = await compressImage(file, 400, 0.75);
    set("cover", data);
    e.target.value = "";
  };

  return (
    <div>
      <div style={S.coverWrap}>
        {draft.cover ? (
          <img src={draft.cover} alt="" style={S.coverImg} />
        ) : (
          <span style={S.coverEmpty}>{t.trackCover}</span>
        )}
      </div>

      <div style={S.photoBtns}>
        <label style={{ ...S.ghostBtn, cursor: "pointer" }}>
          {t.uploadPhoto}
          <input type="file" accept="image/*" onChange={pick} style={{ display: "none" }} />
        </label>
        {draft.cover ? (
          <button
            onClick={() => set("cover", null)}
            style={{ ...S.ghostBtn, color: "#c0392b", borderColor: "#e8c6c1" }}
          >
            {t.photoRemove}
          </button>
        ) : null}
      </div>

      <Field label={t.trackTitle} value={draft.title} onChange={(v) => set("title", v)} />
      <Field label={t.trackArtist} value={draft.artist} onChange={(v) => set("artist", v)} />
      <Field label={t.trackLink} value={draft.link} onChange={(v) => set("link", v)} placeholder="https://" />
      <Field label={t.forEvent} value={draft.event} onChange={(v) => set("event", v)} placeholder={t.forEventPh} />

      {draft.title || draft.artist ? (
        <a
          href={googleUrl(`${draft.title} ${draft.artist}`)}
          target="_blank"
          rel="noreferrer"
          style={{ ...S.ghostBtn, display: "inline-block", textAlign: "center", marginBottom: 12 }}
        >
          {t.searchGoogle}
        </a>
      ) : null}

      <button
        onClick={() => {
          if (!draft.title.trim()) return;
          onSubmit({ ...draft, id: draft.id || Date.now() + "-" + Math.random().toString(36).slice(2, 7) });
        }}
        style={{ ...S.primaryBtn, backgroundColor: accent, color: "#fff" }}
      >
        {submitLabel}
      </button>
    </div>
  );
}

function isPast(entry) {
  if (!entry.date) return false;
  const end = entry.to || "23:59";
  const dt = new Date(`${entry.date}T${end}:00`);
  if (isNaN(dt)) return false;
  return dt.getTime() <= Date.now();
}

function stampText(t, ms, by) {
  if (!ms) return "";
  const d = new Date(ms);
  const date = `${String(d.getDate()).padStart(2, "0")}.${String(d.getMonth() + 1).padStart(2, "0")}.${d.getFullYear()}`;
  const time = `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
  const who = by ? ` · ${by === "admin" ? t.admin2 : t.names[by] || by}` : "";
  return `${date} ${t.at} ${time}${who}`;
}

function PayView({ t, userId, list, adjustments, accent, rate, onAddAdjust, onRemoveAdjust, onRate, who }) {
  const A = accent;
  const [adding, setAdding] = useState(false);
  const [rateEdit, setRateEdit] = useState(false);

  const rateLabel = userId === "vocalTeacher" ? t.rateClass : t.rateLesson;

  const lessons = (list || []).filter((e) => PAY_TYPES.includes(e.type) && !e.auto);

  const held = lessons.filter((e) => !e.cancelled && isPast(e));
  const planned = lessons.filter((e) => !e.cancelled && !isPast(e));
  const cancelled = lessons.filter((e) => e.cancelled);

  // Проведене заняття списується з балансу, а не додається.
  const spent = held.length * rate;
  const adjustTotal = (adjustments || []).reduce((sum, a) => sum + Number(a.amount || 0), 0);
  const balance = adjustTotal - spent;

  const rows = [];
  lessons.forEach((e) => {
    rows.push({
      id: "e-" + e.id,
      date: e.date,
      time: e.from,
      title: e.title || t[e.type],
      amount: e.cancelled ? 0 : isPast(e) ? -rate : null,
      state: e.cancelled ? "cancelled" : isPast(e) ? "held" : "planned",
      stamp: e.cancelled ? stampText(t, e.cancelledAt, e.cancelledBy) : "",
    });
  });
  (adjustments || []).forEach((a) => {
    rows.push({
      id: "a-" + a.id,
      date: a.date,
      title: a.note || t.adjust,
      amount: Number(a.amount || 0),
      state: "adjust",
      stamp: stampText(t, a.at, a.by),
      raw: a,
    });
  });

  rows.sort((x, y) => (x.date > y.date ? -1 : 1));

  return (
    <div style={{ paddingBottom: onAddAdjust ? 70 : 0 }}>
      <div style={{ ...S.balanceCard, borderColor: A }}>
        <div style={S.balanceLabel}>{t.balance}</div>
        <div style={{ ...S.balanceValue, color: A }}>{balance} ₴</div>

        {onRate ? (
          <button onClick={() => setRateEdit(true)} style={{ ...S.rateBtn, borderColor: A, color: A }}>
            {rateLabel}: {rate} ₴ · {t.editRate}
          </button>
        ) : (
          <div style={S.balanceHint}>
            {rateLabel}: {rate} ₴
          </div>
        )}
      </div>

      <div style={S.summaryRow}>
        <div style={{ ...S.summaryChip, borderColor: A }}>
          <span style={{ ...S.summaryLabel, color: A }}>{t.held}</span>
          <span style={S.summaryCount}>{held.length}</span>
        </div>
        <div style={{ ...S.summaryChip, borderColor: "var(--line)" }}>
          <span style={S.summaryLabel}>{t.upcoming}</span>
          <span style={S.summaryCount}>{planned.length}</span>
        </div>
        <div style={{ ...S.summaryChip, borderColor: RED }}>
          <span style={{ ...S.summaryLabel, color: RED }}>{t.cancelledN}</span>
          <span style={S.summaryCount}>{cancelled.length}</span>
        </div>
      </div>

      <div style={S.plannedHead}>{t.history}</div>

      {rows.length === 0 ? (
        <div style={S.emptyState}>
          <p style={S.emptyTitle}>{t.noPay}</p>
        </div>
      ) : null}

      {rows.map((r) => {
        const color =
          r.state === "cancelled" ? RED : r.state === "held" ? A : r.state === "adjust" ? A : "var(--line)";
        return (
          <div key={r.id} style={{ ...S.payRow, borderLeftColor: color }}>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={S.payTop}>
                <span style={S.entryDate}>{r.date}</span>
                {r.time ? <span style={S.entryTime}>{r.time}</span> : null}
              </div>
              <div style={{ ...S.payTitle, textDecoration: r.state === "cancelled" ? "line-through" : "none" }}>
                {r.title}
              </div>
              {r.state === "cancelled" ? (
                <div style={{ ...S.entrySub, color: RED }}>
                  {t.cancelledN}
                  {r.stamp ? ` · ${r.stamp}` : ""}
                </div>
              ) : null}
              {r.state === "adjust" && r.stamp ? <div style={S.entrySub}>{r.stamp}</div> : null}
              {r.state === "planned" ? <div style={S.entrySub}>{t.waiting}</div> : null}
            </div>

            <div style={S.payAmountBox}>
              {r.amount === null ? (
                <span style={{ ...S.payAmount, color: "var(--muted)" }}>—</span>
              ) : r.amount === 0 ? (
                <span style={{ ...S.payAmount, color: RED }}>0 ₴</span>
              ) : (
                <span style={{ ...S.payAmount, color: r.amount > 0 ? A : RED }}>
                  {r.amount > 0 ? "+" : ""}
                  {r.amount} ₴
                </span>
              )}
              {onRemoveAdjust && r.state === "adjust" ? (
                <button onClick={() => onRemoveAdjust(r.raw.id)} style={S.iconBtn}>
                  <TrashIcon color="#e0607a" />
                </button>
              ) : null}
            </div>
          </div>
        );
      })}

      {onAddAdjust ? (
        <button onClick={() => setAdding(true)} style={{ ...S.fabBtn, backgroundColor: A }}>
          + {t.addAdjust}
        </button>
      ) : null}

      {adding ? (
        <Modal title={t.addAdjust} onClose={() => setAdding(false)}>
          <AdjustForm
            t={t}
            accent={A}
            onSubmit={(a) => {
              onAddAdjust({ ...a, by: who, at: Date.now() });
              setAdding(false);
            }}
          />
        </Modal>
      ) : null}

      {rateEdit ? (
        <Modal title={rateLabel} onClose={() => setRateEdit(false)}>
          <RateForm
            t={t}
            accent={A}
            value={rate}
            label={rateLabel}
            onSubmit={(v) => {
              onRate(v);
              setRateEdit(false);
            }}
          />
        </Modal>
      ) : null}
    </div>
  );
}

function RateForm({ t, value, label, onSubmit, accent }) {
  const [val, setVal] = useState(String(value || 0));
  return (
    <div>
      <div style={S.fieldWrap}>
        <label style={S.fieldLabel}>{label}</label>
        <input
          type="text"
          inputMode="numeric"
          value={val}
          onChange={(e) => setVal(e.target.value.replace(/[^\d]/g, "").slice(0, 6))}
          style={S.fieldInput}
        />
      </div>
      <button
        onClick={() => onSubmit(Number(val || 0))}
        style={{ ...S.primaryBtn, backgroundColor: accent, color: "#fff" }}
      >
        {t.saveEdit}
      </button>
    </div>
  );
}

function AdjustForm({ t, onSubmit, accent }) {
  const [date, setDate] = useState("");
  const [amount, setAmount] = useState("");
  const [note, setNote] = useState("");

  return (
    <div>
      <Field label={t.eventDate} value={date} onChange={setDate} type="date" />
      <div style={S.fieldWrap}>
        <label style={S.fieldLabel}>{t.amount}</label>
        <input
          type="text"
          inputMode="numeric"
          value={amount}
          placeholder="-500 / +500"
          onChange={(e) => setAmount(e.target.value.replace(/[^\d-]/g, "").slice(0, 8))}
          style={S.fieldInput}
        />
      </div>
      <Field label={t.note} value={note} onChange={setNote} placeholder={t.notePh} />

      <button
        onClick={() => {
          if (!date || !amount) return;
          onSubmit({
            id: Date.now() + "-" + Math.random().toString(36).slice(2, 7),
            date,
            amount: Number(amount),
            note: note.trim(),
          });
        }}
        style={{ ...S.primaryBtn, backgroundColor: accent, color: "#fff" }}
      >
        {t.add}
      </button>
    </div>
  );
}


/* ---------- словник ---------- */

// Урок вважається актуальним до 00:00 наступного дня після заняття.
function lessonStillListed(entry) {
  if (!entry || !entry.date) return false;
  const next = new Date(`${entry.date}T00:00:00`);
  next.setDate(next.getDate() + 1);
  return next.getTime() > Date.now();
}

function lessonTitle(t, e) {
  const time = e.from ? ` ${e.from}` : "";
  return `${e.date}${time} · ${e.label || e.title || t[e.type] || ""}`.trim();
}

function LessonPicker({ t, lessons, value, onChange, accent }) {
  const [past, setPast] = useState(false);

  const active = lessons.filter(lessonStillListed);
  const gone = lessons.filter((e) => !lessonStillListed(e));
  const shown = past ? gone : active;

  return (
    <div style={S.fieldWrap}>
      <label style={S.fieldLabel}>{t.lessonLabel}</label>

      <div style={{ ...S.segRow, marginBottom: 8 }}>
        <button
          onClick={() => setPast(false)}
          style={{
            ...S.segBtn,
            backgroundColor: "transparent",
            borderColor: !past ? accent : "var(--line)",
            color: !past ? accent : "var(--muted)",
            borderWidth: !past ? 2 : 1,
          }}
        >
          {t.activeLessons}
        </button>
        <button
          onClick={() => setPast(true)}
          style={{
            ...S.segBtn,
            backgroundColor: "transparent",
            borderColor: past ? accent : "var(--line)",
            color: past ? accent : "var(--muted)",
            borderWidth: past ? 2 : 1,
          }}
        >
          {t.pastLessons}
        </button>
      </div>

      <select value={value} onChange={(e) => onChange(e.target.value)} style={S.fieldInput}>
        <option value="">{t.noLesson}</option>
        {shown
          .slice()
          .sort((a, b) => (a.date > b.date ? (past ? -1 : 1) : past ? 1 : -1))
          .map((e) => (
            <option key={e.id} value={e.id}>
              {lessonTitle(t, e)}
            </option>
          ))}
      </select>
    </div>
  );
}

function WordsForm({ t, lessons, accent, onSubmit, isRequest }) {
  const [mode, setMode] = useState("one");
  const [lessonId, setLessonId] = useState("");

  const [word, setWord] = useState("");
  const [translation, setTranslation] = useState("");

  const [draft, setDraft] = useState([
    { word: "", translation: "" },
    { word: "", translation: "" },
    { word: "", translation: "" },
  ]);

  const addRow = () => setDraft([...draft, { word: "", translation: "" }]);

  const setDraftAt = (i, field, value) =>
    setDraft(draft.map((x, idx) => (idx === i ? { ...x, [field]: value } : x)));

  const removeDraft = (i) => setDraft(draft.filter((_, idx) => idx !== i));

  const filledCount = draft.filter((x) => x.word.trim()).length;

  const lessonOf = (id) => lessons.find((e) => e.id === id);

  const submitOne = () => {
    if (!word.trim()) return;
    const l = lessonOf(lessonId);
    onSubmit([
      {
        word: word.trim(),
        translation: translation.trim(),
        lessonId: lessonId || "",
        lessonLabel: l ? lessonTitle(t, l) : "",
      },
    ]);
    setWord("");
    setTranslation("");
  };

  const submitMany = () => {
    const rows = draft.filter((x) => x.word.trim());
    if (rows.length === 0) return;
    const l = lessonOf(lessonId);
    onSubmit(
      rows.map((x) => ({
        word: x.word.trim(),
        translation: (x.translation || "").trim(),
        lessonId: lessonId || "",
        lessonLabel: l ? lessonTitle(t, l) : "",
      }))
    );
    setDraft([
      { word: "", translation: "" },
      { word: "", translation: "" },
      { word: "", translation: "" },
    ]);
  };

  return (
    <div>
      <div style={S.segRow}>
        <button
          onClick={() => setMode("one")}
          style={{
            ...S.segBtn,
            backgroundColor: "transparent",
            borderColor: mode === "one" ? accent : "var(--line)",
            color: mode === "one" ? accent : "var(--muted)",
            borderWidth: mode === "one" ? 2 : 1,
          }}
        >
          {t.oneWord}
        </button>
        <button
          onClick={() => setMode("many")}
          style={{
            ...S.segBtn,
            backgroundColor: "transparent",
            borderColor: mode === "many" ? accent : "var(--line)",
            color: mode === "many" ? accent : "var(--muted)",
            borderWidth: mode === "many" ? 2 : 1,
          }}
        >
          {t.manyWords}
        </button>
      </div>

      <LessonPicker t={t} lessons={lessons} value={lessonId} onChange={setLessonId} accent={accent} />

      {mode === "one" ? (
        <>
          <Field label={t.wordLabel} value={word} onChange={setWord} />
          <Field label={t.translationLabel} value={translation} onChange={setTranslation} />
          <button
            onClick={submitOne}
            style={{
              ...S.primaryBtn,
              backgroundColor: accent,
              color: "#fff",
              opacity: word.trim() ? 1 : 0.45,
            }}
            disabled={!word.trim()}
          >
            + {isRequest ? t.sendRequest : t.addWords}
          </button>
        </>
      ) : (
        <>
          <div style={S.wordHeadRow}>
            <span style={S.wordHeadCell}>{t.wordLabel}</span>
            <span style={S.wordHeadCell}>{t.translationLabel}</span>
            <span style={{ width: 30 }} />
          </div>

          {draft.map((x, i) => (
            <div key={i} style={S.wordDraft}>
              <input
                value={x.word}
                onChange={(e) => setDraftAt(i, "word", e.target.value)}
                placeholder={t.wordLabel}
                style={{ ...S.fieldInput, flex: 1, minWidth: 0 }}
              />
              <span style={S.wordDash}>—</span>
              <input
                value={x.translation}
                onChange={(e) => setDraftAt(i, "translation", e.target.value)}
                placeholder={t.translationLabel}
                style={{ ...S.fieldInput, flex: 1, minWidth: 0 }}
              />
              <button
                onClick={() => removeDraft(i)}
                style={{ ...S.iconBtn, opacity: draft.length > 1 ? 1 : 0.3 }}
                disabled={draft.length <= 1}
              >
                <TrashIcon color="#e0607a" />
              </button>
            </div>
          ))}

          <button onClick={addRow} style={{ ...S.ghostBtn, width: "100%", marginTop: 4, marginBottom: 10 }}>
            + {t.addRow}
          </button>

          <button
            onClick={submitMany}
            style={{
              ...S.primaryBtn,
              backgroundColor: accent,
              color: "#fff",
              opacity: filledCount ? 1 : 0.4,
            }}
            disabled={!filledCount}
          >
            + {isRequest ? t.sendRequest : t.addAll}
            {filledCount ? ` · ${filledCount}` : ""}
          </button>
        </>
      )}
    </div>
  );
}

function roleName(t, by) {
  if (by === "admin") return t.roleAdmin;
  if (by === "englishTeacher") return t.roleTeacher;
  return t.names && t.names[by] ? t.names[by] : by || "—";
}

function stampShort(ms) {
  if (!ms) return "";
  const d = new Date(ms);
  const p = (n) => String(n).padStart(2, "0");
  return `${p(d.getDate())}.${p(d.getMonth() + 1)}.${d.getFullYear()} ${p(d.getHours())}:${p(d.getMinutes())}`;
}

function WordCard({ t, w, accent, onOpen, onInfo }) {
  return (
    <div style={{ ...S.wordCard, borderColor: "var(--line)" }}>
      <button
        onClick={(e) => {
          e.stopPropagation();
          onInfo();
        }}
        style={S.wordInfoBtn}
        title={t.addedBy}
      >
        <HelpIcon color="var(--muted)" />
      </button>

      <button onClick={onOpen} style={S.wordBody}>
        <span style={{ ...S.wordTerm, color: accent }}>{w.word}</span>
        <span style={S.wordTr}>{w.translation || "—"}</span>
        {w.lessonLabel ? <span style={S.wordLesson}>{w.lessonLabel}</span> : null}
      </button>
    </div>
  );
}

function DictionaryView({ t, words, lessons, accent, wide, onAdd, onEdit, onRemove, onRequest, onDismiss, isAdmin }) {
  const [adding, setAdding] = useState(false);
  const [open, setOpen] = useState(null);
  const [info, setInfo] = useState(null);
  const [filter, setFilter] = useState("all");
  const [query, setQuery] = useState("");

  const canEdit = Boolean(onAdd);          // вчителька
  const canRequest = Boolean(onRequest);   // адміністратор
  const pending = (words || []).filter((w) => w.pending);

  const lessonIds = [];
  (words || []).forEach((w) => {
    if (w.pending || w.rejected) return;
    if (w.lessonId && !lessonIds.includes(w.lessonId)) lessonIds.push(w.lessonId);
  });

  const noLesson = (words || []).filter((w) => !w.lessonId && !w.pending && !w.rejected);

  const approved = (words || []).filter((w) => !w.pending && !w.rejected);
  const rejected = (words || []).filter((w) => w.rejected);

  const q = query.trim().toLowerCase();

  const shown = approved
    .filter((w) => {
      if (filter === "all") return true;
      if (filter === "none") return !w.lessonId;
      return w.lessonId === filter;
    })
    .filter((w) => {
      if (!q) return true;
      return (
        (w.word || "").toLowerCase().includes(q) ||
        (w.translation || "").toLowerCase().includes(q)
      );
    });

  const labelOf = (id) => {
    const w = (words || []).find((x) => x.lessonId === id && x.lessonLabel);
    return w ? w.lessonLabel : id;
  };

  return (
    <div style={{ paddingBottom: canEdit ? 70 : 0 }}>
      <div style={{ ...S.searchWrap, borderColor: query ? accent : "var(--line)", borderWidth: query ? 2 : 1 }}>
        <SearchIcon color={query ? accent : "var(--muted)"} />
        <input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder={t.searchWord}
          style={S.searchInput}
        />
        {query ? (
          <button onClick={() => setQuery("")} style={S.searchClear}>
            ×
          </button>
        ) : null}
      </div>

      <div style={S.fieldWrap}>
        <label style={S.fieldLabel}>{t.lessonLabel}</label>
        <select value={filter} onChange={(e) => setFilter(e.target.value)} style={S.fieldInput}>
          <option value="all">
            {t.allWords} · {approved.length}
          </option>
          {noLesson.length ? (
            <option value="none">
              {t.noLesson} · {noLesson.length}
            </option>
          ) : null}
          {lessonIds.map((id) => (
            <option key={id} value={id}>
              {labelOf(id)} · {approved.filter((w) => w.lessonId === id).length}
            </option>
          ))}
        </select>
      </div>

      {canEdit && pending.length ? (
        <div style={{ marginBottom: 18 }}>
          <div style={S.plannedHead}>
            {t.requests} · {pending.length}
          </div>
          {pending.map((w) => (
            <div key={w.id} style={{ ...S.pendingCard, borderColor: accent }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ ...S.wordTerm, color: accent }}>{w.word}</div>
                <div style={S.wordTr}>{w.translation || "—"}</div>
                {w.lessonLabel ? <div style={S.wordLesson}>{w.lessonLabel}</div> : null}
                <div style={S.entrySub}>
                  {t.addedBy}: {roleName(t, w.by)} · {stampShort(w.addedAt)}
                </div>
              </div>
              <button
                onClick={() => onEdit({ ...w, pending: false, approvedAt: Date.now() })}
                style={{ ...S.ghostBtn, borderColor: accent, color: accent }}
              >
                {t.approve}
              </button>
              <button
                onClick={() => onEdit({ ...w, pending: false, rejected: true, rejectedAt: Date.now() })}
                style={{ ...S.ghostBtn, color: "#c0392b", borderColor: "#e8c6c1" }}
              >
                {t.reject}
              </button>
            </div>
          ))}
        </div>
      ) : null}

      {canRequest && rejected.length ? (
        <div style={{ marginBottom: 14 }}>
          <div style={S.plannedHead}>
            {t.rejected} · {rejected.length}
          </div>
          {rejected.map((w) => (
            <div key={w.id} style={{ ...S.pendingCard, borderStyle: "solid", borderColor: "#E0A6A0" }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ ...S.wordTerm, color: "#c0392b", textDecoration: "line-through" }}>
                  {w.word}
                </div>
                <div style={S.wordTr}>{w.translation || "—"}</div>
                <div style={S.entrySub}>{t.rejectedHint}</div>
              </div>
              <button
                onClick={() => onDismiss(w.id)}
                style={{ ...S.ghostBtn, borderColor: accent, color: accent }}
              >
                {t.gotIt}
              </button>
            </div>
          ))}
        </div>
      ) : null}

      {canRequest && pending.length ? (
        <div
          style={{
            ...S.lockedNote,
            backgroundColor: "transparent",
            borderColor: accent,
            color: accent,
            fontWeight: 600,
          }}
        >
          {t.pendingSent} · {pending.length}
        </div>
      ) : null}

      <div style={S.plannedHead}>
        {t.dict} · {shown.length} {t.wordsCount}
        {canEdit ? null : <span style={S.plannedHint}> · {t.viewOnlyDict}</span>}
      </div>

      {shown.length === 0 ? (
        <div style={S.emptyState}>
          <p style={S.emptyTitle}>{query ? t.nothingFound : t.dictEmpty}</p>
        </div>
      ) : null}

      <div style={S.wordGrid}>
        {shown.map((w) => (
          <WordCard
            key={w.id}
            t={t}
            w={w}
            accent={accent}
            onOpen={() => setOpen(w)}
            onInfo={() => setInfo(w)}
          />
        ))}
      </div>

      {canEdit || canRequest ? (
        <button onClick={() => setAdding(true)} style={{ ...S.fabBtn, backgroundColor: accent }}>
          + {t.addWords}
        </button>
      ) : null}

      {adding ? (
        <Modal title={t.addWords} onClose={() => setAdding(false)}>
          <WordsForm
            t={t}
            lessons={lessons}
            accent={accent}
            isRequest={!canEdit}
            onSubmit={(rows) => {
              if (canEdit) onAdd(rows);
              else onRequest(rows);
              setAdding(false);
            }}
          />
        </Modal>
      ) : null}

      {info ? (
        <Modal title={t.infoTitle} onClose={() => setInfo(null)}>
          <div style={{ ...S.wordBig, color: accent }}>{info.word}</div>
          <div style={S.wordBigTr}>{info.translation || "—"}</div>
          {info.lessonLabel ? (
            <div style={{ ...S.eventTag, borderColor: accent, color: accent }}>{info.lessonLabel}</div>
          ) : null}
          <div style={{ ...S.entrySub, marginTop: 12 }}>
            {t.addedBy}: {roleName(t, info.by)}
          </div>
          <div style={S.entrySub}>
            {t.addedOn}: {stampShort(info.addedAt)}
          </div>
        </Modal>
      ) : null}

      {open ? (
        <Modal title={open.word} onClose={() => setOpen(null)}>
          <WordDetails
            t={t}
            w={open}
            accent={accent}
            canEdit={canEdit}
            onSave={(next) => {
              onEdit(next);
              setOpen(null);
            }}
            onRemove={() => {
              onRemove(open.id);
              setOpen(null);
            }}
          />
        </Modal>
      ) : null}
    </div>
  );
}

function WordDetails({ t, w, accent, canEdit, onSave, onRemove }) {
  const [draft, setDraft] = useState(w);
  const set = (k, v) => setDraft({ ...draft, [k]: v });

  if (!canEdit) {
    return (
      <div>
        <div style={{ ...S.wordBig, color: accent }}>{w.word}</div>
        <div style={S.wordBigTr}>{w.translation || "—"}</div>
        {w.lessonLabel ? (
          <div style={{ ...S.eventTag, borderColor: accent, color: accent }}>{w.lessonLabel}</div>
        ) : null}
        {w.addedAt ? (
          <div style={{ ...S.entrySub, marginTop: 10 }}>
            {t.addedOn}: {new Date(w.addedAt).toLocaleDateString()}
          </div>
        ) : null}
      </div>
    );
  }

  return (
    <div>
      <Field label={t.wordLabel} value={draft.word} onChange={(v) => set("word", v)} />
      <Field label={t.translationLabel} value={draft.translation} onChange={(v) => set("translation", v)} />
      {draft.lessonLabel ? (
        <div style={{ ...S.eventTag, borderColor: accent, color: accent, marginBottom: 12 }}>
          {draft.lessonLabel}
        </div>
      ) : null}

      <button onClick={() => onSave(draft)} style={{ ...S.primaryBtn, backgroundColor: accent, color: "#fff" }}>
        {t.saveEdit}
      </button>
      <button
        onClick={onRemove}
        style={{ ...S.ghostBtn, width: "100%", marginTop: 8, color: "#c0392b", borderColor: "#e8c6c1" }}
      >
        {t.del}
      </button>
    </div>
  );
}


/* ---------- admin ---------- */

function AdminPanel({
  t,
  lang,
  setLang,
  wide,
  profiles,
  setProfiles,
  adminProfile,
  setAdminProfile,
  entries,
  setEntries,
  listFor,
  addEntry,
  updateEntry,
  removeEntry,
  toggleCancel,
  events,
  setEvents,
  tracks,
  setTracks,
  adjustments,
  setAdjustments,
  rates,
  setRates,
  words,
  onRequestWords,
  onRemoveWord,
}) {
  const [tab, setTab] = useState("schedule");
  const [targetRaw, setTarget] = useState("trainer");
  // Останній реально обраний акаунт (не "Усі") — щоб вкладки, де "Усі" не має
  // сенсу, показували його, а не відкочувалися на тренера.
  const [lastRole, setLastRole] = useState("trainer");
  const [query, setQuery] = useState("");
  const [editing, setEditing] = useState(null);
  const [keep, setKeep] = useState({ date: "", dateTo: "", from: "17:00", to: "18:00" });

  const pickTarget = (id) => {
    setTarget(id);
    if (id !== "everyone") setLastRole(id);
    setKeep({ date: "", dateTo: "", from: "17:00", to: "18:00" });
    setEditing(null);
  };

  // Активний акаунт. Раніше вибір "Усі" примусово перезаписувався на "тренер"
  // через useEffect при переході на іншу вкладку — і назад уже не повертався.
  // Тепер "Усі" живе лише у вкладці "Графік"; в інших підставляємо lastRole,
  // але сам вибір не стираємо, тож при поверненні він на місці.
  // Оплата стосується тільки вчителів — тренера туди не пускаємо.
  const target = (() => {
    if (targetRaw === "everyone") return tab === "schedule" ? "everyone" : lastRole;
    const safe = REGISTERABLE_ROLES.includes(targetRaw) ? targetRaw : "trainer";
    if (tab === "pay" && safe === "trainer") return "englishTeacher";
    return safe;
  })();

  const accent = BLACK;
  const switchIds = ["trainer", "englishTeacher", "vocalTeacher"];
  const isEveryone = target === "everyone";
  const types = isEveryone
    ? ["rest", VOLUNTEER_TYPE]
    : target === "trainer"
    ? [...TRAINER_TYPES, VOLUNTEER_TYPE]
    : target === "vocalTeacher"
    ? [...VOCAL_TYPES, VOLUNTEER_TYPE]
    : [...ENGLISH_TYPES, "rest", VOLUNTEER_TYPE];
  const legendTypes =
    target === "trainer"
      ? ["sport", "group", "cycle", "run"]
      : target === "vocalTeacher"
      ? ["lesson"]
      : ["english", "speaking"];

  const setTargetProfile = (p) => setProfiles((prev) => ({ ...prev, [target]: p }));

  const toggleLock = () => {
    const p = profiles[target] || emptyProfile;
    setTargetProfile({ ...p, locked: !p.locked });
  };

  const wipe = () => {
    if (window.confirm(t.confirmWipe)) {
      setTargetProfile({ ...emptyProfile });
      setEntries((prev) => ({ ...prev, [target]: [] }));
    }
  };

  return (
    <div style={{ ...S.page, ...THEMES.light }}>
      <LangBar lang={lang} setLang={setLang} accent={accent} />

      <div style={{ ...S.body, maxWidth: wide ? 980 : "100%" }}>
        {tab === "schedule" ? (
          <div style={S.userSwitch}>
            {["everyone", ...switchIds].map((id) => (
              <button
                key={id}
                onClick={() => pickTarget(id)}
                style={{
                  ...S.switchBtn,
                  backgroundColor: target === id ? accent : "transparent",
                  color: target === id ? "var(--bg)" : "var(--muted)",
                  borderColor: target === id ? accent : "var(--line)",
                }}
              >
                {id === "everyone" ? t.everyoneTarget : t.names[id]}
              </button>
            ))}
          </div>
        ) : null}

        {tab === "schedule" && isEveryone && (
          <div style={wide ? S.twoCol : undefined}>
            <div>
              <EntryForm
                t={t}
                types={types}
                onAdd={(e) => switchIds.forEach((id) => addEntry(id, { ...e, id: e.id + "-" + id }))}
                titleLabel={t.titleTrainer}
                keep={keep}
                setKeep={setKeep}
                showReset
              />
              <RestBirthdayCalendar t={t} listFor={listFor} accent={accent} wide={wide} />
            </div>
          </div>
        )}

        {tab === "schedule" && !isEveryone && (
          <div style={wide ? S.twoCol : undefined}>
            <div>
              {editing ? (
                <EntryEditor
                  t={t}
                  entry={editing}
                  onClose={() => setEditing(null)}
                  onSave={(next) => {
                    updateEntry(target, next);
                    setEditing(null);
                  }}
                />
              ) : (
                <EntryForm
                  t={t}
                  types={types}
                  onAdd={(e) => addEntry(target, e)}
                  titleLabel={target === "trainer" ? t.titleTrainer : t.titleTeacher}
                  keep={keep}
                  setKeep={setKeep}
                  showReset
                  platform={target === "englishTeacher" ? profiles.englishTeacher.platform : undefined}
                />
              )}
              <EntryList
                t={t}
                list={listFor(target)}
                rights={RIGHTS.admin}
                onCancel={(id) => toggleCancel(target, id, "admin")}
                onRemove={(id) => removeEntry(target, id)}
                onEdit={(e) => setEditing(e)}
              />
            </div>
          </div>
        )}

        {tab === "all" && <SharedCalendar t={t} listFor={listFor} events={events} accent={accent} wide={wide} />}

        {tab === "events" && <AdminEvents t={t} events={events} setEvents={setEvents} wide={wide} />}

        {tab === "dict" && (
          <DictionaryView
            t={t}
            words={words || []}
            lessons={(listFor("englishTeacher") || []).filter((e) =>
              ["english", "speaking"].includes(e.type)
            )}
            accent={GREEN_DICT}
            wide={wide}
            isAdmin
            onRequest={(rows) => onRequestWords(rows)}
            onDismiss={(id) => onRemoveWord(id)}
          />
        )}

        {tab === "playlist" && (
          <PlaylistView
            t={t}
            tracks={tracks}
            accent={accent}
            wide={wide}
            canProgress
            onAdd={(tr) => setTracks([...tracks, tr])}
            onEdit={(tr) => setTracks(tracks.map((x) => (x.id === tr.id ? tr : x)))}
            onRemove={(id) => setTracks(tracks.filter((x) => x.id !== id))}
          />
        )}

        {tab === "pay" && (
          <div>
            <div style={{ ...S.ownerRow, marginTop: 14 }}>
              {["englishTeacher", "vocalTeacher"].map((id) => {
                const on = target === id;
                return (
                  <button
                    key={id}
                    onClick={() => pickTarget(id)}
                    style={{
                      ...S.switchBtn,
                      backgroundColor: on ? accent : "transparent",
                      color: on ? "var(--bg)" : "var(--muted)",
                      borderColor: on ? accent : "var(--line)",
                    }}
                  >
                    {t.names[id]}
                  </button>
                );
              })}
            </div>

            <PayView
              t={t}
              userId={target}
              list={listFor(target)}
              adjustments={adjustments[target] || []}
              accent={accent}
              rate={rates[target] || 0}
              who="admin"
              onRate={(v) => setRates({ ...rates, [target]: v })}
              onAddAdjust={(a) =>
                setAdjustments({ ...adjustments, [target]: [...(adjustments[target] || []), a] })
              }
              onRemoveAdjust={(id) =>
                setAdjustments({
                  ...adjustments,
                  [target]: (adjustments[target] || []).filter((x) => x.id !== id),
                })
              }
            />
          </div>
        )}

        {tab === "accounts" && (
          <div>
            <AccountSearch
              t={t}
              query={query}
              setQuery={setQuery}
              profiles={profiles}
              target={target}
              setTarget={pickTarget}
              accent={accent}
            />

            <div style={S.adminActions}>
              <button onClick={toggleLock} style={S.ghostBtn}>
                {(profiles[target] || emptyProfile).locked ? t.unlock : t.lock}
              </button>
              <button onClick={wipe} style={{ ...S.ghostBtn, color: "#c0392b", borderColor: "#e8c6c1" }}>
                {t.wipe}
              </button>
            </div>
            <AccountView
              key={target}
              t={t}
              userId={target}
              profile={profiles[target] || emptyProfile}
              setProfile={setTargetProfile}
              canEdit={true}
              accent={accent}
              isAdmin
            />
          </div>
        )}

        {tab === "me" && (
          <AdminSelfProfile t={t} adminProfile={adminProfile} setAdminProfile={setAdminProfile} accent={accent} />
        )}
      </div>

      <TabBar
        t={t}
        tab={tab}
        setTab={setTab}
        tabs={["schedule", "all", "events", "playlist", "dict", "pay", "accounts", "me"]}
        accent={accent}
      />
    </div>
  );
}

function AccountSearch({ t, query, setQuery, profiles, target, setTarget, accent }) {
  const ids = ["trainer", "englishTeacher", "vocalTeacher"];
  const q = query.trim().toLowerCase();

  const match = (id) => {
    if (!q) return true;
    const p = profiles[id] || {};
    const hay = [p.firstName, p.lastName, t.names[id], p.email]
      .filter(Boolean)
      .join(" ")
      .toLowerCase();
    return hay.includes(q);
  };

  const found = ids.filter(match);

  return (
    <div style={{ marginTop: 16, marginBottom: 18 }}>
      <div style={S.searchWrap}>
        <SearchIcon color="var(--muted)" />
        <input
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder={t.search}
          style={S.searchInput}
        />
        {query ? (
          <button onClick={() => setQuery("")} style={S.searchClear}>
            ×
          </button>
        ) : null}
      </div>

      {found.length === 0 ? <div style={S.searchEmpty}>{t.notFound}</div> : null}

      <div style={S.resultList}>
        {found.map((id) => {
          const p = profiles[id] || {};
          const name = [p.firstName, p.lastName].filter(Boolean).join(" ");
          const on = target === id;
          return (
            <button
              key={id}
              onClick={() => setTarget(id)}
              style={{
                ...S.resultRow,
                borderColor: on ? accent : "var(--line)",
                boxShadow: on ? `0 0 0 1px ${accent}` : "none",
              }}
            >
              <span style={{ ...S.resultAvatar, borderColor: on ? accent : "var(--line)" }}>
                {p.avatar ? (
                  <img
                    src={p.avatar}
                    alt=""
                    style={{
                      ...S.avatarImg,
                      transform: `translate(${(p.avatarPos || {}).x || 0}px, ${
                        (p.avatarPos || {}).y || 0
                      }px) scale(${p.avatarZoom || 1})`,
                    }}
                  />
                ) : (p.firstName || "").trim() ? (
                  <span style={{ ...S.avatarInitial, fontSize: 20, color: "var(--muted)" }}>
                    {p.firstName.trim().slice(0, 1).toUpperCase()}
                  </span>
                ) : (
                  <ProfileIcon color="var(--muted)" />
                )}
              </span>
              <span style={{ minWidth: 0 }}>
                <span style={S.resultName}>{name || t.noName}</span>
                <span style={S.resultRole}>{t.names[id]}</span>
              </span>
              {p.locked ? <span style={S.lockTag}>🔒</span> : null}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function AdminSelfProfile({ t, adminProfile, setAdminProfile, accent }) {
  return (
    <div style={S.accountWrap}>
      <h3 style={S.sectionTitle}>{t.adminProfile}</h3>

      <AvatarPicker
        t={t}
        value={adminProfile.avatar}
        zoom={adminProfile.avatarZoom}
        position={adminProfile.avatarPos}
        name={adminProfile.name}
        onChange={(v) => setAdminProfile({ ...adminProfile, avatar: v })}
        onZoom={(z) => setAdminProfile({ ...adminProfile, avatarZoom: z })}
        onPos={(p) => setAdminProfile({ ...adminProfile, avatarPos: p })}
        onPick={(v) => setAdminProfile({ ...adminProfile, avatar: v, avatarPos: { x: 0, y: 0 } })}
        onRemove={() => setAdminProfile({ ...adminProfile, avatar: null, avatarZoom: 1, avatarPos: { x: 0, y: 0 } })}
        onSave={() => {}}
        accent={accent}
      />

      <Field
        label={t.adminName}
        value={adminProfile.name}
        onChange={(v) => setAdminProfile({ ...adminProfile, name: v })}
      />

      <Field
        label={t.birth}
        value={adminProfile.birth}
        onChange={(v) => setAdminProfile({ ...adminProfile, birth: v })}
        type="date"
      />

      <div style={{ ...S.adminBadge, backgroundColor: accent, color: "var(--bg)" }}>{t.adminBadge}</div>
    </div>
  );
}

function Modal({ title, onClose, children }) {
  return (
    <div style={S.modalOverlay} onClick={onClose}>
      <div style={S.modalCard} onClick={(e) => e.stopPropagation()}>
        <div style={S.modalHead}>
          <span style={S.modalTitle}>{title}</span>
          <button onClick={onClose} style={S.modalClose}>
            ×
          </button>
        </div>
        <div style={S.modalBody}>{children}</div>
      </div>
    </div>
  );
}

function EventForm({ t, initial, onSubmit, submitLabel }) {
  const C = ACT.event.color;
  const [draft, setDraft] = useState(
    initial || { title: "Spartan", date: "", place: "", owner: "trainer", image: null }
  );

  const set = (k, v) => setDraft({ ...draft, [k]: v });

  const owners = [
    ["trainer", t.names.trainer],
    ["vocalTeacher", t.names.vocalTeacher],
  ];

  const spartanAllowed = draft.owner === "trainer";

  const chooseOwner = (id) => {
    const next = { ...draft, owner: id };
    if (id === "vocalTeacher" && next.image === SPARTAN_MARK) next.image = null;
    setDraft(next);
  };

  const pick = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    const data = await compressImage(file, 700, 0.7);
    set("image", data);
    e.target.value = "";
  };

  return (
    <div>
      <div style={S.fieldWrap}>
        <label style={S.fieldLabel}>{t.forWhom}</label>
        <div style={S.ownerRow}>
          {owners.map(([id, label]) => {
            const on = draft.owner === id;
            return (
              <button
                key={id}
                onClick={() => chooseOwner(id)}
                style={{
                  ...S.switchBtn,
                  backgroundColor: on ? C : "transparent",
                  color: on ? "#fff" : "var(--muted)",
                  borderColor: on ? C : "var(--line)",
                }}
              >
                {label}
              </button>
            );
          })}
        </div>
      </div>

      {draft.image ? (
        <div style={S.photoPreviewWrap}>
          <img src={resolveImage(draft.image)} alt="" style={S.photoPreview} />
        </div>
      ) : (
        <div style={S.photoEmpty}>{t.noPhoto}</div>
      )}

      <div style={S.photoBtns}>
        <label style={{ ...S.ghostBtn, cursor: "pointer" }}>
          {t.uploadPhoto}
          <input type="file" accept="image/*" onChange={pick} style={{ display: "none" }} />
        </label>
        {spartanAllowed ? (
          <button onClick={() => set("image", SPARTAN_MARK)} style={S.ghostBtn}>
            {t.useDefault}
          </button>
        ) : null}
        {draft.image ? (
          <button
            onClick={() => set("image", null)}
            style={{ ...S.ghostBtn, color: "#c0392b", borderColor: "#e8c6c1" }}
          >
            {t.photoRemove}
          </button>
        ) : null}
      </div>

      <Field label={t.eventName} value={draft.title} onChange={(v) => set("title", v)} placeholder="Spartan" />
      <Field label={t.eventDate} value={draft.date} onChange={(v) => set("date", v)} type="date" />
      <Field label={t.place} value={draft.place} onChange={(v) => set("place", v)} placeholder={t.placePh} />

      <button
        onClick={() => {
          if (!draft.title.trim() || !draft.date) return;
          onSubmit(draft);
        }}
        style={{ ...S.primaryBtn, backgroundColor: C, color: "#fff" }}
      >
        {submitLabel}
      </button>
    </div>
  );
}

function AdminEvents({ t, events, setEvents, wide }) {
  const C = ACT.event.color;
  const [view, setView] = useState("trainer");
  const [creating, setCreating] = useState(false);
  const [editing, setEditing] = useState(null);

  const views = [
    ["trainer", t.names.trainer],
    ["vocalTeacher", t.names.vocalTeacher],
  ];

  const ownerLabel = (o) => (!o || o === "all" ? t.forAll : t.names[o]);

  const create = (draft) => {
    setEvents([
      ...events,
      { ...draft, id: Date.now() + "-" + Math.random().toString(36).slice(2, 7), title: draft.title.trim() },
    ]);
    setCreating(false);
  };

  const saveEdit = (next) => {
    setEvents(events.map((e) => (e.id === next.id ? next : e)));
    setEditing(null);
  };

  const remove = (id) => setEvents(events.filter((e) => e.id !== id));

  const shown = events.filter((e) => (view === "all" ? true : e.owner === view || e.owner === "all"));

  return (
    <div>
      <div style={{ ...S.ownerRow, marginTop: 18, marginBottom: 14 }}>
        {views.map(([id, label]) => {
          const on = view === id;
          return (
            <button
              key={id}
              onClick={() => setView(id)}
              style={{
                ...S.switchBtn,
                backgroundColor: on ? "var(--fg)" : "transparent",
                color: on ? "var(--bg)" : "var(--muted)",
                borderColor: on ? "var(--fg)" : "var(--line)",
              }}
            >
              {label}
            </button>
          );
        })}
      </div>

      <div style={S.plannedHead}>
        {t.created} · {shown.length}
      </div>

      {shown.length === 0 ? (
        <div style={S.emptyState}>
          <p style={S.emptyTitle}>{t.noEvents}</p>
        </div>
      ) : null}

      <div style={{ ...(wide ? S.twoCol : {}), paddingBottom: 70 }}>
        {[...shown]
          .sort((a, b) => (a.date > b.date ? 1 : -1))
          .map((e) => (
            <EventCard
              key={e.id}
              t={t}
              e={e}
              onRemove={remove}
              onEdit={() => setEditing(e)}
              ownerLabel={ownerLabel(e.owner)}
            />
          ))}
      </div>

      <button
        onClick={() => setCreating(true)}
        style={{ ...S.fabBtn, backgroundColor: C }}
      >
        + {t.createEvent}
      </button>

      {creating ? (
        <Modal title={t.newEvent} onClose={() => setCreating(false)}>
          <EventForm t={t} onSubmit={create} submitLabel={"+ " + t.addSpartan} />
        </Modal>
      ) : null}

      {editing ? (
        <Modal title={t.edit} onClose={() => setEditing(null)}>
          <EventForm t={t} initial={editing} onSubmit={saveEdit} submitLabel={t.saveEdit} />
        </Modal>
      ) : null}
    </div>
  );
}

/* ---------- styles ---------- */

const S = {
  page: {
    minHeight: "100vh",
    backgroundColor: "var(--bg)",
    color: "var(--fg)",
    display: "flex",
    flexDirection: "column",
    fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
  },

  topBar: { display: "flex", flexDirection: "column", alignItems: "stretch", padding: "16px 20px 0" },
  langRow: { display: "flex", alignItems: "center", gap: 8, justifyContent: "flex-end" },
  langBtn: {
    padding: "5px 12px",
    fontSize: 11,
    fontWeight: 800,
    letterSpacing: "0.8px",
    border: "1.5px solid",
    borderRadius: 20,
    backgroundColor: "transparent",
    cursor: "pointer",
    fontFamily: "inherit",
  },
  exitRow: { marginTop: 10, display: "flex", alignItems: "center", justifyContent: "space-between" },
  topNote: { fontSize: 13, fontWeight: 600, letterSpacing: "0.2px" },
  exitBtn: {
    width: 34,
    height: 34,
    border: "none",
    backgroundColor: "transparent",
    cursor: "pointer",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    padding: 0,
  },

  loginCenter: { flex: 1, display: "flex", justifyContent: "center", alignItems: "center", padding: "20px 20px 60px" },
  brand: { fontSize: 26, fontWeight: 700, letterSpacing: "-0.3px", color: "var(--fg)", margin: 0, textAlign: "center" },
  brandSub: { fontSize: 13, color: "var(--muted)", margin: "6px 0 36px", textAlign: "center" },
  form: { display: "flex", flexDirection: "column", gap: 10 },
  label: { fontSize: 12, fontWeight: 600, color: "var(--muted)", letterSpacing: "0.3px" },
  input: {
    padding: "13px 14px",
    fontSize: 15,
    border: "1px solid var(--line)",
    borderRadius: 10,
    outline: "none",
    backgroundColor: "var(--surface)",
    color: "var(--on-surface)",
    fontFamily: "inherit",
    boxSizing: "border-box",
  },
  actsBox: {
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 12,
    padding: "14px 16px",
  },
  actsText: { fontSize: 12.5, color: "var(--muted)", margin: "4px 0", lineHeight: 1.5 },
  err: { color: "#d64545", fontSize: 12, margin: 0 },
  loginBtn: {
    padding: "13px 14px",
    fontSize: 15,
    backgroundColor: "var(--fg)",
    color: "var(--bg)",
    border: "none",
    borderRadius: 10,
    cursor: "pointer",
    fontWeight: 600,
    fontFamily: "inherit",
  },

  body: { flex: 1, width: "100%", margin: "0 auto", padding: "4px 18px 110px", boxSizing: "border-box" },
  twoCol: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))", gap: 26, alignItems: "start" },

  brandBlock: { marginTop: 18 },
  brandMark: {
    fontSize: 30,
    fontWeight: 400,
    letterSpacing: "1.5px",
    lineHeight: 1,
    color: "#F5C518",
    textShadow: "0 0 18px rgba(245,197,24,0.4)",
    fontFamily: "'Anton', 'Haettenschweiler', 'Arial Narrow', Impact, sans-serif",
  },
  brandTop: { fontSize: 13, fontWeight: 600, letterSpacing: "0.2px", marginBottom: 4 },
  brandName: { fontSize: 13, color: "var(--muted)", marginTop: 6, fontWeight: 500 },
  monthRow: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 },
  monthTitle: { fontSize: 22, fontWeight: 700, margin: 0 },
  navRow: { display: "flex", gap: 8 },
  navBtn: {
    width: 34,
    height: 34,
    borderRadius: "50%",
    border: "1.5px solid",
    backgroundColor: "transparent",
    fontSize: 17,
    cursor: "pointer",
    lineHeight: 1,
    fontFamily: "inherit",
  },
  countPill: {
    display: "inline-block",
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 20,
    padding: "7px 14px",
    fontSize: 12,
    color: "var(--muted)",
    marginBottom: 20,
  },
  weekRow: { display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 7, marginBottom: 8 },
  weekCell: { textAlign: "center", fontSize: 10, color: "var(--muted)", fontWeight: 700, letterSpacing: "0.5px" },
  grid: { display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 7 },
  emptyCell: { aspectRatio: "1" },
  dayCell: {
    aspectRatio: "1",
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
    justifyContent: "center",
    position: "relative",
    border: "1.5px solid",
    borderRadius: 10,
    fontWeight: 600,
    lineHeight: 1.1,
  },
  eventDot: { position: "absolute", bottom: 4, width: 4, height: 4, borderRadius: "50%" },
  hbTag: {
    position: "absolute",
    top: 3,
    right: 4,
    fontSize: 8,
    fontWeight: 800,
    letterSpacing: "0.5px",
    opacity: 0.85,
  },
  dotsRow: {
    position: "absolute",
    bottom: 4,
    display: "flex",
    alignItems: "center",
    gap: 3,
    maxWidth: "82%",
    flexWrap: "wrap",
    justifyContent: "center",
  },
  dayDot: { width: 5, height: 5, borderRadius: "50%", flexShrink: 0 },
  dotsMore: { fontSize: 7, fontWeight: 800, lineHeight: 1, opacity: 0.85, color: "var(--muted)" },

  dayPanel: {
    marginTop: 18,
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 16,
    padding: "16px 16px 14px",
  },
  dayPanelHead: {
    fontSize: 11,
    fontWeight: 800,
    letterSpacing: "1.6px",
    textTransform: "uppercase",
    color: "var(--muted)",
    marginBottom: 12,
  },
  dayEmpty: { display: "flex", alignItems: "center", gap: 10, fontSize: 14, color: "var(--muted)" },
  dayItem: {
    borderLeft: "3px solid",
    paddingLeft: 12,
    paddingTop: 2,
    paddingBottom: 2,
    marginBottom: 12,
  },
  dayItemTop: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" },
  dayItemTitle: { fontSize: 14, fontWeight: 600, color: "var(--on-surface)" },

  legendRow: { display: "flex", flexWrap: "wrap", gap: 14, marginTop: 18 },
  legendItem: { display: "flex", alignItems: "center", gap: 6 },
  legendDot: { width: 9, height: 9, borderRadius: "50%", display: "inline-block", flexShrink: 0 },
  legendLabel: { fontSize: 11, color: "var(--muted)", fontWeight: 600 },

  typeGrid: { display: "grid", gap: 7, marginBottom: 20 },
  typeCard: {
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
    justifyContent: "center",
    gap: 6,
    padding: "12px 3px",
    border: "1.5px solid",
    borderRadius: 12,
    cursor: "pointer",
    fontFamily: "inherit",
    minHeight: 76,
  },
  typeEmoji: { fontSize: 19, lineHeight: 1 },
  typeText: { fontSize: 9, fontWeight: 700, textAlign: "center", lineHeight: 1.2 },

  segRow: { display: "flex", gap: 6, marginBottom: 14 },
  segBtn: {
    flex: 1,
    padding: "9px 10px",
    fontSize: 11,
    fontWeight: 700,
    border: "1px solid var(--line)",
    borderRadius: 20,
    cursor: "pointer",
    fontFamily: "inherit",
  },
  placeList: { display: "flex", flexDirection: "column", gap: 8 },
  placeOption: {
    display: "flex",
    alignItems: "center",
    gap: 9,
    padding: "12px 13px",
    backgroundColor: "var(--surface)",
    border: "1.5px solid",
    borderRadius: 12,
    cursor: "pointer",
    fontFamily: "inherit",
    textAlign: "left",
    width: "100%",
  },
  placeText: { fontSize: 13, fontWeight: 600, color: "var(--on-surface)" },
  fixedLabel: {
    padding: "11px 13px",
    backgroundColor: "var(--surface)",
    border: "1.5px solid",
    borderRadius: 10,
    fontSize: 13,
    fontWeight: 800,
    letterSpacing: "0.4px",
  },

  twoFields: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 },
  allDayNote: {
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 10,
    padding: "10px 12px",
    fontSize: 12,
    color: "var(--muted)",
    marginBottom: 4,
    textAlign: "center",
    fontWeight: 600,
  },

  balanceCard: {
    border: "1.5px solid",
    borderRadius: 18,
    padding: "18px 20px",
    marginTop: 18,
    marginBottom: 16,
    backgroundColor: "var(--input)",
  },
  balanceLabel: { fontSize: 11, fontWeight: 800, textTransform: "uppercase", letterSpacing: "0.8px", color: "var(--muted)" },
  balanceValue: { fontSize: 34, fontWeight: 800, margin: "6px 0 4px", letterSpacing: "-0.5px" },
  balanceHint: { fontSize: 12, color: "var(--muted)" },
  rateBtn: {
    marginTop: 4,
    padding: "7px 12px",
    fontSize: 11,
    fontWeight: 700,
    border: "1.5px solid",
    borderRadius: 20,
    backgroundColor: "transparent",
    cursor: "pointer",
    fontFamily: "inherit",
  },
  payRow: {
    display: "flex",
    alignItems: "center",
    gap: 10,
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderLeft: "3px solid",
    borderRadius: 12,
    padding: "11px 13px",
    marginBottom: 8,
  },
  payTop: { display: "flex", alignItems: "center", gap: 8, marginBottom: 3 },
  payTitle: { fontSize: 13, fontWeight: 600, color: "var(--on-surface)" },
  payAmountBox: { display: "flex", alignItems: "center", gap: 2, flexShrink: 0 },
  payAmount: { fontSize: 14, fontWeight: 800 },

  summaryRow: { display: "flex", flexWrap: "wrap", gap: 7, marginBottom: 14 },
  summaryChip: {
    display: "inline-flex",
    alignItems: "center",
    gap: 6,
    padding: "6px 11px",
    border: "1.5px solid",
    borderRadius: 20,
    backgroundColor: "var(--surface)",
  },
  summaryLabel: { fontSize: 11, fontWeight: 700, color: "var(--on-surface)" },
  summaryCount: { fontSize: 11, fontWeight: 800, color: "var(--muted)" },

  plannedHead: { fontSize: 11, fontWeight: 800, letterSpacing: "0.8px", textTransform: "uppercase", marginBottom: 10 },
  plannedHint: { fontWeight: 500, color: "var(--muted)", textTransform: "none", letterSpacing: 0 },
  entryCard: {
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderLeft: "3px solid",
    borderRadius: 12,
    padding: "12px 14px",
    marginBottom: 8,
    display: "flex",
    alignItems: "center",
    gap: 10,
  },
  entryTop: { display: "flex", alignItems: "center", gap: 7, flexWrap: "wrap", marginBottom: 5 },
  entryDate: { fontSize: 12, fontWeight: 700, color: "var(--on-surface)" },
  entryTime: { fontSize: 11, color: "var(--muted)", fontWeight: 600 },
  ownerTag: {
    fontSize: 9,
    fontWeight: 800,
    letterSpacing: "0.4px",
    textTransform: "uppercase",
    color: "var(--muted)",
    border: "1px solid var(--line)",
    borderRadius: 20,
    padding: "2px 7px",
  },
  entryTitle: { fontSize: 14, fontWeight: 600, color: "var(--on-surface)" },
  entrySub: { fontSize: 12, color: "var(--muted)", marginTop: 3 },
  cancelBanner: {
    marginTop: 8,
    backgroundColor: "rgba(239,68,68,0.12)",
    border: `1px solid ${RED}`,
    color: RED,
    borderRadius: 8,
    padding: "6px 10px",
    fontSize: 11,
    fontWeight: 700,
  },
  mapLink: {
    display: "inline-flex",
    alignItems: "center",
    gap: 5,
    marginTop: 6,
    fontSize: 12,
    textDecoration: "none",
    fontWeight: 600,
  },
  entryActions: { display: "flex", flexDirection: "column", gap: 2, flexShrink: 0 },
  iconBtn: {
    background: "transparent",
    border: "none",
    cursor: "pointer",
    padding: 6,
    display: "flex",
    alignItems: "center",
    flexShrink: 0,
  },

  sectionTitle: { fontSize: 16, fontWeight: 700, margin: "18px 0 14px" },
  emptyState: { textAlign: "center", paddingTop: 80 },
  emptyTitle: { fontSize: 15, color: "var(--muted)", margin: 0 },
  emptyHint: { fontSize: 12, color: "var(--muted)", marginTop: 6, opacity: 0.7 },

  accountWrap: { width: "100%", maxWidth: 420, paddingTop: 12 },
  avatarBox: { display: "flex", flexDirection: "column", alignItems: "center", marginBottom: 24 },
  avatar: {
    width: 88,
    height: 88,
    borderRadius: "50%",
    backgroundColor: "var(--input)",
    border: "1.5px solid",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    overflow: "hidden",
  },
  avatarImg: { width: "100%", height: "100%", objectFit: "cover", transition: "transform 0.15s ease" },
  avatarPlus: { fontSize: 28 },
  avatarInitial: { fontSize: 34, fontWeight: 700, userSelect: "none" },
  photoLabel: { marginTop: 10, fontSize: 12, cursor: "pointer", fontWeight: 600 },
  zoomRow: { display: "flex", alignItems: "center", gap: 10, marginTop: 14, width: "100%", maxWidth: 240 },
  zoomLabel: { fontSize: 10, color: "var(--muted)", fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.5px" },
  zoomInput: { flex: 1, cursor: "pointer" },
  pinchHint: { fontSize: 11, color: "var(--muted)", marginTop: 6, textAlign: "center", opacity: 0.8 },
  pwRow: { display: "flex", alignItems: "center", gap: 8 },
  eyeBtn: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    width: 40,
    height: 40,
    flexShrink: 0,
    borderRadius: 10,
    border: "1px solid var(--line)",
    backgroundColor: "transparent",
    cursor: "pointer",
  },
  avatarBtns: { display: "flex", gap: 8, marginTop: 12, flexWrap: "wrap", justifyContent: "center" },
  lockedNote: {
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 10,
    padding: "10px 12px",
    fontSize: 11,
    color: "var(--muted)",
    marginBottom: 18,
    lineHeight: 1.4,
  },

  fieldWrap: { marginBottom: 14 },
  fieldLabel: { display: "block", fontSize: 11, color: "var(--muted)", marginBottom: 6, fontWeight: 600 },
  fieldInput: {
    width: "100%",
    padding: "11px 13px",
    fontSize: 14,
    backgroundColor: "var(--input)",
    border: "1px solid var(--line)",
    borderRadius: 10,
    color: "var(--on-surface)",
    outline: "none",
    boxSizing: "border-box",
    fontFamily: "inherit",
  },
  pickRow: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 },
  pickBtn: {
    display: "flex",
    alignItems: "center",
    gap: 9,
    padding: "10px 12px",
    backgroundColor: "var(--input)",
    border: "1.5px solid",
    borderRadius: 10,
    cursor: "pointer",
    fontFamily: "inherit",
  },
  pickIcon: { display: "flex", alignItems: "center", flexShrink: 0 },
  pickLabel: { fontSize: 12, fontWeight: 700, color: "var(--on-surface)" },

  phoneWrap: {
    display: "flex",
    alignItems: "center",
    backgroundColor: "var(--input)",
    border: "1px solid var(--line)",
    borderRadius: 10,
    overflow: "hidden",
  },
  phonePrefix: {
    padding: "11px 10px 11px 13px",
    fontSize: 14,
    fontWeight: 700,
    color: "var(--muted)",
    borderRight: "1px solid var(--line)",
  },
  phoneInput: {
    flex: 1,
    padding: "11px 13px",
    fontSize: 14,
    backgroundColor: "transparent",
    border: "none",
    color: "var(--on-surface)",
    outline: "none",
    fontFamily: "inherit",
    letterSpacing: "1px",
    minWidth: 0,
  },
  hint: { fontSize: 10, color: "var(--muted)", marginTop: 5, opacity: 0.8 },

  primaryBtn: {
    width: "100%",
    padding: "14px",
    border: "none",
    borderRadius: 10,
    fontWeight: 700,
    fontSize: 14,
    cursor: "pointer",
    marginTop: 8,
    fontFamily: "inherit",
  },
  savedMsg: { textAlign: "center", fontSize: 12, marginTop: 10 },

  searchWrap: {
    display: "flex",
    alignItems: "center",
    gap: 9,
    padding: "11px 14px",
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 24,
    marginBottom: 14,
  },
  searchInput: {
    flex: 1,
    border: "none",
    background: "transparent",
    outline: "none",
    fontSize: 14,
    color: "var(--on-surface)",
    fontFamily: "inherit",
    minWidth: 0,
  },
  searchClear: {
    border: "none",
    background: "transparent",
    color: "var(--muted)",
    fontSize: 20,
    cursor: "pointer",
    lineHeight: 1,
    padding: 0,
  },
  searchEmpty: { fontSize: 13, color: "var(--muted)", padding: "8px 4px" },
  resultList: { display: "flex", flexDirection: "column", gap: 8 },
  resultRow: {
    display: "flex",
    alignItems: "center",
    gap: 12,
    padding: "10px 14px",
    backgroundColor: "var(--surface)",
    border: "1.5px solid",
    borderRadius: 14,
    cursor: "pointer",
    fontFamily: "inherit",
    textAlign: "left",
    width: "100%",
  },
  resultAvatar: {
    width: 38,
    height: 38,
    borderRadius: "50%",
    border: "1.5px solid",
    overflow: "hidden",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    flexShrink: 0,
    backgroundColor: "var(--bg)",
  },
  resultName: { display: "block", fontSize: 14, fontWeight: 700, color: "var(--on-surface)" },
  resultRole: { display: "block", fontSize: 11, color: "var(--muted)", marginTop: 2 },
  lockTag: { marginLeft: "auto", fontSize: 13 },

  editorBox: {
    backgroundColor: "var(--surface)",
    border: "1.5px solid var(--line)",
    borderRadius: 16,
    padding: "14px 16px 16px",
    marginBottom: 16,
  },
  editorHead: { display: "flex", alignItems: "center", gap: 8, marginBottom: 14 },
  editorTitle: { fontSize: 12, fontWeight: 800, textTransform: "uppercase", letterSpacing: "0.8px" },

  adminActions: { display: "flex", gap: 8, marginTop: 16, flexWrap: "wrap" },
  ghostBtn: {
    padding: "8px 14px",
    fontSize: 12,
    fontWeight: 600,
    border: "1px solid var(--line)",
    borderRadius: 20,
    backgroundColor: "transparent",
    color: "var(--fg)",
    cursor: "pointer",
    fontFamily: "inherit",
  },

  adminCard: {
    display: "flex",
    alignItems: "center",
    gap: 14,
    border: "1.5px solid",
    borderRadius: 14,
    padding: "14px 16px",
    marginTop: 20,
    maxWidth: 420,
  },
  adminAvatar: {
    width: 52,
    height: 52,
    borderRadius: "50%",
    border: "1.5px solid",
    backgroundColor: "var(--surface)",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    overflow: "hidden",
    flexShrink: 0,
  },
  adminNameText: { fontSize: 16, fontWeight: 700, marginBottom: 6 },
  adminBadge: {
    display: "inline-block",
    fontSize: 10,
    fontWeight: 800,
    letterSpacing: "0.6px",
    padding: "3px 9px",
    borderRadius: 20,
    textTransform: "uppercase",
  },

  userSwitch: { display: "flex", gap: 6, marginTop: 14, marginBottom: 4, flexWrap: "wrap" },
  switchBtn: {
    padding: "7px 12px",
    fontSize: 11,
    fontWeight: 600,
    border: "1px solid",
    borderRadius: 20,
    cursor: "pointer",
    fontFamily: "inherit",
  },

  tabBar: {
    position: "fixed",
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: "var(--bg)",
    borderTop: "1px solid var(--line)",
    padding: "10px 0 16px",
  },
  tabInner: { maxWidth: 720, margin: "0 auto", display: "flex", justifyContent: "space-around" },
  tabBtn: {
    background: "transparent",
    border: "none",
    cursor: "pointer",
    display: "flex",
    flexDirection: "column",
    alignItems: "center",
    gap: 3,
    fontFamily: "inherit",
    padding: "0 6px",
  },
  tabLabel: { fontSize: 9, fontWeight: 600 },

  spartanCard: {
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 14,
    overflow: "hidden",
    marginBottom: 14,
    display: "flex",
    flexDirection: "column",
  },
  spartanImgWrap: { position: "relative", width: "100%", lineHeight: 0 },
  spartanImg: { width: "100%", display: "block", objectFit: "cover" },
  spartanRibbon: {
    position: "absolute",
    left: 12,
    bottom: 12,
    color: "#fff",
    fontSize: 12,
    fontWeight: 800,
    letterSpacing: "1.2px",
    textTransform: "uppercase",
    padding: "5px 12px",
    borderRadius: 6,
  },
  spartanBody: { padding: "12px 14px" },
  coverWrap: {
    width: 200,
    height: 200,
    margin: "0 auto 12px",
    borderRadius: 14,
    overflow: "hidden",
    backgroundColor: "var(--input)",
    border: "1px solid var(--line)",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
  coverImg: { width: "100%", height: "100%", objectFit: "cover", display: "block" },
  coverEmpty: { fontSize: 12, color: "var(--muted)", textAlign: "center", padding: "0 12px" },
  eventTag: {
    display: "inline-block",
    marginTop: 6,
    fontSize: 10,
    fontWeight: 800,
    letterSpacing: "0.4px",
    textTransform: "uppercase",
    border: "1px solid",
    borderRadius: 20,
    padding: "3px 9px",
  },

  trackCard: {
    display: "flex",
    alignItems: "center",
    gap: 12,
    backgroundColor: "var(--surface)",
    border: "1px solid var(--line)",
    borderRadius: 14,
    padding: "10px 12px",
    marginBottom: 10,
  },
  trackCover: {
    width: 54,
    height: 54,
    borderRadius: 10,
    overflow: "hidden",
    backgroundColor: "var(--input)",
    border: "1px solid var(--line)",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    flexShrink: 0,
  },
  trackTitle: { fontSize: 14, fontWeight: 700, color: "var(--on-surface)" },
  trackArtist: { fontSize: 12, color: "var(--muted)", marginTop: 2 },
  trackLinks: { display: "flex", gap: 12, marginTop: 6, flexWrap: "wrap" },
  trackLink: { fontSize: 11, fontWeight: 700, textDecoration: "none" },

  wordGrid: { display: "flex", flexWrap: "wrap", gap: 8 },
  wordCard: {
    position: "relative",
    backgroundColor: "var(--surface)",
    border: "1.5px solid",
    borderRadius: 14,
    minWidth: 150,
  },
  wordBody: {
    display: "flex",
    flexDirection: "column",
    alignItems: "flex-start",
    gap: 2,
    padding: "10px 26px 10px 14px",
    background: "transparent",
    border: "none",
    cursor: "pointer",
    fontFamily: "inherit",
    textAlign: "left",
    width: "100%",
  },
  wordInfoBtn: {
    position: "absolute",
    top: 5,
    right: 5,
    background: "transparent",
    border: "none",
    cursor: "pointer",
    padding: 3,
    lineHeight: 0,
  },
  pendingCard: {
    display: "flex",
    alignItems: "center",
    gap: 10,
    backgroundColor: "var(--surface)",
    border: "1.5px dashed",
    borderRadius: 14,
    padding: "10px 12px",
    marginBottom: 8,
  },
  wordTerm: { fontSize: 14, fontWeight: 800 },
  wordTr: { fontSize: 12, color: "var(--on-surface)" },
  wordLesson: { fontSize: 9, color: "var(--muted)", marginTop: 3 },
  wordBig: { fontSize: 26, fontWeight: 800, marginBottom: 4 },
  wordBigTr: { fontSize: 16, color: "var(--on-surface)", marginBottom: 12 },
  wordDraft: { display: "flex", alignItems: "center", gap: 6, marginBottom: 8 },
  wordHeadRow: { display: "flex", alignItems: "center", gap: 6, marginBottom: 6 },
  wordHeadCell: {
    flex: 1,
    fontSize: 11,
    fontWeight: 700,
    color: "var(--muted)",
    paddingLeft: 4,
  },
  wordDash: { color: "var(--muted)", fontSize: 13, flexShrink: 0 },

  fabBtn: {
    position: "fixed",
    left: 18,
    right: 18,
    bottom: 76,
    maxWidth: 520,
    margin: "0 auto",
    padding: "15px",
    border: "none",
    borderRadius: 14,
    color: "#fff",
    fontWeight: 700,
    fontSize: 14,
    cursor: "pointer",
    fontFamily: "inherit",
    zIndex: 20,
    boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
  },
  modalOverlay: {
    position: "fixed",
    inset: 0,
    backgroundColor: "rgba(0,0,0,0.55)",
    display: "flex",
    alignItems: "flex-end",
    justifyContent: "center",
    zIndex: 50,
    padding: "40px 0 0",
  },
  modalCard: {
    width: "100%",
    maxWidth: 520,
    maxHeight: "88vh",
    backgroundColor: "var(--bg)",
    borderTopLeftRadius: 22,
    borderTopRightRadius: 22,
    display: "flex",
    flexDirection: "column",
    overflow: "hidden",
    border: "1px solid var(--line)",
  },
  modalHead: {
    display: "flex",
    alignItems: "center",
    justifyContent: "space-between",
    padding: "16px 18px 12px",
    borderBottom: "1px solid var(--line)",
  },
  modalTitle: { fontSize: 15, fontWeight: 800 },
  modalClose: {
    border: "none",
    background: "transparent",
    fontSize: 26,
    lineHeight: 1,
    color: "var(--muted)",
    cursor: "pointer",
    padding: 0,
  },
  modalBody: { padding: "16px 18px 28px", overflowY: "auto" },
  cardActions: { display: "flex", gap: 4, padding: "0 10px 10px" },
  photoPreviewWrap: {
    width: "100%",
    borderRadius: 12,
    overflow: "hidden",
    border: "1px solid var(--line)",
    marginBottom: 10,
    lineHeight: 0,
  },
  photoPreview: { width: "100%", display: "block" },
  photoBtns: { display: "flex", gap: 8, marginBottom: 16, flexWrap: "wrap" },
  photoEmpty: {
    width: "100%",
    padding: "30px 12px",
    textAlign: "center",
    backgroundColor: "var(--surface)",
    border: "1px dashed var(--line)",
    borderRadius: 12,
    fontSize: 12,
    color: "var(--muted)",
    marginBottom: 10,
  },
  ownerRow: { display: "flex", gap: 6, flexWrap: "wrap" },
};

const SPARTAN_IMG =
  "data:image/jpeg;base64,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";


/* точка входу: без збірки, React підключається в index.html */
ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <DelvyCalendarSystem />
  </React.StrictMode>
);
