// cabinet.jsx — Personal cabinet screens

// ——— SHARED DATA (legacy mocks — kept only as fallback for the dead CabinetReading detail view) ———
const PERSONS = [
  { id: 1, name: 'Алина', subname: 'я', date: '14.07.1994', time: '11:32', place: 'Москва', sun: 'cancer', moon: 'scorpio', asc: 'virgo', primary: true },
  { id: 2, name: 'Дима', subname: 'партнёр', date: '03.11.1991', time: '06:15', place: 'Санкт-Петербург', sun: 'scorpio', moon: 'taurus', asc: 'sagittarius' },
  { id: 3, name: 'Маша', subname: 'мама', date: '22.04.1962', time: '—',     place: 'Воронеж',         sun: 'taurus',  moon: 'pisces', asc: 'leo' },
  { id: 4, name: 'Лёва', subname: 'сын',    date: '08.03.2019', time: '19:48', place: 'Москва',          sun: 'pisces',  moon: 'libra', asc: 'cancer' },
  { id: 5, name: 'Ева',  subname: 'подруга',date: '17.09.1995', time: '14:00', place: 'Тбилиси',        sun: 'virgo',   moon: 'gemini', asc: 'capricorn' },
];

const READINGS = [
  { id: 1, kind: 'Натальная карта', person: 'Алина', date: '12 мая 2026', status: 'ready', pages: 50, accent: 'gold', planets: ['sun','moon','mercury'] },
  { id: 2, kind: 'Совместимость', person: 'Алина × Дима', date: '02 мая 2026', status: 'ready', pages: 42, accent: 'rose', planets: ['venus','mars'] },
  { id: 3, kind: 'Прогноз на год', person: 'Алина', date: '18 апр 2026', status: 'ready', pages: 38, accent: 'celest', planets: ['jupiter','saturn'] },
  { id: 4, kind: 'Натальная карта', person: 'Лёва', date: '14 мар 2026', status: 'ready', pages: 50, accent: 'gold', planets: ['sun','moon'] },
  { id: 5, kind: 'Натальная карта', person: 'Маша', date: '03 фев 2026', status: 'ready', pages: 50, accent: 'gold', planets: ['sun','moon'] },
  { id: 6, kind: 'Прогноз на год', person: 'Дима', date: 'генерируется', status: 'pending', pages: 38, accent: 'celest', planets: ['jupiter','saturn'] },
];

const ZODIAC_RUS = { aries: 'Овен', taurus: 'Телец', gemini: 'Близнецы', cancer: 'Рак', leo: 'Лев', virgo: 'Дева', libra: 'Весы', scorpio: 'Скорпион', sagittarius: 'Стрелец', capricorn: 'Козерог', aquarius: 'Водолей', pisces: 'Рыбы' };

// ——— Shared cabinet data context ———
// Загружается один раз при монтировании Cabinet и расходится во все подстраницы,
// чтобы переключение вкладок не дёргало API повторно.
const CabinetDataCtx = React.createContext({
  user: null,
  persons: [],
  orders: [],
  loading: true,
  refetchPersons: async () => {},
  refetchOrders: async () => {},
});

// ——— Cabinet top bar (logo + email + logout) ———
const CabinetTopBar = () => {
  const { user } = React.useContext(CabinetDataCtx);
  return (
    <header style={{
      position: 'sticky', top: 0, zIndex: 50,
      padding: '14px clamp(16px, 5vw, 56px)',
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      background: 'rgba(10, 8, 22, 0.78)',
      backdropFilter: 'blur(20px) saturate(160%)',
      WebkitBackdropFilter: 'blur(20px) saturate(160%)',
      borderBottom: '1px solid var(--line-soft)',
    }}>
      <a href="/" style={{ display: 'flex', alignItems: 'center', gap: '10px', textDecoration: 'none', color: 'inherit' }}>
        <span style={{ display: 'inline-flex', color: 'var(--gold)' }}><LogoMark size={22} /></span>
        <span style={{ fontFamily: 'var(--font-display)', fontSize: '19px' }}>Star Path</span>
      </a>
      <div className="row gap-4" style={{ alignItems: 'center' }}>
        {user?.email && (
          <span className="mono muted" style={{ fontSize: '12px' }}>{user.email}</span>
        )}
        {user?.role === 'admin' && (
          <a href="/admin" className="mono" style={{ fontSize: '12px', color: 'var(--gold)', textDecoration: 'none' }}>Админ</a>
        )}
        <button
          onClick={() => window.__logout?.()}
          className="mono"
          style={{
            background: 'none', border: '0.5px solid var(--line)', cursor: 'pointer',
            padding: '6px 14px', borderRadius: '6px',
            color: 'var(--ink-secondary)', fontSize: '12px',
            fontFamily: 'var(--font-mono)', letterSpacing: '0.04em',
          }}
        >
          Выйти
        </button>
      </div>
    </header>
  );
};

// ——— Cabinet header / shell ———
const CabinetHeader = ({ subPage, onSubPage }) => {
  const items = [
    { id: 'home',    label: 'Сегодня' },
    { id: 'readings', label: 'Разборы' },
    { id: 'persons', label: 'Персоны' },
    { id: 'calendar', label: 'Транзиты' },
    { id: 'journal', label: 'Журнал' },
  ];
  return (
    <div className="subnav">
      <div className="row" style={{ gap: '8px', alignItems: 'center', flex: 1 }}>
        {items.map(it => (
          <button key={it.id} className={`subnav-link ${subPage === it.id ? 'active' : ''}`} onClick={() => onSubPage(it.id)}>
            {it.label}
          </button>
        ))}
      </div>
      <button className="btn btn-gold btn-sm" onClick={() => window.__nav?.('wizard')}>
        <IconPlus size={14} />
        Новый разбор
      </button>
    </div>
  );
};

// ——— Shared helpers (orders → reading cards) ———
// SERVICE_META — соответствие service-key → визуальные параметры карточек разбора.
const SERVICE_META = {
  natal:             { kind: 'Натальная карта',        accent: 'gold',   planets: ['sun','moon','mercury'], pages: 50 },
  year_ahead:        { kind: 'Прогноз на год',         accent: 'celest', planets: ['jupiter','saturn'],     pages: 38 },
  compatibility:     { kind: 'Совместимость',          accent: 'rose',   planets: ['venus','mars'],         pages: 42 },
  matrix:            { kind: 'Матрица судьбы',          accent: 'sage',   planets: ['sun','moon','mercury'], pages: 17 },
  personal_forecast: { kind: 'Индивидуальный гороскоп', accent: 'celest', planets: ['moon','mercury'],       pages: 12 },
};
const fmtOrderDate = (iso) => {
  if (!iso) return '—';
  try { return new Date(iso).toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', year: 'numeric' }); }
  catch (_) { return '—'; }
};
const orderToReading = (o, personsById) => {
  const meta = SERVICE_META[o.service] || SERVICE_META.natal;
  const person = (o.person_id && personsById[o.person_id]?.name)
    || o.person_name
    || (o.service === 'compatibility' && o.person2_id ? `${personsById[o.person_id]?.name || '—'} × ${personsById[o.person2_id]?.name || '—'}` : '')
    || 'Разбор';
  return {
    id: o.id,
    kind: meta.kind,
    person,
    date: o.status === 'ready' || o.status === 'pending'
      ? (o.status === 'pending' || o.status === 'generating' ? 'генерируется' : fmtOrderDate(o.ready_at || o.created_at))
      : fmtOrderDate(o.created_at),
    status: (o.status === 'pending' || o.status === 'generating') ? 'pending' : o.status,
    pages: meta.pages,
    accent: meta.accent,
    planets: meta.planets,
    pdf_url: o.pdf_url,
  };
};

// Helpers for person rendering — backend отдаёт born_date в ISO, время "HH:MM".
const isoToDot = (iso) => {
  if (!iso || iso.length < 10) return '';
  return `${iso.slice(8,10)}.${iso.slice(5,7)}.${iso.slice(0,4)}`;
};

// ——— Cabinet · Today (home) ———
const CabinetHome = () => {
  const { user, persons, orders, loading } = React.useContext(CabinetDataCtx);

  const personsById = React.useMemo(() => Object.fromEntries(persons.map(p => [p.id, p])), [persons]);
  const readings = React.useMemo(() => orders.map(o => orderToReading(o, personsById)), [orders, personsById]);
  const firstName = (user?.name || user?.email || '').split(/[\s@]/)[0] || 'друг';
  const ordersCount = orders.length;
  const today = new Date().toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', weekday: 'long' });

  return (
    <div className="section" style={{ padding: '40px 56px 80px' }} data-screen-label="03 Кабинет / Сегодня">
      <div className="rgrid" style={{ display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: '32px', marginBottom: '40px' }}>
        {/* Приветствие + статус */}
        <div className="card" style={{ padding: '40px', position: 'relative', overflow: 'hidden' }}>
          <div style={{ position: 'absolute', right: -120, top: -80, opacity: 0.5 }}>
            <NatalChartBg size={420} opacity={0.6} />
          </div>
          <div className="row gap-2" style={{ alignItems: 'center', marginBottom: '24px' }}>
            <span className="chip chip-gold"><span className="dot dot-gold" />Личный кабинет</span>
            <span className="mono muted" style={{ fontSize: '11px' }}>{today}</span>
          </div>
          <div className="display-md" style={{ fontSize: '40px', marginBottom: '20px', lineHeight: 1.1, position: 'relative' }}>
            Привет,<br/><span className="italic gold">{firstName}</span>.
          </div>
          <p style={{ fontSize: '15px', color: 'var(--ink-secondary)', lineHeight: 1.55, maxWidth: '480px', marginBottom: '24px', position: 'relative' }}>
            {ordersCount === 0
              ? 'У тебя пока нет разборов. Начни с натальной карты — 50 страниц о тебе за 1 990 ₽.'
              : `У тебя ${ordersCount} ${ordersCount === 1 ? 'разбор' : ordersCount < 5 ? 'разбора' : 'разборов'}. Открой любой ниже или закажи новый.`}
          </p>
          <div className="row gap-3" style={{ alignItems: 'center', position: 'relative' }}>
            <button className="btn btn-gold btn-sm" onClick={() => window.__nav?.('wizard')}>
              <IconPlus size={14} /> Новый разбор
            </button>
            {user?.email && (
              <span className="mono muted" style={{ fontSize: '11px' }}>{user.email}</span>
            )}
          </div>
        </div>

        {/* Live transits */}
        <div className="card" style={{ padding: '32px' }}>
          <div className="between" style={{ marginBottom: '24px' }}>
            <div className="label">Текущие транзиты</div>
            <button className="mono muted" style={{ background: 'none', border: 'none', fontSize: '11px', cursor: 'pointer' }}>обновить</button>
          </div>
          <div className="col gap-4">
            {[
              { p1: 'jupiter', p2: 'sun', aspect: 'тригон',     orb: '2°15\'', when: 'до 24 мая', good: true },
              { p1: 'saturn',  p2: 'moon', aspect: 'квадрат',   orb: '4°02\'', when: 'до 03 июня', good: false },
              { p1: 'venus',   p2: 'mercury', aspect: 'соединение', orb: '0°54\'', when: 'сегодня', good: true },
            ].map((t, i) => (
              <div key={i} className="row gap-3" style={{ alignItems: 'center', padding: '12px 0', borderBottom: i < 2 ? '1px solid var(--line-soft)' : 'none' }}>
                <div className="row gap-2" style={{ alignItems: 'center', width: 70 }}>
                  <div style={{ color: t.good ? 'var(--sage)' : 'var(--rose)' }}><PlanetGlyph kind={t.p1} size={18} /></div>
                  <span className="mono muted" style={{ fontSize: '11px' }}>{t.aspect === 'соединение' ? '⊙' : t.aspect === 'тригон' ? '△' : '□'}</span>
                  <div style={{ color: t.good ? 'var(--sage)' : 'var(--rose)' }}><PlanetGlyph kind={t.p2} size={18} /></div>
                </div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: '14px' }}>{t.aspect}</div>
                  <div className="mono muted" style={{ fontSize: '11px' }}>{t.when}</div>
                </div>
                <span className="mono" style={{ fontSize: '11px', color: 'var(--ink-muted)' }}>{t.orb}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Быстрый заказ — на основе сохранённых персон */}
      {persons.length > 0 && (
        <div style={{ marginBottom: '48px' }}>
          <div className="between between-stack" style={{ marginBottom: '20px', alignItems: 'flex-end' }}>
            <h2 className="display-md" style={{ fontSize: '36px' }}>Купить в <span className="italic gold">2 клика</span></h2>
            <span className="mono muted" style={{ fontSize: '11px' }}>на основе сохранённых персон</span>
          </div>
          <div className="rgrid-2" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px' }}>
            {persons.slice(0, 3).map((p) => {
              const dot = isoToDot(p.born_date);
              return (
                <button key={p.id}
                  onClick={() => { window.location.href = `/order/new?person=${encodeURIComponent(p.id)}`; }}
                  className="card" style={{ textAlign: 'left', cursor: 'pointer', border: '1px solid var(--line)', padding: '20px', background: 'var(--bg-raised)' }}>
                  <div className="between" style={{ marginBottom: '16px' }}>
                    <div className="dot" style={{ background: 'var(--gold)' }} />
                    <IconArrowUpRight size={14} />
                  </div>
                  <div style={{ fontSize: '17px', marginBottom: '6px' }}>Натальная карта · {p.name}</div>
                  <div className="mono muted" style={{ fontSize: '11px', marginBottom: '20px' }}>
                    {p.name}{dot ? ` · ${dot}` : ''}{p.born_time ? ` · ${p.born_time}` : ''}
                  </div>
                  <span className="mono gold" style={{ fontSize: '13px' }}>1 990 ₽</span>
                </button>
              );
            })}
          </div>
        </div>
      )}

      {/* Недавние разборы */}
      <div>
        <div className="between between-stack" style={{ marginBottom: '20px', alignItems: 'flex-end' }}>
          <h2 className="display-md" style={{ fontSize: '36px' }}>Недавние <span className="italic gold">разборы</span></h2>
          {readings.length > 3 && (
            <button className="btn btn-ghost btn-sm" onClick={() => window.__navSub?.('readings')}>Все разборы <IconArrowRight size={12} /></button>
          )}
        </div>
        {loading ? (
          <div className="muted" style={{ fontSize: '14px', padding: '20px 0' }}>Загружаем твои разборы…</div>
        ) : readings.length === 0 ? (
          <div className="card" style={{ padding: '32px', background: 'var(--bg-raised)', textAlign: 'center' }}>
            <div className="display-md" style={{ fontSize: '22px', marginBottom: '12px' }}>
              Здесь пока <span className="italic gold">пусто</span>
            </div>
            <p className="muted" style={{ fontSize: '14px', marginBottom: '20px', maxWidth: '420px', margin: '0 auto 20px' }}>
              Создай свой первый разбор — это 50 страниц о тебе, готовые за 2 минуты.
            </p>
            <button className="btn btn-gold btn-sm" onClick={() => window.__nav?.('wizard')}>
              <IconPlus size={14} /> Создать первый разбор
            </button>
          </div>
        ) : (
          <div className="rgrid-2" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px' }}>
            {readings.slice(0, 3).map(r => (
              <ReadingCard key={r.id} r={r} onClick={() => { window.location.href = `/order/${r.id}`; }} />
            ))}
          </div>
        )}
      </div>
    </div>
  );
};

// ——— Reading card ———
const ReadingCard = ({ r, onClick }) => (
  <button onClick={onClick} className="card" style={{
    textAlign: 'left', cursor: 'pointer',
    padding: '24px',
    background: 'var(--bg-raised)',
    transition: 'border-color 160ms',
  }} onMouseEnter={e => e.currentTarget.style.borderColor = 'var(--gold-dim)'} onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--line)'}>
    <div className="between" style={{ marginBottom: '24px' }}>
      <span className="chip" style={{
        color: `var(--${r.accent})`,
        borderColor: `color-mix(in oklab, var(--${r.accent}) 50%, transparent)`,
        background: `color-mix(in oklab, var(--${r.accent}) 10%, transparent)`,
      }}>{r.kind}</span>
      {r.status === 'pending'
        ? <span className="mono" style={{ fontSize: '10px', color: 'var(--gold)' }}>генерируется...</span>
        : <span className="mono muted" style={{ fontSize: '10px' }}>{r.pages} стр.</span>}
    </div>
    <div className="row gap-3" style={{ marginBottom: '20px' }}>
      {r.planets.map((pl, j) => (
        <div key={j} style={{ width: 28, height: 28, borderRadius: '50%', border: '1px solid var(--line)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: `var(--${r.accent})` }}>
          <PlanetGlyph kind={pl} size={14} />
        </div>
      ))}
    </div>
    <div className="display-md" style={{ fontSize: '22px', marginBottom: '6px', lineHeight: 1.1 }}>{r.person}</div>
    <div className="between">
      <span className="mono muted" style={{ fontSize: '11px' }}>{r.date}</span>
      <IconArrowRight size={14} style={{ color: 'var(--ink-muted)' }} />
    </div>
  </button>
);

// ——— Cabinet · Readings list ———
const CabinetReadings = () => {
  const { persons, orders, loading } = React.useContext(CabinetDataCtx);
  const [filter, setFilter] = React.useState('all');

  const personsById = React.useMemo(() => Object.fromEntries(persons.map(p => [p.id, p])), [persons]);
  const readings = React.useMemo(() => orders.map(o => orderToReading(o, personsById)), [orders, personsById]);

  const tabs = [
    { id: 'all', label: 'Все', count: readings.length },
    { id: 'natal', label: 'Натальные карты', count: readings.filter(r => r.kind === 'Натальная карта').length },
    { id: 'forecast', label: 'Прогнозы', count: readings.filter(r => r.kind === 'Прогноз на год').length },
    { id: 'compat', label: 'Совместимость', count: readings.filter(r => r.kind === 'Совместимость').length },
  ];
  const filtered = filter === 'all' ? readings : readings.filter(r => {
    if (filter === 'natal') return r.kind === 'Натальная карта';
    if (filter === 'forecast') return r.kind === 'Прогноз на год';
    return r.kind === 'Совместимость';
  });

  return (
    <div className="section" style={{ padding: '40px 56px 80px' }} data-screen-label="04 Кабинет / Разборы">
      <div className="between between-stack" style={{ marginBottom: '40px', alignItems: 'flex-end' }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: '14px' }}>{readings.length} разборов</div>
          <h1 className="display-lg">Мои <span className="italic gold">разборы</span></h1>
        </div>
        <div className="row gap-3">
          <button className="btn btn-icon"><IconSearch size={16} /></button>
          <button className="btn btn-icon"><IconFilter size={16} /></button>
        </div>
      </div>

      {/* Tabs */}
      <div className="row gap-2" style={{ marginBottom: '32px', flexWrap: 'wrap' }}>
        {tabs.map(t => (
          <button key={t.id} onClick={() => setFilter(t.id)} className="chip" style={{
            cursor: 'pointer',
            background: filter === t.id ? 'var(--ink-primary)' : 'var(--bg-elevated)',
            color: filter === t.id ? 'var(--bg-base)' : 'var(--ink-secondary)',
            borderColor: filter === t.id ? 'var(--ink-primary)' : 'var(--line)',
            padding: '8px 14px',
            fontSize: '12px',
          }}>
            {t.label} <span className="mono" style={{ opacity: 0.6, marginLeft: 4 }}>{t.count}</span>
          </button>
        ))}
      </div>

      {loading ? (
        <div className="muted" style={{ fontSize: '14px', padding: '20px 0' }}>Загружаем твои разборы…</div>
      ) : filtered.length === 0 ? (
        <div className="card" style={{ padding: '40px', background: 'var(--bg-raised)', textAlign: 'center' }}>
          <div className="display-md" style={{ fontSize: '24px', marginBottom: '12px' }}>
            {readings.length === 0
              ? <>Пока нет ни одного <span className="italic gold">разбора</span></>
              : <>В этой категории <span className="italic gold">пусто</span></>}
          </div>
          <p className="muted" style={{ fontSize: '14px', marginBottom: '20px', maxWidth: '420px', margin: '0 auto 20px' }}>
            {readings.length === 0
              ? 'Создай свой первый разбор — 50 страниц о тебе за 2 минуты.'
              : 'Попробуй другой фильтр или закажи новый разбор.'}
          </p>
          <button className="btn btn-gold btn-sm" onClick={() => window.__nav?.('wizard')}>
            <IconPlus size={14} /> Новый разбор
          </button>
        </div>
      ) : (
        <div className="rgrid-2" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '20px' }}>
          {filtered.map(r => (
            <ReadingCard key={r.id} r={r} onClick={() => { window.location.href = `/order/${r.id}`; }} />
          ))}
        </div>
      )}
    </div>
  );
};

// ——— Cabinet · Persons ———
// Преобразуем относительную «роль» к компактному отображению.
// Бэкенд хранит role в поле relation (mom / partner / self / ...).
const RELATION_RUS = {
  self: 'я',
  partner: 'партнёр',
  mom: 'мама',
  dad: 'папа',
  mother: 'мама',
  father: 'папа',
  child: 'ребёнок',
  son: 'сын',
  daughter: 'дочь',
  friend: 'друг',
  sister: 'сестра',
  brother: 'брат',
  family: 'семья',
  other: 'другое',
};
const relationLabel = (rel) => {
  if (!rel) return '';
  const key = String(rel).toLowerCase();
  return RELATION_RUS[key] || rel;
};

const PersonCard = ({ p, onEdit, onOrder }) => {
  // p: либо backend-DTO (id строка, born_date "YYYY-MM-DD", born_time "HH:MM", place, relation, is_default),
  // либо legacy-мок (date, time, place, subname, sun/moon/asc).
  const isBackend = typeof p.id === 'string' && (p.born_date !== undefined || p.relation !== undefined || p.has_birth !== undefined);

  const displayName = p.name || '—';
  const subname = isBackend ? relationLabel(p.relation) : (p.subname || '');
  const dateText = isBackend ? (isoToDot(p.born_date) || '—') : (p.date || '—');
  const timeText = isBackend ? (p.born_time || '—') : (p.time || '—');
  const placeText = p.place || '—';
  const primary = isBackend ? !!p.is_default : !!p.primary;
  // legacy mock содержит явные знаки sun/moon/asc, у backend их нет до полного расчёта.
  const sunSign = !isBackend ? p.sun : null;
  const moonSign = !isBackend ? p.moon : null;
  const ascSign = !isBackend ? p.asc : null;

  return (
    <div className="card" style={{ padding: '24px', position: 'relative' }}>
      {primary && <div style={{ position: 'absolute', top: 16, right: 16 }}>
        <span className="chip chip-gold" style={{ fontSize: '10px' }}>я</span>
      </div>}
      <div className="row gap-4" style={{ alignItems: 'flex-start', marginBottom: '20px' }}>
        <div style={{ width: 56, height: 56, borderRadius: '50%', border: '1.5px solid var(--gold)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--gold)' }}>
          {sunSign
            ? <ZodiacGlyph kind={sunSign} size={28} />
            : <PlanetGlyph kind="sun" size={26} />}
        </div>
        <div style={{ flex: 1 }}>
          <div className="display-md" style={{ fontSize: '26px', lineHeight: 1.1 }}>{displayName}</div>
          {subname && (
            <div className="mono muted" style={{ fontSize: '11px', marginTop: '4px', letterSpacing: '0.08em', textTransform: 'uppercase' }}>{subname}</div>
          )}
        </div>
      </div>

      <div className="col gap-2" style={{ marginBottom: '20px' }}>
        <div className="row" style={{ alignItems: 'center', gap: '10px', fontSize: '13px' }}>
          <IconCalendar size={14} style={{ color: 'var(--ink-muted)' }} />
          <span className="mono">{dateText}</span>
          <span className="mono muted" style={{ marginLeft: 'auto', fontSize: '12px' }}>{timeText}</span>
        </div>
        <div className="row" style={{ alignItems: 'center', gap: '10px', fontSize: '13px' }}>
          <IconPin size={14} style={{ color: 'var(--ink-muted)' }} />
          <span>{placeText}</span>
        </div>
      </div>

      {sunSign && (
        <div className="row gap-2" style={{ marginBottom: '20px', flexWrap: 'wrap' }}>
          <span className="chip" style={{ gap: '6px' }}>
            <PlanetGlyph kind="sun" size={12} /> {ZODIAC_RUS[sunSign]}
          </span>
          {moonSign && (
            <span className="chip" style={{ gap: '6px' }}>
              <PlanetGlyph kind="moon" size={12} /> {ZODIAC_RUS[moonSign]}
            </span>
          )}
          {ascSign && (
            <span className="chip" style={{ gap: '6px' }}>
              <span className="mono" style={{ fontSize: '10px' }}>ASC</span> {ZODIAC_RUS[ascSign]}
            </span>
          )}
        </div>
      )}

      <div className="row gap-2">
        <button className="btn btn-ghost btn-sm" style={{ flex: 1 }} onClick={() => onEdit?.(p)}>
          Редактировать
        </button>
        <button className="btn btn-ghost btn-sm" style={{ flex: 1 }} onClick={() => (onOrder ? onOrder(p) : (window.location.href = `/order/new?person=${encodeURIComponent(p.id)}`))}>
          Заказать разбор
        </button>
      </div>
    </div>
  );
};

const NewPersonCard = ({ onClick }) => (
  <button onClick={onClick} style={{
    border: '1.5px dashed var(--line)',
    borderRadius: '18px',
    padding: '24px',
    background: 'transparent',
    cursor: 'pointer',
    minHeight: '320px',
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    gap: '16px',
    color: 'var(--ink-muted)',
    transition: 'all 200ms',
  }}
    onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--gold)'; e.currentTarget.style.color = 'var(--gold)'; }}
    onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.color = 'var(--ink-muted)'; }}>
    <div style={{ width: 56, height: 56, borderRadius: '50%', border: '1.5px dashed currentColor', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <IconPlus size={24} />
    </div>
    <div style={{ fontFamily: 'var(--font-display)', fontSize: '22px', fontStyle: 'italic' }}>Добавить персону</div>
    <div className="mono" style={{ fontSize: '11px', maxWidth: '160px', textAlign: 'center', lineHeight: 1.4 }}>
      для повторных разборов и совместимости
    </div>
  </button>
);

// Inline-редактор персоны — общий для PATCH (есть id) и POST (нет id).
const PersonEditor = ({ person, onClose, onSaved, onDeleted }) => {
  // person передаётся как объект backend-DTO (или пустой шаблон для создания).
  // Локальный стейт держим в виде «формы» — поля в человеческом виде.
  const [name, setName] = React.useState(person?.name || '');
  const [relation, setRelation] = React.useState(person?.relation || '');
  const [bornDate, setBornDate] = React.useState(person?.born_date || ''); // YYYY-MM-DD
  const [bornTime, setBornTime] = React.useState(person?.born_time || ''); // HH:MM
  const [place, setPlace] = React.useState(person?.place || '');
  const [gender, setGender] = React.useState(person?.gender || 'female'); // female|male
  const [tzName, setTzName] = React.useState(person?.tz_name || 'Europe/Moscow');
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState(null);

  const isNew = !person?.id;

  const save = async () => {
    setError(null);
    if (!name.trim()) {
      setError('Имя обязательно');
      return;
    }
    setSaving(true);
    try {
      const body = {
        name: name.trim(),
        born_date: bornDate || '',
        born_time: bornTime || '',
        tz_name: tzName || 'Europe/Moscow',
        place: place || '',
        relation: relation || '',
        gender: gender || 'female',
      };
      const url = isNew ? '/api/persons' : `/api/persons/${encodeURIComponent(person.id)}`;
      const method = isNew ? 'POST' : 'PATCH';
      const r = await fetch(url, {
        method,
        credentials: 'same-origin',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      });
      if (!r.ok) {
        let msg = 'Не удалось сохранить';
        try { const j = await r.json(); if (j?.error) msg = j.error; } catch (_) {}
        setError(msg);
        return;
      }
      await onSaved?.();
      onClose?.();
    } catch (e) {
      setError('Сетевая ошибка');
    } finally {
      setSaving(false);
    }
  };

  const remove = async () => {
    if (isNew) { onClose?.(); return; }
    if (!window.confirm(`Удалить персону «${name}»?`)) return;
    setSaving(true);
    try {
      const r = await fetch(`/api/persons/${encodeURIComponent(person.id)}`, {
        method: 'DELETE',
        credentials: 'same-origin',
      });
      if (!r.ok && r.status !== 204) {
        setError('Не удалось удалить');
        return;
      }
      await onDeleted?.();
      onClose?.();
    } catch (e) {
      setError('Сетевая ошибка');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 1000,
      background: 'rgba(0,0,0,0.7)', backdropFilter: 'blur(8px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: '40px',
    }} onClick={onClose}>
      <div className="card" onClick={e => e.stopPropagation()} style={{
        maxWidth: '720px', width: '100%',
        padding: '40px',
        background: 'var(--bg-raised)',
        maxHeight: '90vh', overflowY: 'auto',
      }}>
        <div className="between" style={{ marginBottom: '32px' }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: '8px' }}>{isNew ? 'Новая персона' : 'Редактирование'}</div>
            <h2 className="display-md" style={{ fontSize: '32px' }}>Данные персоны</h2>
          </div>
          <button className="btn btn-icon" onClick={onClose} disabled={saving}><IconClose size={16} /></button>
        </div>

        <div className="col gap-4">
          <div className="row gap-4 row-stack">
            <label className="field" style={{ flex: 1 }}>
              <span className="label">Имя</span>
              <input className="input" value={name} onChange={e => setName(e.target.value)} />
            </label>
            <label className="field" style={{ flex: 1 }}>
              <span className="label">Роль (для тебя)</span>
              <input className="input" value={relation} onChange={e => setRelation(e.target.value)} placeholder="мама / партнёр / подруга..." />
            </label>
          </div>
          <div className="row gap-4 row-stack">
            <label className="field" style={{ flex: 1 }}>
              <span className="label">Дата рождения</span>
              <input className="input mono" type="date" value={bornDate} onChange={e => setBornDate(e.target.value)} />
            </label>
            <label className="field" style={{ flex: 1 }}>
              <span className="label">Время — если знаешь</span>
              <input className="input mono" type="time" value={bornTime} onChange={e => setBornTime(e.target.value)} placeholder="—" />
            </label>
          </div>
          <label className="field">
            <span className="label">Место рождения</span>
            <input className="input" value={place} onChange={e => setPlace(e.target.value)} placeholder="Москва" />
          </label>
          <label className="field">
            <span className="label">Пол</span>
            <select className="input" value={gender} onChange={e => setGender(e.target.value)}>
              <option value="female">Женский</option>
              <option value="male">Мужской</option>
            </select>
            <span className="mono muted" style={{ fontSize: '11px', marginTop: '4px' }}>Чтобы разбор был в правильном роде: «ты родилась» / «ты родился».</span>
          </label>
          <label className="field">
            <span className="label">Часовой пояс</span>
            <input className="input mono" value={tzName} onChange={e => setTzName(e.target.value)} placeholder="Europe/Moscow" />
          </label>

          <div className="card" style={{ background: 'var(--bg-base)', padding: '16px', marginTop: '8px' }}>
            <div className="row gap-2" style={{ alignItems: 'center', marginBottom: '12px' }}>
              <IconShield size={14} style={{ color: 'var(--gold)' }} />
              <span className="mono" style={{ fontSize: '11px', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--ink-muted)' }}>Что мы рассчитаем</span>
            </div>
            <div className="row gap-3" style={{ flexWrap: 'wrap' }}>
              <span className="chip" style={{ gap: '6px' }}><PlanetGlyph kind="sun" size={12} /> Солнце</span>
              <span className="chip" style={{ gap: '6px' }}><PlanetGlyph kind="moon" size={12} /> Луна</span>
              <span className="chip" style={{ gap: '6px' }}><span className="mono" style={{ fontSize: '10px' }}>ASC</span></span>
              <span className="chip" style={{ gap: '6px' }}>+ 12 домов, аспекты</span>
            </div>
          </div>

          {error && (
            <div className="mono" style={{ color: 'var(--rose)', fontSize: '12px' }}>{error}</div>
          )}

          <div className="between" style={{ marginTop: '20px' }}>
            <button className="btn btn-ghost" style={{ color: 'var(--rose)' }} onClick={remove} disabled={saving || isNew}>
              Удалить персону
            </button>
            <div className="row gap-3">
              <button className="btn btn-ghost" onClick={onClose} disabled={saving}>Отмена</button>
              <button className="btn btn-gold" onClick={save} disabled={saving}>
                {saving ? 'Сохраняем…' : 'Сохранить'}
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

const CabinetPersons = () => {
  const { persons, loading, refetchPersons } = React.useContext(CabinetDataCtx);
  const [editing, setEditing] = React.useState(null);
  const [creating, setCreating] = React.useState(false);

  // Для блока совместимости — выбираем двоих из реальных персон.
  const [compatA, setCompatA] = React.useState('');
  const [compatB, setCompatB] = React.useState('');
  React.useEffect(() => {
    if (persons.length >= 1 && !compatA) setCompatA(persons[0].id);
    if (persons.length >= 2 && !compatB) setCompatB(persons[1].id);
  }, [persons]);

  return (
    <div className="section" style={{ padding: '40px 56px 80px' }} data-screen-label="05 Кабинет / Персоны">
      <div className="between between-stack" style={{ marginBottom: '40px', alignItems: 'flex-end' }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: '14px' }}>{persons.length} сохранены</div>
          <h1 className="display-lg">Мои <span className="italic gold">персоны</span></h1>
          <p style={{ color: 'var(--ink-muted)', marginTop: '12px', maxWidth: '480px' }}>
            Сохрани близких — заказывай разборы и совместимость в два клика, не вводя данные заново.
          </p>
        </div>
        <button className="btn btn-gold" onClick={() => setCreating(true)}>
          <IconPlus size={14} /> Новая персона
        </button>
      </div>

      {loading ? (
        <div className="muted" style={{ fontSize: '14px', padding: '20px 0' }}>Загружаем персоны…</div>
      ) : (
        <div className="rgrid-2" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '20px' }}>
          {persons.map(p => <PersonCard key={p.id} p={p} onEdit={setEditing} />)}
          <NewPersonCard onClick={() => setCreating(true)} />
        </div>
      )}

      {/* Compatibility builder */}
      {persons.length >= 2 && (
        <div className="card" style={{ marginTop: '48px', padding: '40px', background: 'var(--bg-raised)' }}>
          <div className="between" style={{ marginBottom: '32px' }}>
            <div>
              <div className="eyebrow" style={{ marginBottom: '8px', color: 'var(--rose)' }}>Совместимость</div>
              <h2 className="display-md" style={{ fontSize: '32px' }}>Сравни <span className="italic rose">двоих</span> из сохранённых</h2>
            </div>
          </div>
          <div className="row gap-6 row-stack" style={{ alignItems: 'center' }}>
            <select className="select" style={{ flex: 1 }} value={compatA} onChange={e => setCompatA(e.target.value)}>
              {persons.map(p => <option key={p.id} value={p.id}>{p.name}{p.relation ? ` · ${relationLabel(p.relation)}` : ''}</option>)}
            </select>
            <div style={{ position: 'relative', width: 56, height: 56, borderRadius: '50%', border: '1px solid var(--rose)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--rose)' }}>
              <IconHeart size={20} />
            </div>
            <select className="select" style={{ flex: 1 }} value={compatB} onChange={e => setCompatB(e.target.value)}>
              {persons.map(p => <option key={p.id} value={p.id}>{p.name}{p.relation ? ` · ${relationLabel(p.relation)}` : ''}</option>)}
            </select>
            <button
              className="btn btn-primary"
              style={{ background: 'var(--rose)', borderColor: 'var(--rose)' }}
              disabled={!compatA || !compatB || compatA === compatB}
              onClick={() => {
                const q = new URLSearchParams({ service: 'compatibility', person: compatA, person2: compatB });
                window.location.href = `/order/new?${q.toString()}`;
              }}
            >
              Заказать · 2 490 ₽ <IconArrowRight size={14} />
            </button>
          </div>
        </div>
      )}

      {editing && (
        <PersonEditor
          person={editing}
          onClose={() => setEditing(null)}
          onSaved={refetchPersons}
          onDeleted={refetchPersons}
        />
      )}
      {creating && (
        <PersonEditor
          person={{ name: '', relation: '', born_date: '', born_time: '', place: '', tz_name: 'Europe/Moscow' }}
          onClose={() => setCreating(false)}
          onSaved={refetchPersons}
        />
      )}
    </div>
  );
};

// ——— Cabinet · Reading detail (dead code — навигация теперь идёт на /order/{id}) ———
const CabinetReading = ({ reading, onBack }) => {
  const r = reading || READINGS[0];
  const [page, setPage] = React.useState(7);
  return (
    <div className="section" style={{ padding: '32px 56px 80px' }} data-screen-label="06 Кабинет / Карточка разбора">
      <button onClick={onBack} className="btn btn-ghost btn-sm" style={{ marginBottom: '32px' }}>
        <IconArrowLeft size={14} /> К разборам
      </button>

      <div className="rgrid" style={{ display: 'grid', gridTemplateColumns: '1fr 1.4fr', gap: '40px' }}>
        {/* Left — metadata + chart */}
        <div>
          <div className="eyebrow" style={{ marginBottom: '14px' }}>{r.kind}</div>
          <h1 className="display-lg" style={{ marginBottom: '24px', fontSize: '64px' }}>
            <span className="italic">{r.person}</span>
          </h1>

          <div className="card" style={{ padding: '24px', marginBottom: '20px', background: 'var(--bg-raised)' }}>
            <div className="col gap-3">
              <div className="between" style={{ fontSize: '13px' }}>
                <span className="mono muted">Создан</span>
                <span className="mono">{r.date}</span>
              </div>
              <div className="divider" />
              <div className="between" style={{ fontSize: '13px' }}>
                <span className="mono muted">Объём</span>
                <span className="mono">{r.pages} страниц</span>
              </div>
              <div className="divider" />
              <div className="between" style={{ fontSize: '13px' }}>
                <span className="mono muted">Модель</span>
                <span className="mono">DeepSeek + Swiss Eph.</span>
              </div>
              <div className="divider" />
              <div className="between" style={{ fontSize: '13px' }}>
                <span className="mono muted">Версия</span>
                <span className="mono">v2.3 / 2026</span>
              </div>
            </div>
          </div>

          <div className="row gap-2" style={{ marginBottom: '24px' }}>
            <button className="btn btn-gold" style={{ flex: 1 }}>
              <IconDownload size={14} /> Скачать PDF
            </button>
            <button className="btn btn-icon"><IconRefresh size={14} /></button>
          </div>

          <div className="card" style={{ padding: '20px', background: 'var(--bg-raised)' }}>
            <div className="label" style={{ marginBottom: '16px' }}>Главные размещения</div>
            <div className="col gap-3">
              {[
                { p: 'sun', label: 'Солнце', sign: 'cancer', house: '4' },
                { p: 'moon', label: 'Луна', sign: 'scorpio', house: '8' },
                { p: 'venus', label: 'Венера', sign: 'gemini', house: '3' },
                { p: 'mars', label: 'Марс', sign: 'libra', house: '7' },
              ].map((pl, i) => (
                <div key={i} className="between">
                  <div className="row gap-3" style={{ alignItems: 'center' }}>
                    <div className="gold"><PlanetGlyph kind={pl.p} size={16} /></div>
                    <span style={{ fontSize: '14px' }}>{pl.label}</span>
                  </div>
                  <div className="row gap-2" style={{ alignItems: 'center' }}>
                    <ZodiacGlyph kind={pl.sign} size={14} />
                    <span className="mono muted" style={{ fontSize: '11px' }}>{ZODIAC_RUS[pl.sign]}</span>
                    <span className="mono" style={{ fontSize: '11px', color: 'var(--gold)' }}>·  {pl.house}d</span>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* Right — PDF reader */}
        <div className="card" style={{ padding: 0, background: 'var(--bg-elevated)', overflow: 'hidden' }}>
          {/* Chapter nav */}
          <div className="between" style={{ padding: '16px 24px', borderBottom: '1px solid var(--line)' }}>
            <div className="row gap-2" style={{ alignItems: 'center' }}>
              <button className="btn btn-icon" onClick={() => setPage(Math.max(1, page - 1))}><IconArrowLeft size={14} /></button>
              <button className="btn btn-icon" onClick={() => setPage(Math.min(r.pages, page + 1))}><IconArrowRight size={14} /></button>
              <span className="mono muted" style={{ fontSize: '12px', marginLeft: '8px' }}>стр. {page} / {r.pages}</span>
            </div>
            <div className="row gap-2">
              <button className="chip" style={{ cursor: 'pointer' }}>Главы</button>
              <button className="btn btn-icon"><IconBook size={14} /></button>
            </div>
          </div>

          {/* PDF page */}
          <div style={{ padding: '48px 56px', minHeight: '640px', position: 'relative', maxHeight: '70vh', overflow: 'auto' }}>
            <div style={{ position: 'absolute', top: '40px', right: '56px', opacity: 0.3 }}>
              <NatalChart size={140} variant="tiny" showHouses={false} showAspects={false} animated={false} glow={false} />
            </div>
            <div className="label" style={{ marginBottom: '12px' }}>Глава 1 · Ядро личности</div>
            <h2 className="display-md" style={{ fontSize: '34px', marginBottom: '24px', lineHeight: 1.1, maxWidth: '420px' }}>
              Солнце в <span className="italic gold">Раке</span>,<br/>Луна в <span className="italic">Скорпионе</span>.
            </h2>
            <p style={{ fontFamily: 'var(--font-display)', fontSize: '19px', lineHeight: 1.55, color: 'var(--ink-secondary)', marginBottom: '20px', maxWidth: '540px' }}>
              Ты родилась с парадоксом внутри: мягкая внешне (Рак), но с глубоким, иногда тёмным внутренним миром (Скорпион). Это даёт тебе редкий дар — видеть людей насквозь, оставаясь при этом доброй.
            </p>
            <p style={{ fontFamily: 'var(--font-display)', fontSize: '17px', lineHeight: 1.6, color: 'var(--ink-secondary)', marginBottom: '20px', maxWidth: '540px' }}>
              Эмоциональная палитра — от лёгкой меланхолии до экстатической вовлечённости. Когда что-то цепляет — ты вкладываешься на 200%. Когда отстраняешься — это надолго.
            </p>
            <div style={{ borderLeft: '2px solid var(--gold)', padding: '12px 20px', margin: '32px 0', maxWidth: '480px' }}>
              <div className="label gold" style={{ marginBottom: '8px' }}>Что с этим делать</div>
              <p style={{ fontSize: '14px', color: 'var(--ink-secondary)', lineHeight: 1.55 }}>
                Учись доверять первому впечатлению — оно у тебя точнее, чем у 80% людей. И не вини себя за «слишком много чувств» — это твой инструмент работы.
              </p>
            </div>
            <p style={{ fontFamily: 'var(--font-display)', fontSize: '17px', lineHeight: 1.6, color: 'var(--ink-secondary)', maxWidth: '540px' }}>
              На уровне отношений с собой — научись разделять «грустно потому что так звёзды» и «грустно потому что я устала». Луна в Скорпионе любит драматизировать...
            </p>
          </div>
        </div>
      </div>
    </div>
  );
};

// ——— Cabinet · Calendar (transits) ———
// Бэкенда для расчёта транзитов пока нет — данные демонстрационные.
const CabinetCalendar = () => {
  const days = Array.from({ length: 35 }, (_, i) => i - 2); // -2 to 32 (leading days)
  return (
    <div className="section" style={{ padding: '40px 56px 80px' }} data-screen-label="07 Кабинет / Транзиты">
      <div className="between between-stack" style={{ marginBottom: '24px', alignItems: 'flex-end' }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: '14px' }}>Май 2026</div>
          <h1 className="display-lg">Транзиты и <span className="italic gold">окна</span></h1>
        </div>
        <div className="row gap-2">
          <button className="btn btn-icon"><IconArrowLeft size={14} /></button>
          <button className="btn btn-ghost btn-sm">Сегодня</button>
          <button className="btn btn-icon"><IconArrowRight size={14} /></button>
        </div>
      </div>

      <div className="card" style={{ padding: '12px 16px', marginBottom: '24px', background: 'var(--bg-raised)' }}>
        <div className="muted" style={{ fontSize: '13px' }}>
          Транзиты сейчас демо — рассчитываем на следующей итерации.
        </div>
      </div>

      <div className="rgrid" style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: '32px' }}>
        {/* Calendar */}
        <div className="card" style={{ padding: '24px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '8px', marginBottom: '12px' }}>
            {['Пн','Вт','Ср','Чт','Пт','Сб','Вс'].map(d => (
              <div key={d} className="mono muted" style={{ fontSize: '11px', textAlign: 'center', letterSpacing: '0.1em' }}>{d}</div>
            ))}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: '8px' }}>
            {days.map((d, i) => {
              const inMonth = d > 0 && d <= 31;
              const isToday = d === 18;
              // dummy events
              const events = {
                3: ['gold'], 7: ['rose'], 12: ['celest', 'gold'], 14: ['sage'],
                18: ['gold', 'rose'], 21: ['celest'], 24: ['gold'], 28: ['rose', 'sage']
              }[d] || [];
              return (
                <div key={i} style={{
                  aspectRatio: '1',
                  borderRadius: '10px',
                  border: isToday ? '1.5px solid var(--gold)' : '1px solid var(--line-soft)',
                  background: isToday ? 'var(--gold-glow)' : 'transparent',
                  padding: '8px',
                  display: 'flex',
                  flexDirection: 'column',
                  justifyContent: 'space-between',
                  opacity: inMonth ? 1 : 0.25,
                  cursor: inMonth ? 'pointer' : 'default',
                }}>
                  <span className="mono" style={{ fontSize: '12px', color: isToday ? 'var(--gold)' : 'var(--ink-primary)' }}>
                    {inMonth ? d : (d <= 0 ? 30 + d : d - 31)}
                  </span>
                  <div className="row gap-2" style={{ alignItems: 'center' }}>
                    {events.map((e, j) => (
                      <span key={j} className="dot" style={{ background: `var(--${e})`, width: 4, height: 4 }} />
                    ))}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* Upcoming events */}
        <div>
          <div className="label" style={{ marginBottom: '16px' }}>Ближайшие окна</div>
          <div className="col gap-3">
            {[
              { date: '18 мая', label: 'Венера ☌ Меркурий', desc: 'Лёгкий день для денежных разговоров.', accent: 'gold' },
              { date: '21 мая', label: 'Меркурий → Близнецы', desc: 'Окно для важных коммуникаций до 4 июня.', accent: 'celest' },
              { date: '24 мая', label: 'Юпитер △ Солнце', desc: 'Удачный день для шага в новое.', accent: 'gold' },
              { date: '28 мая', label: 'Марс □ Сатурн', desc: 'Возможна фрустрация — не торопить.', accent: 'rose' },
              { date: '03 июня', label: 'Полнолуние в Стрельце', desc: 'Кульминация темы свободы и обучения.', accent: 'sage' },
            ].map((e, i) => (
              <div key={i} className="card" style={{ padding: '16px 20px', background: 'var(--bg-raised)' }}>
                <div className="row gap-3" style={{ alignItems: 'flex-start' }}>
                  <div style={{ width: 6, height: 6, borderRadius: '50%', background: `var(--${e.accent})`, marginTop: 8 }} />
                  <div style={{ flex: 1 }}>
                    <div className="between" style={{ marginBottom: '4px' }}>
                      <span style={{ fontSize: '14px' }}>{e.label}</span>
                      <span className="mono muted" style={{ fontSize: '11px' }}>{e.date}</span>
                    </div>
                    <p style={{ fontSize: '13px', color: 'var(--ink-muted)', lineHeight: 1.4 }}>{e.desc}</p>
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

// ——— Cabinet · Journal ———
// Бэкенда для записей журнала пока нет — данные демонстрационные.
const CabinetJournal = () => (
  <div className="section" style={{ padding: '40px 56px 80px' }} data-screen-label="08 Кабинет / Журнал">
    <div className="between between-stack" style={{ marginBottom: '24px', alignItems: 'flex-end' }}>
      <div>
        <div className="eyebrow" style={{ marginBottom: '14px' }}>23 записи</div>
        <h1 className="display-lg">Журнал <span className="italic gold">самонаблюдений</span></h1>
        <p className="muted" style={{ marginTop: '12px', maxWidth: '480px' }}>
          Отслеживай состояние и события — алгоритм сопоставит их с транзитами.
        </p>
      </div>
      <button className="btn btn-gold"><IconPlus size={14} /> Новая запись</button>
    </div>

    <div className="card" style={{ padding: '12px 16px', marginBottom: '24px', background: 'var(--bg-raised)' }}>
      <div className="muted" style={{ fontSize: '13px' }}>
        Журнал сейчас демо — сохранение и сопоставление с транзитами появятся на следующей итерации.
      </div>
    </div>

    {/* Mood input */}
    <div className="card" style={{ padding: '32px', marginBottom: '40px', background: 'var(--bg-raised)' }}>
      <div className="label" style={{ marginBottom: '16px' }}>Как ты сегодня?</div>
      <div className="row gap-3" style={{ marginBottom: '24px' }}>
        {[
          { label: 'тяжело', color: 'rose' },
          { label: 'устало', color: 'rose' },
          { label: 'ровно', color: 'celest' },
          { label: 'хорошо', color: 'sage' },
          { label: 'на подъёме', color: 'gold' },
        ].map((m, i) => (
          <button key={i} className="chip" style={{
            cursor: 'pointer',
            padding: '10px 16px',
            fontSize: '13px',
            color: i === 3 ? 'var(--bg-base)' : `var(--${m.color})`,
            background: i === 3 ? `var(--${m.color})` : `color-mix(in oklab, var(--${m.color}) 8%, transparent)`,
            borderColor: `color-mix(in oklab, var(--${m.color}) 50%, transparent)`,
          }}>{m.label}</button>
        ))}
      </div>
      <textarea className="textarea" placeholder="Что произошло сегодня? Что чувствуешь?" rows={3} />
    </div>

    {/* Entries */}
    <div className="col gap-3">
      {[
        { date: '17 мая 2026', mood: 'sage', moodLabel: 'хорошо', txt: 'Сделала презентацию — приняли без правок. Чувствую, что переход на новую работу был правильным. Венера на МС сегодня — наверное, оттуда уверенность.', transit: 'Венера на МС, тригон Юпитера' },
        { date: '14 мая 2026', mood: 'rose', moodLabel: 'тяжело', txt: 'Поругалась с Димой. Опять про деньги. Чувствую — что-то старое поднимается, не из этой ситуации.', transit: 'Марс □ Венера, тёмная Луна' },
        { date: '12 мая 2026', mood: 'celest', moodLabel: 'ровно', txt: 'Прочитала натальную карту целиком. Раздел про мать — попадание. Надо позвонить.', transit: '—' },
      ].map((e, i) => (
        <div key={i} className="card" style={{ padding: '24px 28px' }}>
          <div className="between" style={{ marginBottom: '12px' }}>
            <div className="row gap-3" style={{ alignItems: 'center' }}>
              <span className="mono muted" style={{ fontSize: '11px', letterSpacing: '0.1em' }}>{e.date}</span>
              <span className="chip" style={{ fontSize: '10px', color: `var(--${e.mood})`, background: `color-mix(in oklab, var(--${e.mood}) 10%, transparent)`, borderColor: `color-mix(in oklab, var(--${e.mood}) 40%, transparent)` }}>
                {e.moodLabel}
              </span>
            </div>
            <span className="mono muted" style={{ fontSize: '10px' }}>{e.transit}</span>
          </div>
          <p style={{ fontFamily: 'var(--font-display)', fontSize: '18px', lineHeight: 1.5, color: 'var(--ink-secondary)' }}>{e.txt}</p>
        </div>
      ))}
    </div>
  </div>
);

// ——— Main cabinet shell ———
const Cabinet = ({ subPage = 'home', onSubPage }) => {
  // Единый shared-стейт для всех подстраниц кабинета.
  const [data, setData] = React.useState({ user: null, persons: [], orders: [], loading: true });

  const fetchPersons = React.useCallback(async () => {
    try {
      const r = await fetch('/api/persons', { credentials: 'same-origin' });
      if (!r.ok) return;
      const j = await r.json();
      setData(d => ({ ...d, persons: j.persons || [] }));
    } catch (e) { console.warn('cabinet.persons.reload', e); }
  }, []);

  const fetchOrders = React.useCallback(async () => {
    try {
      const r = await fetch('/api/orders', { credentials: 'same-origin' });
      if (!r.ok) return;
      const j = await r.json();
      setData(d => ({ ...d, orders: j.orders || [] }));
    } catch (e) { console.warn('cabinet.orders.reload', e); }
  }, []);

  React.useEffect(() => {
    (async () => {
      try {
        const [meR, psR, ordR] = await Promise.all([
          fetch('/api/auth/me', { credentials: 'same-origin' }),
          fetch('/api/persons', { credentials: 'same-origin' }),
          fetch('/api/orders', { credentials: 'same-origin' }),
        ]);
        const me = meR.ok ? await meR.json() : null;
        const ps = psR.ok ? await psR.json() : { persons: [] };
        const ord = ordR.ok ? await ordR.json() : { orders: [] };
        setData({
          user: me?.user || me,
          persons: ps.persons || [],
          orders: ord.orders || [],
          loading: false,
        });
      } catch (e) {
        console.warn('cabinet.load', e);
        setData(d => ({ ...d, loading: false }));
      }
    })();
  }, []);

  // Expose nav so children can switch tabs
  React.useEffect(() => { window.__navSub = onSubPage; }, [onSubPage]);

  const ctxValue = React.useMemo(() => ({
    ...data,
    refetchPersons: fetchPersons,
    refetchOrders: fetchOrders,
  }), [data, fetchPersons, fetchOrders]);

  return (
    <CabinetDataCtx.Provider value={ctxValue}>
      <CabinetTopBar />
      <CabinetHeader subPage={subPage} onSubPage={onSubPage} />
      {subPage === 'home' && <CabinetHome />}
      {subPage === 'readings' && <CabinetReadings />}
      {subPage === 'persons' && <CabinetPersons />}
      {subPage === 'calendar' && <CabinetCalendar />}
      {subPage === 'journal' && <CabinetJournal />}
    </CabinetDataCtx.Provider>
  );
};

Object.assign(window, { Cabinet, PersonCard, PERSONS, READINGS, ZODIAC_RUS, CabinetReading });
