/* calc2-app.jsx — калькулятор сметы v2: общий компонент для всех ЛК.
   Роль определяется ?role= (точка входа из каждого ЛК) + переключатель для предпросмотра.
   Вкладки: Состав сметы (дерево) · Материалы · График · Сводка.
   Статусная воронка: Черновик → В работе → На согласовании → Готово. */
(function () {
  const C = window.Calc2;
  // defensive: некоторые сборки DS не экспортируют IconTile (visual-override §9) —
  // mountWhenReady требует его в REQ, а LKSection использует. Подставляем нейтральный шим.
  const _DS = window.DesignSystem_9e0a09 || (window.DesignSystem_9e0a09 = {});
  if (typeof _DS.IconTile !== 'function') {
    _DS.IconTile = function IconTile({ size, bg, color, children, style }) {
      const d = size === 'sm' ? 32 : 38;
      return React.createElement('span', { style: { display: 'inline-grid', placeItems: 'center', width: d, height: d, borderRadius: 10, background: bg || 'var(--secondary)', color: color || 'var(--text-secondary)', flexShrink: 0, ...(style || {}) } }, children);
    };
  }
  const { Card, Badge, Button } = window.DesignSystem_9e0a09;
  const { Ic, fmtRub, LKSection, Kpi, Shell, PageHead, mountWhenReady } = window;
  const { useState, useEffect } = React;
  const rub = C.rub;

  const HOME = { manager: 'manager.html', foreman: 'foreman.html', designer: 'designer.html', procurement: 'procurement.html', client: 'client.html', super: 'super.html' };
  const BRAND = { manager: 'Менеджер', foreman: 'Прораб', designer: 'Дизайнер', procurement: 'Закупки', client: 'Клиент', super: 'ОБИТЕЛЬ · Super' };

  function roleConfig(role) {
    const m = C.ROLE_META[role];
    return { brand: BRAND[role] || m.brand, brandSub: m.sub, mark: m.mark, markBg: m.tone, name: m.name, email: role + '@obitel.ru', ava: m.abbr, avaC: m.tone };
  }
  function navFor(role) {
    const calc = { label: 'Смета', items: [
      { id: 'works', icon: 'list-tree', label: 'Состав сметы' },
      { id: 'mat', icon: 'package', label: 'Материалы' },
      { id: 'schedule', icon: 'calendar-range', label: 'График' },
      { id: 'summary', icon: 'receipt', label: 'Сводка' },
    ] };
    const back = { label: 'Кабинет', items: [{ id: 'home', icon: 'arrow-left', label: 'Вернуться в кабинет' }] };
    if (role === 'manager' || role === 'super') back.items.push({ id: 'constructor', icon: 'sliders-horizontal', label: 'Конструктор (источник)' });
    return [calc, back];
  }

  /* ── шапка проекта (legacy — заменена Calc2IntakeHeader) ── */
  function ProjectHead({ est, setEst, role }) {
    return window.Calc2IntakeHeader
      ? React.createElement(window.Calc2IntakeHeader, { est, setEst, role })
      : null;
  }

  /* ── статусная полоса ── */
  function StatusStrip({ est, role }) {
    const st = C.STATUS[est.status];
    const tone = st.tone;
    const toneBg = { ink: ['var(--secondary)', 'var(--foreground)'], info: ['color-mix(in srgb, var(--info) 14%, var(--card))', 'var(--info)'], warning: ['var(--warning-soft)', 'var(--warning-strong)'], success: ['var(--success-soft)', 'var(--success-strong)'] }[tone];
    const idx = C.STATUS_ORDER.indexOf(est.status);
    const locked = C.isLocked(est.status);
    return (
      <div className="cc-status">
        <span className="cc-status-ic" style={{ background: toneBg[0], color: toneBg[1] }}><Ic n={st.icon} s={18} /></span>
        <div className="cc-status-main">
          <div className="cc-status-t">Статус сметы: {st.label}</div>
          <div className="cc-status-s">{st.desc}</div>
        </div>
        <div className="cc-steps">
          {C.STATUS_ORDER.map((s, i) => (
            <React.Fragment key={s}>
              {i > 0 && <span className="arr"><Ic n="chevron-right" s={13} /></span>}
              <span className={'cc-step' + (i < idx ? ' done' : i === idx ? ' cur' : '')}><span className="dot" />{C.STATUS[s].label}</span>
            </React.Fragment>
          ))}
        </div>
        {locked && role !== 'super' && <span className="cc-lock"><Ic n="lock" s={12} />редактор закрыт · правки через Change Request</span>}
      </div>
    );
  }

  /* ── опции (чипы-флаги из конструктора) ── */
  function OptionFlags({ est, setEst, role }) {
    const opts = C.options();
    if (!opts.length) return null;
    const canEdit = C.can(role, 'preset', est.status) || role === 'manager' || role === 'super';
    const on = (key) => (est.flags || []).includes(key);
    const toggle = (key) => {
      const f = new Set(est.flags || []);
      f.has(key) ? f.delete(key) : f.add(key);
      setEst({ ...est, flags: [...f] });
    };
    return (
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontSize: 11, fontWeight: 800, color: 'var(--text-tertiary)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: 9 }}>Опции проекта · из каталога</div>
        <div className="cc-flags">
          {opts.map((o) => (
            <button key={o.key} className={'cc-flag' + (on(o.key) ? ' on' : '')} style={{ '--fc': o.color }} disabled={!canEdit && !on(o.key)} onClick={() => canEdit && toggle(o.key)}>
              <span>{o.icon}</span>{o.name}
            </button>
          ))}
        </div>
      </div>
    );
  }

  /* ── материалы (BOM) ── */
  function MaterialsTab({ est, setEst, role }) {
    const { catalog } = C.loadCatalog();
    const m = C.materials(est, catalog);
    const proc = role === 'procurement' || role === 'super';
    const status = est.status;
    const area = est.project.area;

    // группировка по ЭТАП → РАБОТА (узлы с материалами) — видно, что к чему привязано
    const groups = [];
    catalog.forEach((ph) => (ph.stages || []).forEach((st) => {
      const entries = [];
      const stIncluded = (st.tasks || []).some((tk) => { const L = (tk.sub && tk.sub.length) ? tk.sub : [tk]; return L.some((n) => C.nodeState(est, n).included); });
      if (stIncluded && C.nodeMaterials(est, st.id, area).length) entries.push({ node: st, label: 'Этап целиком', kind: 'stage' });
      (st.tasks || []).forEach((tk) => {
        if (tk.sub && tk.sub.length) {
          if (tk.sub.some((n) => C.nodeState(est, n).included) && C.nodeMaterials(est, tk.id, area).length) entries.push({ node: tk, label: tk.name + ' · вся задача', kind: 'task' });
          tk.sub.forEach((su) => { if (C.nodeState(est, su).included && C.nodeMaterials(est, su.id, area).length) entries.push({ node: su, label: tk.name + ' › ' + su.name, kind: 'sub' }); });
        } else if (C.nodeState(est, tk).included && C.nodeMaterials(est, tk.id, area).length) {
          entries.push({ node: tk, label: tk.name, kind: 'task' });
        }
      });
      if (entries.length) groups.push({ phase: ph, stage: st, entries });
    }));

    const Agg = ({ items, kind }) => (
      <div>
        <div className="cc-matsub">{kind === 'finish' ? 'Чистовые' : 'Черновые'} · {items.length} поз · {rub(items.reduce((a, x) => a + x.client, 0))} ₽</div>
        {items.length === 0 ? <div style={{ fontSize: 13, color: 'var(--text-tertiary)', padding: '4px 2px' }}>Нет позиций</div> : (
          <table className="cc-mattbl">
            <thead><tr><th>Материал</th>{proc && <th>Поставщик</th>}<th className="num">Кол-во</th>{proc && <th className="num">Закупка/ед</th>}<th className="num">Цена/ед</th><th className="num">Итого</th></tr></thead>
            <tbody>
              {items.map((it) => (
                <tr key={it.id}>
                  <td><div className="cc-mat-name">{it.name}</div><div className="cc-mat-sku">{it.sku}{it.approval ? ' · треб. согл.' : ''}{it.lead ? ' · lead ' + it.lead + 'д' : ''} · {it.stages.join(', ')}</div></td>
                  {proc && <td style={{ color: 'var(--text-secondary)', fontSize: 12.5 }}>{it.supplier || '—'}</td>}
                  <td className="num">{it.qty} {it.unit}</td>
                  {proc && <td className="num" style={{ color: 'var(--text-secondary)' }}>{rub(it.unitCost)} ₽</td>}
                  <td className="num" style={{ color: 'var(--text-secondary)' }}>{rub(it.unitClient)} ₽</td>
                  <td className="num" style={{ fontWeight: 800 }}>{rub(it.client)} ₽</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    );

    return (
      <div className="cc-narrow">
        <PageHead eyebrow="Смета · материалы (BOM)" h1="Материалы" lede="Сгруппировано по работам — видно, какой материал к какой работе привязан. Количество и замену можно править прямо здесь в рамках своей роли; правки сохраняются и в составе сметы." />
        <div className="cc-kpis">
          <div className="cc-kpi"><i>Черновые</i><b>{rub(m.roughTotal)} ₽</b><u>{m.rough.length} позиций</u></div>
          <div className="cc-kpi"><i>Чистовые</i><b>{rub(m.finishTotal)} ₽</b><u>{m.finish.length} позиций</u></div>
          <div className="cc-kpi"><i>Согласований</i><b>{m.approvalCount}</b><u>чистовые</u></div>
          <div className="cc-kpi accent"><i>Материалы всего</i><b>{rub(m.total)} ₽</b><u>для клиента</u></div>
        </div>

        {groups.length === 0 && <div className="cc-empty">Включите работы в составе сметы — материалы появятся здесь.</div>}
        {groups.map((g) => (
          <LKSection key={g.stage.id} icon="package" title={g.stage.name} sub={g.phase.name + ' · ' + g.entries.length + ' раб. с материалами'} style={{ marginBottom: 14 }}>
            <div className="cc-matgrp">
              {g.entries.map((en) => {
                const mats = C.nodeMaterials(est, en.node.id, area);
                const tot = mats.reduce((a, x) => a + x.client, 0);
                return (
                  <div className="cc-matwork" key={en.node.id + en.kind}>
                    <div className="cc-matwork-h">
                      <span className="cc-matwork-nm">{en.label}</span>
                      {en.kind === 'stage' && <span className="cc-pill cat">этап</span>}
                      <span style={{ flex: 1 }} />
                      {tot > 0 && <span className="cc-money strong">{rub(tot)} ₽</span>}
                    </div>
                    <window.MatStrip node={en.node} est={est} setEst={setEst} role={role} status={status} area={area} flush />
                  </div>
                );
              })}
            </div>
          </LKSection>
        ))}

        <LKSection icon="table-2" cat="plumb" title="Сводная спецификация" sub="итоги по материалам — сумма по всем работам" style={{ marginTop: 4 }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            <Agg items={m.rough} kind="rough" />
            <Agg items={m.finish} kind="finish" />
          </div>
        </LKSection>
      </div>
    );
  }

  /* ── сводка + действия ── */
  function SummaryTab({ est, setEst, role, onSent }) {
    const s = C.summary(est);
    const stages = Object.values(s.works.byStage).filter((x) => x.total > 0).sort((a, b) => b.total - a.total);
    const maxStage = stages.length ? stages[0].total : 1;
    const canDiscount = C.can(role, 'discount', est.status);
    const showMargin = C.sees(role, 'margin');
    const setStatus = (status, what) => setEst(C.logAudit({ ...est, status }, C.ROLE_META[role].short, what));

    // решения клиента
    const decisions = Object.values(est.decisions || {});
    const rejected = decisions.filter((d) => d.state === 'rejected').length;

    return (
      <div className="cc-narrow">
        <PageHead eyebrow="Смета · сводка" h1="Итог по смете" lede="Работы и материалы, разбивка по этапам, скидка и срок. Финальную цену видят все роли; маржа — только Super." />
        {est.status === 'ready' && (
          <div className="lk-banner" style={{ marginBottom: 14, display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap' }}>
            <span className="lk-banner-s">{est.projectId ? 'Проект ' + est.projectId + ' создан' : 'Смета согласована — готова к запуску проекта'}</span>
            {est.projectId ? <a className="chip" href={'foreman-inbox.html?project=' + est.projectId}>У прораба →</a> : <a className="chip" href="manager-handoff.html">Перейти к handoff →</a>}
          </div>
        )}
        <div className="cc-kpis">
          <div className="cc-kpi"><i>Работы</i><b>{rub(s.works.client)} ₽</b><u>{s.works.lines} позиций</u></div>
          <div className="cc-kpi"><i>Материалы</i><b>{rub(s.mats.total)} ₽</b><u>черновые + чистовые</u></div>
          <div className="cc-kpi"><i>Срок</i><b>{s.calDays} дн</b><u>≈ {s.weeks} нед</u></div>
          {showMargin ? <div className="cc-kpi"><i>Маржа · Super</i><b>{s.marginPct}%</b><u>{rub(s.margin)} ₽</u></div>
            : <div className="cc-kpi"><i>Позиций</i><b>{s.works.lines + s.mats.rough.length + s.mats.finish.length}</b><u>работ + материалов</u></div>}
          <div className="cc-kpi accent"><i>Итого клиенту</i><b>{rub(s.total)} ₽</b><u>скидка {est.discount || 0}%</u></div>
        </div>

        <LKSection icon="bar-chart-3" cat="elec" title="Разбивка по этапам" sub="доля в стоимости работ" style={{ marginBottom: 16 }}>
          <div className="cc-bars">
            {stages.length === 0 && <div style={{ fontSize: 13, color: 'var(--text-tertiary)' }}>Нет включённых работ.</div>}
            {stages.map((st, i) => (
              <div className="cc-bar-row" key={i}>
                <div className="top"><span style={{ fontWeight: 600 }}><span style={{ display: 'inline-block', width: 8, height: 8, borderRadius: '50%', background: st.color, marginRight: 7 }} />{st.name}</span><b>{rub(st.total)} ₽</b></div>
                <div className="cc-bar"><span style={{ width: (st.total / maxStage * 100) + '%', background: st.color }} /></div>
              </div>
            ))}
          </div>
        </LKSection>

        <Card variant="glass" padding="lg">
          <div className="cc-sum">
            <div className="cc-sum-row"><span>Работы</span><span>{rub(s.works.client)} ₽</span></div>
            {s.works.packages && s.works.packages.lines > 0 && (
              <div className="cc-sum-row sub"><span>· в т.ч. пакеты услуг ({s.works.packages.lines} шаг.)</span><span>{rub(s.works.packages.total)} ₽</span></div>
            )}
            <div className="cc-sum-row"><span>Материалы</span><span>{rub(s.mats.total)} ₽</span></div>
            <div className="cc-sum-row sub"><span>Подытог</span><span>{rub(s.subtotal)} ₽</span></div>
            <div className="cc-sum-row"><span>Скидка{canDiscount ? <input type="number" min={0} max={50} value={est.discount} onChange={(e) => setEst({ ...est, discount: Math.min(50, Math.max(0, +e.target.value || 0)) })} className="cc-disc" /> : <b style={{ margin: '0 4px' }}>{est.discount || 0}</b>}%</span><span style={{ color: 'var(--destructive)' }}>−{rub(s.discountRub)} ₽</span></div>
            {showMargin && <div className="cc-sum-row"><span>Себестоимость работ (Super)</span><span style={{ color: 'var(--text-tertiary)' }}>{rub(s.works.cost)} ₽</span></div>}
            <div className="cc-sum-row total"><span>Итого клиенту</span><span>{rub(s.total)} ₽</span></div>
          </div>
          <ActionBar est={est} setEst={setEst} role={role} setStatus={setStatus} onSent={onSent} rejected={rejected} />
        </Card>

        {(est.audit || []).length > 0 && role !== 'client' && (
          <LKSection icon="history" cat="plumb" title="Аудит и изменения" sub={est.audit.length + ' событий'} style={{ marginTop: 16 }}>
            <div className="cc-audit">
              {est.audit.slice(0, 10).map((a, i) => (
                <div className="cc-audit-row" key={i}><span className="cc-audit-who">{a.who}</span><span className="cc-audit-what">{a.what}</span><span className="cc-audit-when">{C.timeAgo(a.at)}</span></div>
              ))}
            </div>
          </LKSection>
        )}
        {(est.changeRequests || []).length > 0 && (
          <LKSection icon="git-pull-request" cat="elec" title="Запросы на изменение" sub={est.changeRequests.length + ' шт'} style={{ marginTop: 16 }}>
            <div className="cc-audit">
              {est.changeRequests.map((cr) => (
                <div className="cc-audit-row" key={cr.id}><span className="cc-audit-who">{cr.author}</span><span className="cc-audit-what">{cr.note || 'Запрос на изменение сметы'}</span><span className="cc-audit-when">{C.timeAgo(cr.at)}</span></div>
              ))}
            </div>
          </LKSection>
        )}
      </div>
    );
  }

  function ActionBar({ est, setEst, role, setStatus, onSent, rejected }) {
    const status = est.status;
    const locked = C.isLocked(status);
    const btns = [];
    const save = <Button key="save" variant="ghost" size="md" iconLeft={<Ic n="save" s={15} />} onClick={() => { C.save(est); }}>Сохранить</Button>;
    const print = <Button key="print" variant="ghost" size="md" iconLeft={<Ic n="printer" s={15} />} onClick={() => window.print()}>Печать / PDF</Button>;

    if (role === 'manager') {
      if (status === 'draft') {
        btns.push(<Button key="h" variant="ghost" size="md" iconLeft={<Ic n="users" s={15} />} onClick={() => setStatus('internal', 'передал смету в работу команде')}>Передать прорабу / дизайнеру</Button>);
        btns.push(<Button key="s" variant="primary" size="md" iconLeft={<Ic n="send" s={15} />} onClick={() => { setStatus('client_review', 'отправил смету клиенту'); onSent && onSent(); }}>Отправить клиенту</Button>);
      } else if (status === 'internal') {
        btns.push(<Button key="s" variant="primary" size="md" iconLeft={<Ic n="send" s={15} />} onClick={() => { setStatus('client_review', 'отправил смету клиенту'); onSent && onSent(); }}>Отправить клиенту</Button>);
      } else if (locked) {
        btns.push(<Button key="cr" variant="primary" size="md" iconLeft={<Ic n="git-pull-request" s={15} />} onClick={() => setEst(C.openChangeRequest(est, 'Менеджер', 'Корректировка после согласования', []))}>Открыть Change Request</Button>);
      }
    } else if (role === 'foreman' || role === 'designer') {
      if (status === 'internal' || status === 'draft') {
        btns.push(<Button key="rd" variant="primary" size="md" iconLeft={<Ic n="check" s={15} />} onClick={() => setEst(C.logAudit(est, C.ROLE_META[role].short, 'подтвердил свою часть сметы'))}>Подтвердить мою часть</Button>);
      } else if (locked) {
        btns.push(<Button key="cr" variant="ghost" size="md" iconLeft={<Ic n="git-pull-request" s={15} />} onClick={() => setEst(C.openChangeRequest(est, C.ROLE_META[role].short, 'Замечание по составу', []))}>Запрос на изменение</Button>);
      }
    } else if (role === 'procurement') {
      btns.push(<Button key="rd" variant="primary" size="md" iconLeft={<Ic n="package-check" s={15} />} onClick={() => setEst(C.logAudit(est, 'Закупки', 'подтвердил готовность спецификации'))}>Готовность спецификации</Button>);
    } else if (role === 'client') {
      if (status === 'client_review') {
        btns.push(<Button key="r" variant="ghost" size="md" iconLeft={<Ic n="rotate-ccw" s={15} />} onClick={() => setStatus('internal', 'клиент отправил смету на доработку')}>На доработку</Button>);
        btns.push(<Button key="a" variant="primary" size="md" iconLeft={<Ic n="check-circle" s={15} />} disabled={rejected > 0} onClick={() => setStatus('ready', 'клиент согласовал смету')}>{rejected > 0 ? `Снимите ${rejected} отказ(ов)` : 'Согласовать смету'}</Button>);
      }
    } else if (role === 'super') {
      const next = { draft: 'internal', internal: 'client_review', client_review: 'ready', ready: 'draft' }[status];
      const nextLabel = { internal: 'В работу', client_review: 'На согласование', ready: 'Запустить проект', draft: 'Вернуть в черновик' }[next];
      btns.push(<Button key="n" variant="primary" size="md" iconLeft={<Ic n="rocket" s={15} />} onClick={() => setStatus(next, 'Super перевёл статус → ' + C.STATUS[next].label)}>{nextLabel}</Button>);
      if (locked) btns.push(<Button key="u" variant="ghost" size="md" iconLeft={<Ic n="unlock" s={15} />} onClick={() => setStatus('draft', 'Super разблокировал редактор')}>Разблокировать</Button>);
    }

    return <div className="cc-actions">{save}<div style={{ flex: 1 }} />{print}{btns}</div>;
  }

  /* ── APP ── */
  function App() {
    const q = new URLSearchParams(window.location.search);
    const initRole = C.ROLE_LIST.includes(q.get('role')) ? q.get('role') : 'manager';
    const dealId = q.get('deal') || 'D-404';
    const [role] = useState(initRole);
    const [tab, setTab] = useState('works');
    const [est, setEst] = useState(() => {
      const intake = window.loadSiteIntake && window.loadSiteIntake(dealId);
      const loaded = C.load(dealId);
      let base = loaded || C.blankEstimate({
        dealId,
        client: (intake && intake.clientName) || '',
        object: (intake && intake.address) || 'Объект',
        area: 52,
        status: 'draft',
      });
      if (!base.project.dealId) base.project.dealId = dealId;
      if (window.CalcIntakeReadiness && intake) {
        base = window.CalcIntakeReadiness.syncEstimateProject(base, intake);
      }
      return base;
    });
    const [sent, setSent] = useState(false);
    const [theme, setTheme] = useState(() => { try { return localStorage.getItem('remontpro_theme') === 'dark' ? 'dark' : 'light'; } catch (e) { return 'light'; } });
    useEffect(() => { C.save(est); }, [est]);
    useEffect(() => {
      const { catalog: cat } = C.loadCatalog();
      if (!cat || !cat.length) return;
      setEst((e) => C.applyConditionalInclusion(e, cat));
    }, []);
    useEffect(() => {
      const el = document.documentElement;
      if (theme === 'dark') el.setAttribute('data-theme', 'dark');
      else el.setAttribute('data-theme', 'light');
      try { localStorage.setItem('remontpro_theme', theme); } catch (e) {}
    }, [theme]);
    C.status = est.status;

    const { catalog, source, version } = C.loadCatalog();
    const s = C.summary(est);

    const go = (z) => {
      if (z === 'home') { window.location.href = HOME[role]; return; }
      if (z === 'constructor') { window.location.href = '../Конструктор проектов.html'; return; }
      setTab(z); setSent(false);
      const c = document.querySelector('.content'); if (c) c.scrollTop = 0;
    };

    const crumbMap = { works: 'Состав', mat: 'Материалы', schedule: 'График', summary: 'Сводка' };

    return (
      <Shell role={roleConfig(role)} nav={navFor(role)} active={tab} onNav={go} crumbs={['Калькулятор сметы', crumbMap[tab]]} tabNav>
        <div className="cc-wrap">
          <div className="cc-narrow">
            {/* тема (роль-предпросмотр убран: роль задаётся точкой входа ?role=) */}
            <div className="cc-rolebar">
              <button className="cc-theme" onClick={() => setTheme((t) => t === 'dark' ? 'light' : 'dark')}
                title={theme === 'dark' ? 'Светлая тема' : 'Тёмная тема'} aria-label="Переключить тему">
                <Ic n={theme === 'dark' ? 'sun' : 'moon'} s={15} />
                <span>{theme === 'dark' ? 'Светлая' : 'Тёмная'}</span>
              </button>
            </div>

            <ProjectHead est={est} setEst={setEst} role={role} />
            <StatusStrip est={est} role={role} />

            <div className="cc-source" style={{ marginBottom: 14 }}>
              <Ic n="link" s={13} />
              Источник: <b>живой каталог конструктора{source === 'published' ? ' (опубл. v' + (version || 1) + ')' : ''}</b> · структура и правила — только чтение
            </div>

            <div className="cc-tabs">
              <button className={tab === 'works' ? 'on' : ''} onClick={() => go('works')}><Ic n="list-tree" s={15} />Состав сметы</button>
              <button className={tab === 'mat' ? 'on' : ''} onClick={() => go('mat')}><Ic n="package" s={15} />Материалы<span className="cc-tab-n">{s.mats.rough.length + s.mats.finish.length}</span></button>
              <button className={tab === 'schedule' ? 'on' : ''} onClick={() => go('schedule')}><Ic n="calendar-range" s={15} />График</button>
              <button className={tab === 'summary' ? 'on' : ''} onClick={() => go('summary')}><Ic n="receipt" s={15} />Сводка</button>
            </div>
          </div>

          {tab === 'works' && (
            <div className="cc-narrow">
              {window.AssemblyPanel && (
                <window.AssemblyPanel est={est} setEst={setEst} role={role} dealId={dealId} />
              )}
              <OptionFlags est={est} setEst={setEst} role={role} />
              {window.Calc2Pkg && <window.Calc2Pkg.PackageChips est={est} setEst={setEst} role={role} />}
              <window.EstimateTree est={est} setEst={setEst} role={role} catalog={catalog} />
            </div>
          )}
          {tab === 'mat' && <MaterialsTab est={est} setEst={setEst} role={role} />}
          {tab === 'schedule' && <div className="cc-narrow"><window.ScheduleView est={est} setEst={setEst} role={role} catalog={catalog} /></div>}
          {tab === 'summary' && (
            sent ? (
              <div className="cc-narrow"><Card variant="glass" padding="lg"><div className="cc-success">
                <span className="cc-success-ic" style={{ background: 'var(--success)' }}><Ic n="send" s={28} c="#fff" sw={2.3} /></span>
                <div className="cc-success-t">Смета отправлена клиенту</div>
                <div className="cc-success-s">{est.project.client || 'Клиент'} получит смету на {rub(s.total)} ₽ на согласование. Статус → «На согласовании», редактор закрыт для правок (кроме Super) — изменения через Change Request.</div>
                <Button variant="ghost" size="md" style={{ marginTop: 8 }} iconLeft={<Ic n="arrow-left" s={15} />} onClick={() => setSent(false)}>Вернуться к смете</Button>
              </div></Card></div>
            ) : <SummaryTab est={est} setEst={setEst} role={role} onSent={() => setSent(true)} />
          )}
        </div>

        {tab !== 'summary' && (
          <button className="cc-fab" onClick={() => go('summary')}>
            <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
              <span className="cc-fab-l">Итого клиенту</span>
              <span className="cc-fab-v">{rub(s.total)} ₽</span>
            </span>
            <Ic n="arrow-right" s={16} c="var(--card)" />
          </button>
        )}
      </Shell>
    );
  }

  mountWhenReady(() => <App />);
})();
