/* ops2-team-analytics.jsx — зоны «Команда», «Аналитика» + drawer проекта */
(function () {
  const { Card, Badge, IconTile, Button, Input } = window.DesignSystem_9e0a09;
  const { CardHead, OpsWgt, OpsModal, Donut, SeriesChart, useOpsChartViz } = window;
  const O = () => window.OPS;

  function AnaFunnelSeries({ f, onOpen }) {
    const viz = useOpsChartViz('hbar');
    return (
      <SeriesChart
        labels={['Лиды', 'Встречи', 'Сметы', 'Договоры']}
        values={[f.leads, f.meetings, f.estimates, f.contracts]}
        viz={viz}
        h={viz === 'donut' ? 96 : 100}
        base={f.leads}
        onRowClick={onOpen}
      />
    );
  }

  function LeadSourcesChart({ sources }) {
    const viz = useOpsChartViz('hbar');
    const rows = (sources || []).slice(0, 5);
    const labels = rows.map((s) => s.label);
    const values = rows.map((s) => Math.round((s.share || 0) * 100));
    if (viz === 'hbar') {
      return (
        <div className="kart-mini-list">
          {rows.map((s, i) =>
            <div key={i} className="kart-mini-row">
              <div className="kart-mini-row-top"><span className="kart-mini-row-label">{s.label}</span><span className="kart-mini-row-val t-num">{Math.round(s.share * 100)}%</span></div>
              <div className="kart-mini-row-bar"><div className="kart-mini-row-fill" style={{ width: `${Math.round(s.share * 100)}%`, background: s.color }} /></div>
            </div>)}
        </div>
      );
    }
    return <SeriesChart labels={labels} values={values} viz={viz} h={100} unit="%" base={100} />;
  }

  function TeamLoadChart({ slices, center }) {
    const viz = useOpsChartViz('donut');
    if (viz === 'donut') {
      return (
        <div className="team-load-donut donut-no-legend">
          <Donut slices={slices} size={76} stroke={12} centerTop={center} centerBottom="загрузка" />
          <div className="team-load-keys">
            {slices.map((s, i) => (
              <div key={i} className="team-load-key"><span style={{ width: 8, height: 8, borderRadius: '50%', background: s.color }} />{s.label}<b className="t-num">{s.value}</b></div>
            ))}
          </div>
        </div>
      );
    }
    return (
      <SeriesChart
        labels={slices.map((s) => s.label)}
        values={slices.map((s) => s.value)}
        viz={viz}
        h={100}
      />
    );
  }

  function ZoneSeg({ tabs, active, onChange, ariaLabel }) {
    return (
      <div className="ov-pipe-seg seg zone-seg" role="tablist" aria-label={ariaLabel} style={{ marginBottom: 18 }}>
        {tabs.map(([k, l, ic]) =>
          <button key={k} type="button" role="tab" aria-selected={active === k} className={active === k ? 'on' : ''} onClick={() => onChange(k)}>
            <Ic n={ic} s={14} />{l}
          </button>
        )}
      </div>);
  }

  function TableCard({ title, sub, action, children }) {
    return (
      <Card variant="glass" padding="lg" style={{ overflow: 'hidden', gridColumn: '1 / -1' }}>
        <CardHead title={title} sub={sub} action={action} />
        <div className="ov-inset">
          <div className="tbl-scroll">{children}</div>
        </div>
      </Card>);
  }

  /* ============================================================
     КОМАНДА — вкладки: Реестр · Аналитика · Планирование · Табели · Встречи
     ============================================================ */
  const tSOFT = ['#c98a4a', '#6a9e78', '#6d83b8', '#9a86c4', '#c2a23e'];
  function tAggregate(records, groups) {
    const tc = records.length || 1;
    const tp = records.reduce((s, r) => s + (r.profit || 0), 0) || 1;
    return groups.map((g, i) => {
      const rs = records.filter(g.match);
      const profit = rs.reduce((s, r) => s + (r.profit || 0), 0);
      const durs = rs.filter((r) => r.durationDays > 0).map((r) => r.durationDays);
      const margins = rs.filter((r) => r.margin != null).map((r) => r.margin);
      return { label: g.label, color: tSOFT[i % tSOFT.length], count: rs.length, countShare: rs.length / tc,
        profitShare: profit / tp, avgDur: durs.length ? Math.round(durs.reduce((a, b) => a + b, 0) / durs.length) : null,
        avgMargin: margins.length ? Math.round(margins.reduce((a, b) => a + b, 0) / margins.length) : null };
    });
  }
  function TeamMiniRing({ slices, size = 68, stroke = 11 }) {
    const total = slices.reduce((s, x) => s + x.value, 0) || 1;
    const r = (size - stroke) / 2;
    const C = 2 * Math.PI * r;
    let acc = 0;
    return (
      <svg width={size} height={size} className="kart-donut-svg" style={{ flexShrink: 0, transform: 'rotate(-90deg)' }} aria-hidden="true">
        {slices.map((sl, i) => {
          const frac = sl.value / total;
          const dash = frac * C;
          const el = <circle key={i} cx={size / 2} cy={size / 2} r={r} fill="none" stroke={sl.color} strokeWidth={stroke} strokeDasharray={`${dash} ${C - dash}`} strokeDashoffset={-acc * C} />;
          acc += frac;
          return el;
        })}
      </svg>);
  }

  function TeamSlicesCompact({ byType, byArea, byHousing }) {
    const typeSegs = byType.filter((s) => s.count > 0);
    const slices = typeSegs.map((s) => ({ label: s.label, value: s.count, color: s.color }));
    const lead = typeSegs[0];
    const secondary = [
      { dim: 'Площадь', seg: byArea[0] },
      { dim: 'Жильё', seg: byHousing[0] },
    ].filter((x) => x.seg);
    return (
      <div className="team-slices-wgt">
        <div className="kart-donut-wgt">
          <div className="kart-donut-ring-wrap">
            <TeamMiniRing slices={slices} />
            <div className="kart-donut-center">
              <b className="t-num">{lead ? Math.round((lead && lead.countShare || 0) * 100) + '%' : '—'}</b>
              <span>тип ремонта</span>
            </div>
          </div>
          <ul className="kart-donut-keys">
            {typeSegs.slice(0, 3).map((s, i) => (
              <li key={i}><span style={{ background: s.color }} />{s.label}<b className="t-num">{Math.round((s && s.countShare || 0) * 100)}%</b></li>
            ))}
          </ul>
        </div>
        {secondary.length > 0 && (
          <div className="team-slices-side" aria-label="Другие срезы · лидеры">
            {secondary.map(({ dim, seg }) => (
              <div key={dim} className="team-slices-side-row">
                <span className="team-slices-side-dim">{dim}</span>
                <span className="team-slices-side-lab" title={seg.label}>{seg.label}</span>
                <b className="t-num team-slices-side-pct">{Math.round((seg && seg.countShare || 0) * 100)}%</b>
              </div>
            ))}
          </div>
        )}
      </div>);
  }

  function TeamBreakdownDonut({ title, sub, segs }) {
    const slices = segs.filter((s) => s.count > 0).map((s) => ({ label: s.label, value: s.count, color: s.color }));
    return (
      <Card variant="glass" padding="lg">
        <CardHead title={title} sub={sub} />
        <Donut slices={slices} size={140} stroke={22} centerTop={segs[0] ? Math.round(segs[0].countShare * 100) + '%' : '—'} centerBottom={segs[0] ? segs[0].label : ''} />
        <div className="kart-donut-keys" style={{ marginTop: 12 }}>
          {segs.slice(0, 4).map((s, i) => (
            <div key={i} className="kart-mini-row-meta" style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
              <span>{s.label}</span>
              <span className="t-num">{Math.round(s.profitShare * 100)}% прибыль · {s.avgMargin != null ? s.avgMargin + '%' : '—'}</span>
            </div>
          ))}
        </div>
      </Card>);
  }

  /* ---- метрика-плитка для карточки команды ---- */
  function TM({ label, value, tone }) {
    return (
      <div className="tm-cell">
        <div className="tm-v" style={tone ? { color: tone } : null}>{value}</div>
        <div className="tm-l">{label}</div>
      </div>);
  }

  function TeamAnalytics() {
    const O2 = O();
    const teams = O2.TEAMS;
    const K = O2.KARTOTEKA;
    const totalHours = teams.reduce((s, t) => s + t.hours, 0);
    const avgChecklist = Math.round(teams.reduce((s, t) => s + t.checklistPct, 0) / teams.length);
    const avgAccuracy = Math.round(teams.reduce((s, t) => s + t.estimateAccuracy, 0) / teams.length);
    const byType = tAggregate(K, [...new Set(K.map((r) => r.type))].map((t) => ({ label: t, match: (r) => r.type === t })));
    const byArea = tAggregate(K, O2.AREA_SEGMENTS.map((s) => ({ label: s.label, match: (r) => s.test(r.area) })));
    const byHousing = tAggregate(K, [...new Set(K.map((r) => r.housing))].map((h) => ({ label: h, match: (r) => r.housing === h })));
    const ratingC = (n) => <span style={{ display: 'inline-flex', alignItems: 'center', gap: 3 }}><Ic n="star" s={12} c="var(--chart-5)" /><span className="t-num" style={{ fontWeight: 700 }}>{n}</span></span>;
    const [modal, setModal] = React.useState(null);
    const riskyTeams = [...teams].sort((a, b) => (b.delays.count - a.delays.count) || (b.load - a.load));

    const loadSlices = [
      { label: O2.LOAD.low.l, value: O2.TEAM_SUMMARY.load.low, color: O2.LOAD.low.c },
      { label: O2.LOAD.mid.l, value: O2.TEAM_SUMMARY.load.mid, color: O2.LOAD.mid.c },
      { label: O2.LOAD.high.l, value: O2.TEAM_SUMMARY.load.high, color: O2.LOAD.high.c },
      { label: O2.LOAD.off.l, value: O2.TEAM_SUMMARY.load.off, color: O2.LOAD.off.c },
    ];

    return (
      <div className="ov ov-zone">
        <KpiRow items={[
          { label: 'Совокупная загрузка', value: O2.TEAM_LOAD_TOTAL, unit: '%', hint: 'по всем бригадам', icon: 'gauge', bg: 'var(--cat-plumb-bg)', fg: 'var(--cat-plumb-fg)' },
          { label: 'Отработано часов', value: totalHours, unit: 'ч', hint: 'по табелю за период', icon: 'clock', bg: 'var(--cat-elec-bg)', fg: 'var(--cat-elec-fg)' },
          { label: 'Чек-листы выполнены', value: avgChecklist, unit: '%', hint: 'в среднем', icon: 'list-checks', bg: 'var(--success-soft)', fg: 'var(--success-strong)' },
          { label: 'Точность смет', value: avgAccuracy, unit: '%', hint: 'факт vs смета', icon: 'target', bg: 'var(--cat-tile-bg)', fg: 'var(--cat-tile-fg)' },
        ]} />
        <div className="ov-wgt-grid" style={{ gridColumn: '1 / -1' }}>
          <OpsWgt title="Загрузка бригад" expand={() => setModal('teams')} chartViz defaultViz="donut">
            <TeamLoadChart slices={loadSlices} center={O2.TEAM_LOAD_TOTAL + '%'} />
          </OpsWgt>
          <OpsWgt title="Бригады под контролем" badge={teams.length} expand={() => setModal('teams')} className="ov-wgt-wide">
            <div className="ov-wgt-list">
              {riskyTeams.slice(0, 3).map((t) => (
                <div key={t.id} className="ov-wgt-row">
                  <div className="ov-wgt-row-main">
                    <div className="ov-wgt-row-t">Бригада {t.foreman.split(' ')[0]} · {t.specialty}</div>
                    <div className="ov-wgt-row-s">{t.projects} проектов · {t.hours} ч · чек-листы {t.checklistPct}%</div>
                    <div className="ov-wgt-row-bar"><Bar pct={t.load} color={t.load > 85 ? 'var(--destructive)' : t.load > 70 ? 'var(--warning)' : 'var(--success)'} height={5} /></div>
                  </div>
                  <div className="ov-wgt-row-r">
                    <Badge tone={t.delays.count > 0 ? 'warning' : 'success'} dot>{t.delays.count > 0 ? `${t.delays.count} задерж.` : 'ok'}</Badge>
                  </div>
                </div>
              ))}
            </div>
          </OpsWgt>
          <OpsWgt title="Финансовый сигнал" expand={() => setModal('teams')}>
            <div className="ov-wgt-list">
              {riskyTeams.slice(0, 3).map((t) => (
                <div key={t.id} className="ov-wgt-row">
                  <div className="ov-wgt-row-main">
                    <div className="ov-wgt-row-t">Бригада {t.foreman.split(' ')[0]}</div>
                    <div className="ov-wgt-row-s">остаток {fmtCompact(t.finance.remaining)} ₽</div>
                  </div>
                  <div className="ov-wgt-row-r t-num" style={{ color: t.finance.overrun > 0 ? 'var(--destructive)' : 'var(--success-strong)', fontWeight: 800 }}>
                    {t.finance.overrun > 0 ? '+' : ''}{t.finance.overrun}%
                  </div>
                </div>
              ))}
            </div>
          </OpsWgt>
          <OpsWgt title="Срезы по проектам" expand={() => setModal('slices')}>
            <TeamSlicesCompact byType={byType} byArea={byArea} byHousing={byHousing} />
          </OpsWgt>
        </div>
        {modal === 'teams' && (
          <OpsModal title="Команда · полный обзор" subtitle="Бригады, загрузка, качество и бюджет" onClose={() => setModal(null)}>
            <div className="team-cards">
              {teams.map((t) => (
                <Card key={t.id} variant="glass" padding="lg">
                  <div className="tc-head">
                    <span className="row-ava" style={{ background: t.avaC, width: 40, height: 40, fontSize: 13 }}>{t.ava}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div className="t-h3" style={{ fontSize: 16 }}>Бригада {t.foreman.split(' ')[0]}</div>
                      <div style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>Прораб {t.foreman} · {t.specialty}</div>
                    </div>
                    <div className="tc-crew">{t.crew.map((c, i) => <span key={i} className="mini-ava" style={{ background: c.color, width: 26, height: 26, fontSize: 9.5, marginLeft: i ? -8 : 0, border: '2px solid var(--card)' }}>{c.initials}</span>)}</div>
                  </div>
                  <div className="tc-metrics">
                    <TM label="Проектов" value={t.projects} />
                    <TM label="Новых" value={t.projectsNew} tone="var(--info)" />
                    <TM label="Завершено" value={t.projectsDone} tone="var(--success-strong)" />
                    <TM label="Загрузка" value={t.load + '%'} tone={t.load > 85 ? 'var(--destructive)' : t.load > 70 ? 'var(--warning-strong)' : 'var(--success-strong)'} />
                    <TM label="Часы" value={t.hours} />
                    <TM label="Чек-листы" value={t.checklistPct + '%'} />
                    <TM label="Контент" value={t.contentPct + '%'} />
                    <TM label="Точн. смет" value={t.estimateAccuracy + '%'} tone={t.estimateAccuracy >= 95 ? 'var(--success-strong)' : 'var(--foreground)'} />
                  </div>
                  <div className="tc-load"><span className="ov-foot-l" style={{ marginBottom: 6 }}>Уровень загрузки</span><Bar pct={t.load} color={t.load > 85 ? 'var(--destructive)' : t.load > 70 ? 'var(--warning)' : 'var(--success)'} height={7} /></div>
                  <div className="tc-fin">
                    <div><div className="ov-foot-l">План затрат</div><div className="t-num tc-fin-v">{fmtCompact(t.finance.plan)} ₽</div></div>
                    <div><div className="ov-foot-l">Перерасход</div><div className="t-num tc-fin-v" style={{ color: t.finance.overrun > 0 ? 'var(--destructive)' : 'var(--success-strong)' }}>{t.finance.overrun > 0 ? '+' : ''}{t.finance.overrun}%</div></div>
                    <div><div className="ov-foot-l">Остаток бюджета</div><div className="t-num tc-fin-v">{fmtCompact(t.finance.remaining)} ₽</div></div>
                  </div>
                  <div className="tc-foot">
                    <span className="tc-chip"><span className="ov-foot-l" style={{ marginBottom: 0 }}>Клиенты</span>{ratingC(t.ratingClient)}</span>
                    <span className="tc-chip"><span className="ov-foot-l" style={{ marginBottom: 0 }}>Сотрудники</span>{ratingC(t.ratingStaff)}</span>
                    <span className={'tc-chip' + (t.delays.count > 0 ? ' warn' : ' ok')}>
                      <Ic n={t.delays.count > 0 ? 'clock-alert' : 'check-circle-2'} s={13} sw={2.2} />
                      {t.delays.count > 0 ? `${t.delays.count} задержка · ср. ${t.delays.avgDays} дн` : 'Сдачи без задержек'}
                    </span>
                  </div>
                </Card>
              ))}
            </div>
          </OpsModal>
        )}
        {modal === 'slices' && (
          <OpsModal title="Срезы по проектам команд" subtitle="Тип ремонта, площадь и жильё" onClose={() => setModal(null)}>
            <div className="dl-grid">
              <TeamBreakdownDonut title="По типу ремонта" sub="Доля в потоке и вклад в прибыль" segs={byType} />
              <TeamBreakdownDonut title="По площади" sub="Сегменты площадей" segs={byArea} />
              <TeamBreakdownDonut title="По типу жилья" sub="Доля потока и маржа" segs={byHousing} />
            </div>
          </OpsModal>
        )}
      </div>);
  }

  function TeamPlanning() {
    const O2 = O();
    const PT = O2.PLAN_TYPES;
    return (
      <div className="ov ov-zone">
        <Card variant="glass" padding="lg" style={{ gridColumn: '1 / -1', marginBottom: 18, overflow: 'hidden' }}>
          <CardHead title="Планирование занятости · неделя" sub="Рабочий график, отпуска, собеседования, выезды на объекты и замеры" />
          <div className="ov-inset">
          <div className="plan-legend">
            {Object.entries(PT).map(([k, v]) => <span key={k} className="plan-leg-item"><span className="plan-leg-dot" style={{ background: v.c }} />{v.l}</span>)}
          </div>
          <div className="tbl-scroll">
            <div className="plan-grid">
              <div className="plan-corner">Сотрудник</div>
              {O2.PLAN_DAYS.map((d, i) => <div key={i} className="plan-day-h">{d}</div>)}
              {O2.PLANNING.map((row, ri) =>
                <React.Fragment key={ri}>
                  <div className="plan-person"><span className="mini-ava" style={{ background: row.avaC, width: 26, height: 26, fontSize: 9.5 }}>{row.ava}</span><div style={{ minWidth: 0 }}><div className="plan-person-n">{row.name}</div><div className="plan-person-r">{row.role}</div></div></div>
                  {row.week.map((t, ci) => { const v = PT[t]; return (
                    <div key={ci} className="plan-cell" style={{ background: v.bg, color: v.c }} title={v.l}>
                      <Ic n={v.ic} s={13} sw={2} />
                    </div>); })}
                </React.Fragment>
              )}
            </div>
          </div>
          </div>
        </Card>

        <Card variant="glass" padding="lg" style={{ gridColumn: '1 / -1' }}>
          <CardHead title="Выезды на замеры" sub="Назначенные и неназначенные выезды на объекты" />
          <div className="ov-inset">
          <div className="mv-grid">
            {O2.MEASURE_VISITS.map((m, i) => { const s = O2.MEASURE_STATUS[m.status]; return (
              <div key={i} className={'mv-card' + (m.status === 'unassigned' ? ' alert' : '')}>
                <div className="mv-when"><Ic n="calendar-clock" s={13} c="var(--text-tertiary)" /><span className="mv-date">{m.date}</span><span className="mv-time t-num">{m.time}</span></div>
                <div className="mv-client">{m.client}</div>
                <div className="mv-addr"><Ic n="map-pin" s={12} c="var(--text-tertiary)" />{m.address}</div>
                <div className="mv-foot">
                  <span className="mv-asg"><span className="mini-ava" style={{ background: m.avaC, width: 20, height: 20, fontSize: 8.5 }}>{m.ava}</span><span style={{ color: m.assignee === 'не назначен' ? 'var(--destructive)' : 'var(--text-secondary)', fontWeight: m.assignee === 'не назначен' ? 600 : 500 }}>{m.assignee}</span></span>
                  <Badge bg={s.bg} color={s.fg}>{s.l}</Badge>
                </div>
              </div>); })}
          </div>
          </div>
        </Card>
      </div>);
  }

  function TeamTimesheets() {
    return (
      <div className="ov ov-zone">
        <KpiRow items={[
          { label: 'Часов за период', value: 310, delta: 9, deltaTone: 'up', hint: 'по всем бригадам', icon: 'clock', bg: 'var(--cat-plumb-bg)', fg: 'var(--cat-plumb-fg)' },
          { label: 'Корректировок', value: 6, hint: 'прорабом', icon: 'pencil', bg: 'var(--cat-elec-bg)', fg: 'var(--cat-elec-fg)' },
          { label: 'Утверждено табелей', value: 94, unit: '%', hint: 'остальное на проверке', icon: 'check', bg: 'var(--success-soft)', fg: 'var(--success-strong)' },
        ]} />
        <TableCard title="Табель учёта рабочего времени" sub="По людям и проектам за период">
          <table className="cl-tbl"><thead><tr><th>Человек</th><th>Проект</th><th>План</th><th>Факт</th><th>Статус</th></tr></thead><tbody>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">40 ч</td><td className="t-num">38.5 ч</td><td><Badge tone="success" dot>Утверждён</Badge></td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">40 ч</td><td className="t-num">46 ч</td><td><Badge tone="warning" dot>+6 ч овертайм</Badge></td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">40 ч</td><td className="t-num">32 ч</td><td><Badge tone="info" dot>На проверке</Badge></td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">30 ч</td><td className="t-num">30 ч</td><td><Badge tone="success" dot>Утверждён</Badge></td></tr>
          </tbody></table>
        </TableCard>
      </div>);
  }

  function TeamMeetings() {
    const O2 = O();
    const planned = O2.MEETINGS.filter((m) => m.status === 'planned');
    const held = O2.MEETINGS.filter((m) => m.status === 'held');
    const MeetRow = (m, i) => { const k = O2.MEETING_KIND[m.kind]; const s = O2.MEETING_STATUS[m.status]; return (
      <div key={i} className="meet-row">
        <span className="meet-ic" style={{ background: `color-mix(in srgb, ${k.c} 14%, var(--card))`, color: k.c }}><Ic n={k.ic} s={16} sw={2} /></span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="meet-title">{m.title}</div>
          <div className="meet-meta"><span className="t-num">{m.date}</span><span>·</span><span>{m.client !== '—' ? m.client : k.l}</span></div>
        </div>
        <span className="meet-who"><span className="mini-ava" style={{ background: m.avaC, width: 22, height: 22, fontSize: 8.5 }}>{m.who.split(' ').map((w) => w[0]).slice(0, 2).join('')}</span>{m.who}</span>
        <Badge bg={s.bg} color={s.fg} dot>{s.l}</Badge>
      </div>); };
    return (
      <div className="ov ov-zone cc-grid">
        <Card variant="glass" padding="lg">
          <CardHead title="Запланированные" sub="Встречи и созвоны в календаре" action={<Badge tone="neutral" dot>{planned.length}</Badge>} />
          <div className="ov-inset"><div className="meet-list">{planned.map(MeetRow)}</div></div>
        </Card>
        <Card variant="glass" padding="lg">
          <CardHead title="Проведённые" sub="Завершённые встречи за период" action={<Badge tone="success" dot>{held.length}</Badge>} />
          <div className="ov-inset"><div className="meet-list">{held.map(MeetRow)}</div></div>
        </Card>
      </div>);
  }

  function TeamRoster() {
    const [q, setQ] = React.useState('');
    const lkHref = (p) => p.lk ? `lk/${p.lk}.html?superView=${p.id}&name=${encodeURIComponent(p.name)}` : null;
    function effColor(eff) {return eff >= 95 ? 'var(--success-strong)' : eff >= 88 ? 'var(--info)' : 'var(--warning-strong)';}
    function rosterCountLabel(n) {
      const mod10 = n % 10;
      const mod100 = n % 100;
      if (mod100 >= 11 && mod100 <= 14) return `${n} человек`;
      if (mod10 === 1) return `${n} человек`;
      if (mod10 >= 2 && mod10 <= 4) return `${n} человека`;
      return `${n} человек`;
    }

    function RowActions({ p }) {
      const [open, setOpen] = React.useState(false);
      const ref = React.useRef();
      React.useEffect(() => {
        if (!open) return;
        const h = (e) => {if (ref.current && !ref.current.contains(e.target)) setOpen(false);};
        const k = (e) => {if (e.key === 'Escape') setOpen(false);};
        document.addEventListener('mousedown', h);document.addEventListener('keydown', k);
        return () => {document.removeEventListener('mousedown', h);document.removeEventListener('keydown', k);};
      }, [open]);
      const items = [
      { ic: 'key-round', l: 'Доступы и роли' },
      { ic: 'replace', l: 'Поменять доступ' },
      { ic: 'bell-ring', l: 'Уведомление в ЛК', act: () => window.opsNotifyLk && window.opsNotifyLk({ name: p.name, ava: p.ava, avaC: p.avaC, context: 'Просьба обратить внимание на профиль и задачи', object: p.role }) },
      { sep: true },
      { ic: 'user-minus', l: 'Отметить «увольняется»', tone: 'warn' },
      { ic: 'ban', l: 'Заблокировать', tone: 'warn' },
      { ic: 'trash-2', l: 'Удалить', tone: 'danger' }];
      return (
        <span ref={ref} style={{ position: 'relative', display: 'inline-flex' }}>
          <button className="row-kebab" onClick={() => setOpen((o) => !o)} title="Действия"><Ic n="more-horizontal" s={16} /></button>
          {open &&
          <div className="row-menu">
              {items.map((it, i) => it.sep ?
            <div key={i} className="row-menu-sep" /> :
            <button key={i} className={'row-menu-item' + (it.tone ? ' ' + it.tone : '')} onClick={() => {setOpen(false);it.act && it.act();}}>
                    <Ic n={it.ic} s={15} sw={2} />{it.l}
                  </button>)}
            </div>}
        </span>);
    }
    function Row({ p }) {
      const href = lkHref(p);
      return (
        <tr onClick={() => href && (location.href = href)} style={{ cursor: href ? 'pointer' : 'default' }}>
          <td><div className="cell-person"><span className="row-ava" style={{ background: p.avaC }}>{p.ava}</span><div><div className="cell-name">{p.name}</div><div className="cell-sub">{p.id}</div></div></div></td>
          <td>{p.trade !== '—' ? <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ fontWeight: 600, fontSize: 13 }}>{p.trade}</span><span className="cell-sub" style={{ display: 'inline' }}>{p.tradeAbbr}</span><Stars n={p.stars} /></span> : <span style={{ color: 'var(--text-tertiary)' }}>—</span>}</td>
          <td>{p.foreman !== '—' ? <span style={{ fontSize: 13 }}>{p.foreman}</span> : <span style={{ color: 'var(--text-tertiary)' }}>—</span>}</td>
          <td><LoadDot load={p.load} /></td>
          <td className="t-num">{p.hours > 0 ? p.hours.toFixed(1) + ' ч' : '—'}</td>
          <td>{p.payable > 0 ? <span className="t-num" style={{ fontWeight: 600 }}>{fmtCompact(p.payable)} ₽</span> : <span style={{ color: 'var(--text-tertiary)' }}>—</span>}</td>
          <td>{p.eff != null ? <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}><span style={{ width: 54, height: 6, borderRadius: 999, background: 'var(--muted)', overflow: 'hidden' }}><span style={{ display: 'block', height: '100%', width: p.eff + '%', background: effColor(p.eff), borderRadius: 999 }} /></span><span className="t-num" style={{ fontWeight: 600, fontSize: 12.5 }}>{p.eff}%</span></span> : <span style={{ color: 'var(--text-tertiary)' }}>—</span>}</td>
          <td style={{ textAlign: 'right' }} onClick={(ev) => ev.stopPropagation()}>
            <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              {href ? <a className="cta-lk" href={href}><Ic n="external-link" s={13} sw={2.2} />Открыть ЛК</a> : <span className="cta-lk muted">ЛК скоро</span>}
              <RowActions p={p} />
            </div>
          </td>
        </tr>);
    }
    return (
      <div className="ov ov-zone">
        <div className="team-roster-bar">
          <div className="team-roster-search">
            <Input placeholder="Поиск по имени, специальности" leading={<Ic n="search" s={16} />} value={q} onChange={(e) => setQ(e.target.value)} />
          </div>
          <p className="team-roster-note">Строка → нативный ЛК · баннер «Просмотр от имени Super»</p>
        </div>
        {O().ROLE_GROUPS.map((g) => {
          const people = O().TEAM.filter((p) => p.role === g.role && (!q || p.name.toLowerCase().includes(q.toLowerCase()) || p.trade.toLowerCase().includes(q.toLowerCase())));
          if (!people.length) return null;
          return (
            <div key={g.role} className="team-roster-group">
              <div className="team-group-head">
                <IconTile size="sm" bg="#70a2a9" color="#545454"><Ic n={g.icon} s={17} /></IconTile>
                <span className="team-group-title">{g.plural}</span>
                <span className="team-count">{rosterCountLabel(people.length)}</span>
              </div>
              <Card variant="glass" padding="lg" style={{ overflow: 'hidden', gridColumn: '1 / -1' }}>
                <div className="ov-inset">
                <div className="tbl-scroll">
                  <table className="cl-tbl">
                    <thead><tr><th>Человек</th><th>Специальность</th><th>Прораб</th><th>Загрузка</th><th>Часы/нед</th><th>ЗП к выплате</th><th>Эффект.</th><th></th></tr></thead>
                    <tbody>{people.map((p) => <Row key={p.id} p={p} />)}</tbody>
                  </table>
                </div>
                </div>
              </Card>
            </div>);
        })}
      </div>);
  }

  function TeamZone() {
    const [tab, setTab] = React.useState('analytics');
    const tabs = [['analytics', 'Аналитика', 'bar-chart-3'], ['roster', 'Реестр', 'table-2'], ['planning', 'Планирование', 'calendar-days'], ['timesheets', 'Табели', 'clock'], ['meetings', 'Встречи', 'calendar-check']];
    return (
      <div>
        <ZoneSeg tabs={tabs} active={tab} onChange={setTab} ariaLabel="Раздел команды" />
        {tab === 'analytics' && <TeamAnalytics />}
        {tab === 'roster' && <TeamRoster />}
        {tab === 'planning' && <TeamPlanning />}
        {tab === 'timesheets' && <TeamTimesheets />}
        {tab === 'meetings' && <TeamMeetings />}
      </div>);
  }

  /* ============================================================
     DRAWER ПРОЕКТА
     ============================================================ */
  function ProjectDrawer({ id, onClose }) {
    const p = O().PROJECTS.find((x) => x.id === id);
    const [tab, setTab] = React.useState('summary');
    React.useEffect(() => {setTab('summary');}, [id]);
    if (!p) return null;
    const h = O().HEALTH[p.health];

    return (
      <React.Fragment>
        <div className="drawer-ov open" onClick={onClose} />
        <aside className="proj-drawer open">
          <div className="pd-head">
            <button className="pd-close" onClick={onClose}><Ic n="x" s={16} /></button>
            <div className="pd-code">{p.code} · {p.area}</div>
            <div className="pd-title">{p.client} · {p.address}</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
              <Badge bg={`var(--cat-${p.cat}-bg)`} color={`var(--cat-${p.cat}-fg)`} dot>{p.phase}</Badge>
              <span style={{ fontSize: 12.5, color: 'var(--text-tertiary)' }}>Прораб {p.foreman} · {p.deadline}</span>
            </div>
          </div>
          <div className="pd-tabs">
            {[['summary', 'Сводка'], ['tasks', 'Задачи'], ['notes', 'Заметки'], ['checklists', 'Чек-листы'], ['feed', 'Лента']].map(([k, l]) =>
            <button key={k} className={'pd-tab' + (tab === k ? ' on' : '')} onClick={() => setTab(k)}>{l}</button>
            )}
          </div>
          <div className="pd-body">{renderTab(p, tab)}</div>
        </aside>
      </React.Fragment>);


    function renderTab(p, tab) {
      if (tab === 'summary') return (
        <div>
          <div className="pd-sec">
            <div className="pd-sec-t">Прогресс</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}><div style={{ flex: 1 }}><Bar pct={p.pct} color={`var(--cat-${p.cat}-fg)`} height={8} /></div><span className="t-num" style={{ fontWeight: 800, fontSize: 17 }}>{p.pct}%</span></div>
          </div>
          <div className="pd-sec">
            <div className="pd-sec-t">Параметры <span className="super-edit"><Ic n="pencil" s={11} />Super edit</span></div>
            <div className="pd-grid2">
              <div className="pd-field"><div className="pd-field-l">Площадь</div><div className="pd-field-v t-num">{p.area}</div></div>
              <div className="pd-field"><div className="pd-field-l">Этап</div><div className="pd-field-v">{p.stage}</div></div>
              <div className="pd-field"><div className="pd-field-l">Дедлайн</div><div className="pd-field-v">{p.deadline}</div></div>
              <div className="pd-field"><div className="pd-field-l">Заметки ack</div><div className="pd-field-v">{p.notesAck}</div></div>
              <div className="pd-field"><div className="pd-field-l">Затраты</div><div className="pd-field-v t-num">{fmtCompact(p.spent)} ₽</div></div>
              <div className="pd-field"><div className="pd-field-l">Смета</div><div className="pd-field-v t-num">{fmtCompact(p.estimate)} ₽</div></div>
            </div>
          </div>
          <div className="pd-sec">
            <div className="pd-sec-t">Алерты</div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              {p.fails > 0 && <Badge tone="danger" icon={<Ic n="x-circle" s={12} />}>{p.fails} чек-листа провалено</Badge>}
              {p.pending > 0 && <Badge tone="warning" icon={<Ic n="clock" s={12} />}>{p.pending} заметка без ack</Badge>}
              {!p.fails && !p.pending && <span style={{ color: 'var(--success-strong)', fontSize: 13, fontWeight: 600 }}>Без замечаний</span>}
            </div>
          </div>
        </div>);

      if (tab === 'notes') return (
        <div>
          <div className="pd-sec-t">Заметки проекта · <span style={{ color: 'var(--primary)' }}>Изменить как Super</span></div>
          {[['МД', '#e8793a', '—', '13 июн', 'Стяжка полусухая М150, толщина 50 мм. Демпферная лента по периметру обязательна.'],
          ['СМ', '#4e7fca', '—', '14 июн', 'Маяки снять после схватывания, выбоины зашпаклевать ремсоставом.']].map((n, i) =>
          <div key={i} className="note-item"><span className="row-ava" style={{ background: n[1], width: 32, height: 32, fontSize: 11 }}>{n[0]}</span><div style={{ flex: 1 }}><div style={{ fontSize: 13, fontWeight: 600 }}>{n[2]} <span style={{ fontSize: 11.5, color: 'var(--text-tertiary)' }}>· {n[3]}</span></div><div style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.5, marginTop: 4 }}>{n[4]}</div></div></div>
          )}
        </div>);

      if (tab === 'checklists') return (
        <div>
          <div className="pd-sec-t">Чек-листы выполнения · <span style={{ color: 'var(--primary)' }}>Force complete (audit)</span></div>
          {[['ok', 'Демпферная лента по периметру'], ['ok', 'Маяки выставлены по уровню'], ['fail', 'Пресс-тест труб — не пройден'], ['pend', 'Армирующая сетка уложена']].map((ck, i) =>
          <div key={i} className="ck-item"><span className={'ck-box ' + ck[0]}>{ck[0] === 'ok' ? <Ic n="check" s={12} sw={3} /> : ck[0] === 'fail' ? <Ic n="x" s={12} sw={3} /> : null}</span><span className="ck-lbl" style={ck[0] === 'fail' ? { color: 'var(--destructive)' } : {}}>{ck[1]}</span></div>
          )}
        </div>);

      if (tab === 'tasks') return (
        <div>
          <div className="pd-sec-t">Задачи проекта · Super может override статус</div>
          {[['ok', 'Выравнивание потолков — гостиная', 'сдано'], ['pend', 'Заливка стяжки', '—'], ['pend', 'Покраска стен — спальня 1', '—']].map((t, i) =>
          <div key={i} className="ck-item"><span className={'ck-box ' + t[0]}>{t[0] === 'ok' ? <Ic n="check" s={12} sw={3} /> : null}</span><span className="ck-lbl">{t[1]} <span className="cell-sub" style={{ display: 'inline' }}>· {t[2]}</span></span></div>
          )}
        </div>);

      // feed — события из общей ленты, скоупленные на этот проект
      const evs = O().ACTIVITY.filter((e) => e.projId === p.id);
      return (
        <div>
          <div className="pd-sec-t">Лента проекта · <span style={{ color: 'var(--text-secondary)' }}>{evs.length} событий</span></div>
          {evs.map((e) => {
            return (
              <div key={e.id} className="note-item">
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div className="ov-exc-title">{e.title}</div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', fontSize: 11.5, color: 'var(--text-tertiary)', marginTop: 4 }}>
                    <span>{e.actor.name}</span><span>·</span><span>{e.day}, {e.time}</span>
                    {(e.chips || []).slice(0, 1).map((ch, j) => <Badge key={j} tone={ch.tone} dot>{ch.label}</Badge>)}
                  </div>
                </div>
              </div>);
          })}
          {evs.length === 0 && <div style={{ padding: '24px 0', textAlign: 'center', color: 'var(--text-tertiary)', fontSize: 13 }}>По проекту пока нет событий в ленте</div>}
        </div>);

    }
  }

  /* ============================================================
     АНАЛИТИКА
     ============================================================ */
  function AnalyticsZone({ period, prevLabel, go }) {
    const [tab, setTab] = React.useState('funnel');
    const tabs = [['funnel', 'Воронка', 'filter'], ['economics', 'Экономика', 'wallet'], ['notes', 'Заметки', 'message-square'], ['quality', 'Качество', 'list-checks'], ['people', 'Люди', 'users-round'], ['hours', 'Часы', 'clock']];

    return (
      <div>
        <ZoneSeg tabs={tabs} active={tab} onChange={setTab} ariaLabel="Раздел аналитики" />
        {tab === 'funnel' && <AnaFunnel period={period} prevLabel={prevLabel} />}
        {tab === 'economics' && <AnaEconomics period={period} prevLabel={prevLabel} />}
        {tab === 'notes' && <AnaNotes />}
        {tab === 'quality' && <AnaQuality />}
        {tab === 'people' && <AnaPeople />}
        {tab === 'hours' && <AnaHours />}
      </div>);

  }

  function KpiRow({ items }) {
    const { StatWidget } = window.DesignSystem_9e0a09;
    return (
      <div className="ana-kpi" style={{ gridColumn: '1 / -1' }}>
        {items.map((it, i) =>
        <Card key={i} variant="glass" padding="md">
            <StatWidget label={it.label} value={it.value} unit={it.unit} delta={it.delta} deltaTone={it.deltaTone} hint={it.hint} />
          </Card>
        )}
      </div>);

  }

  function AnaFunnel({ period, prevLabel }) {
    const f = O().FUNNEL[period];
    const [modal, setModal] = React.useState(null);
    return (
      <div className="ov ov-zone">
        <KpiRow items={[
        { label: 'Конверсия лид→сделка', value: Math.round(f.contracts / f.leads * 100), unit: '%', delta: f.winrateDelta, deltaTone: f.winrateDelta >= 0 ? 'up' : 'down', hint: `к ${prevLabel}`, icon: 'target', bg: 'var(--cat-demo-bg)', fg: 'var(--cat-demo-fg)' },
        { label: 'Средний чек', value: fmtCompact(f.avgCheck), unit: '₽', hint: 'по договорам', icon: 'banknote', bg: 'var(--cat-paint-bg)', fg: 'var(--cat-paint-fg)' },
        { label: 'Срок лид→договор', value: f.leadDays, unit: 'дн', hint: 'в среднем', icon: 'timer', bg: 'var(--cat-plumb-bg)', fg: 'var(--cat-plumb-fg)' },
        { label: 'Потеряно в пуле', value: f.lostPool, hint: 'не дошли до встречи', icon: 'user-x', bg: '#fdecec', fg: 'var(--destructive)' }]
        } />
        <div className="ov-wgt-grid" style={{ gridColumn: '1 / -1' }}>
          <OpsWgt title="Воронка продаж" badge={`к ${prevLabel}`} expand={() => setModal('funnel')} className="ov-wgt-wide ov-wgt-funnel" chartViz defaultViz="hbar">
            <div className="ov-wgt-kpis ov-wgt-kpis--tight">
              <div className="ov-wgt-kpi"><div className="ov-wgt-kpi-v t-num">{f.leads}</div><div className="ov-wgt-kpi-l">Лиды</div></div>
              <div className="ov-wgt-kpi"><div className="ov-wgt-kpi-v t-num">{f.meetings}</div><div className="ov-wgt-kpi-l">Встречи</div></div>
              <div className="ov-wgt-kpi"><div className="ov-wgt-kpi-v t-num">{f.estimates}</div><div className="ov-wgt-kpi-l">Сметы</div></div>
              <div className="ov-wgt-kpi"><div className="ov-wgt-kpi-v t-num">{f.contracts}</div><div className="ov-wgt-kpi-l">Договоры</div></div>
            </div>
            <AnaFunnelSeries f={f} onOpen={() => setModal('funnel')} />
          </OpsWgt>
          <OpsWgt title="Источники лидов" expand={() => setModal('sources')} chartViz defaultViz="hbar">
            <LeadSourcesChart sources={O().LEAD_SOURCES} />
          </OpsWgt>
        </div>
        {modal === 'funnel' && (
          <OpsModal title="Воронка продаж" subtitle={`Лиды → встречи → сметы → договоры · сравнение с ${prevLabel}`} onClose={() => setModal(null)}>
            <div className="ov-inset">
              <SalesFunnel data={f} />
            </div>
            <div className="ov-inset ov-funnel-foot">
              <div><div className="ov-foot-l">Средний чек</div><div className="t-num ov-foot-v">{fmtCompact(f.avgCheck)} ₽</div></div>
              <div><div className="ov-foot-l">Лид → договор</div><div className="t-num ov-foot-v">{f.leadDays} дн</div></div>
              <div><div className="ov-foot-l">Конверсия лид→сделка</div><div className="t-num ov-foot-v">{Math.round(f.contracts / f.leads * 100)}%</div></div>
              <div><div className="ov-foot-l">Winrate к {prevLabel}</div><div className="ov-foot-v"><Delta value={f.winrateDelta} /></div></div>
            </div>
          </OpsModal>
        )}
        {modal === 'sources' && (
          <OpsModal title="Лиды по источникам" subtitle="Доля входящих лидов по каналам привлечения" onClose={() => setModal(null)}>
            <div className="ov-inset">
              {O().LEAD_SOURCES.map((s, i) =>
              <div key={i} className="ov-cost-row">
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5 }}><span style={{ fontSize: 13, fontWeight: 600 }}>{s.label}</span><span className="t-num" style={{ fontSize: 13, fontWeight: 700 }}>{Math.round(s.share * 100)}%</span></div>
                <Bar pct={s.share * 100} color={s.color} />
              </div>)}
            </div>
          </OpsModal>
        )}
      </div>);

  }

  function AnaEconomics({ period, prevLabel }) {
    const O2 = O();
    const e = O2.ECONOMICS[period];
    const [costDim, setCostDim] = React.useState('total');
    const [calDay, setCalDay] = React.useState(null);
    const cost = O2.COSTS[costDim];
    const costSlices = cost.slices || null;
    return (
      <div className="ov ov-zone">
        <KpiRow items={[
        { label: 'Потрачено', value: fmtCompact(e.spent), unit: '₽', delta: e.dSpent, deltaTone: 'down', hint: `к ${prevLabel}`, icon: 'arrow-down-circle', bg: 'var(--cat-demo-bg)', fg: 'var(--cat-demo-fg)' },
        { label: 'Перечислено', value: fmtCompact(e.received), unit: '₽', delta: e.dReceived, deltaTone: 'up', hint: `к ${prevLabel}`, icon: 'arrow-up-circle', bg: 'var(--cat-paint-bg)', fg: 'var(--cat-paint-fg)' },
        { label: 'Прибыль', value: fmtCompact(e.profit), unit: '₽', delta: e.dProfit, deltaTone: 'up', hint: `маржа ${e.marginPct}%`, icon: 'trending-up', bg: 'var(--success-soft)', fg: 'var(--success-strong)' }]
        } />

        <Card variant="glass" padding="lg" style={{ gridColumn: '1 / -1', marginBottom: 18 }}>
          <CardHead
            title={`Календарь оплат и прибыли · ${O2.PAY_CALENDAR.month}`}
            sub="Приход, расход и кассовые разрывы по дням"
            action={
              <span style={{ display: 'flex', gap: 12, fontSize: 11, color: 'var(--text-tertiary)' }}>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}><span className="cal-key" style={{ background: 'var(--success)' }} />приход</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}><span className="cal-key" style={{ background: 'var(--warning)' }} />расход</span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 5 }}><span className="cal-key" style={{ background: 'var(--destructive)' }} />разрыв</span>
              </span>
            } />
          <div className="ov-inset">
            <PayCalendar data={O2.PAY_CALENDAR} onDay={(d, c) => setCalDay({ d, c })} />
          </div>
          {calDay &&
          <div className="ov-cal-pop">
              <Ic n="calendar" s={14} c="var(--primary)" />
              <span style={{ fontWeight: 700 }}>{calDay.d} {O2.PAY_CALENDAR.month.split(' ')[0].toLowerCase()}:</span>
              {calDay.c.in > 0 && <span style={{ color: 'var(--success-strong)' }}>приход {fmtCompact(calDay.c.in)} ₽</span>}
              {calDay.c.out > 0 && <span style={{ color: 'var(--destructive)' }}>расход {fmtCompact(calDay.c.out)} ₽</span>}
            </div>
          }
        </Card>

        <div className="cc-grid" style={{ gridColumn: '1 / -1', marginBottom: 18 }}>
          <Card variant="glass" padding="lg">
            <CardHead
              title="Дебиторка · AR aging"
              sub="Возраст задолженности и топ-должники"
              action={<div style={{ textAlign: 'right' }}><div className="t-num" style={{ fontSize: 20, fontWeight: 800 }}>{fmtCompact(O2.AR.total)} ₽</div><div style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>всего долга</div></div>} />
            <div className="ov-inset">
            <StackBar slices={O2.AR.buckets} />
            <div className="ov-debtors">
              <div className="ov-foot-l" style={{ marginBottom: 8 }}>Топ-должники</div>
              {O2.AR.debtors.map((d, i) =>
              <div key={i} className="ov-debtor-row">
                  <span className="mini-ava" style={{ background: d.avaC, width: 26, height: 26, fontSize: 10 }}>{d.ava}</span>
                  <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: 'var(--foreground)' }}>{d.name}</span>
                  <span className="t-num" style={{ fontSize: 13, fontWeight: 700 }}>{fmtCompact(d.amount)} ₽</span>
                  <span className="t-num" style={{ fontSize: 11.5, fontWeight: 700, color: d.overdue > 30 ? 'var(--destructive)' : 'var(--text-tertiary)', width: 64, textAlign: 'right' }}>{d.overdue > 0 ? `+${d.overdue} дн` : 'в срок'}</span>
                </div>
              )}
            </div>
            </div>
          </Card>

          <Card variant="glass" padding="lg">
            <CardHead title="Структура затрат" sub="Где «утекают» деньги — срез по ролям и проектам" />
            <div className="ov-cost-tabs">
              {[['total', 'Общая'], ['projects', 'Проекты'], ['executors', 'Исполнители'], ['foremen', 'Прорабы'], ['managers', 'Менеджеры'], ['designers', 'Дизайнеры']].map(([k, l]) =>
              <button key={k} className={'ov-cost-tab' + (costDim === k ? ' on' : '')} onClick={() => setCostDim(k)}>{l}</button>
              )}
            </div>
            <div className="ov-inset">
            {costSlices ?
            <Donut slices={costSlices} size={150} stroke={24} centerTop={`${fmtCompact(costSlices.reduce((s, x) => s + x.value, 0))} ₽`} centerBottom="общие затраты" /> :
            <div className="ov-cost-rows">
                {cost.rows.map((r, i) => {
                const maxV = Math.max(...cost.rows.map((x) => x.spent));
                return (
                  <div key={i} className="ov-cost-row">
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 5 }}>
                        <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--foreground)' }}>{r.name}</span>
                        <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                          <span className="t-num" style={{ fontSize: 13, fontWeight: 700 }}>{fmtCompact(r.spent)} ₽</span>
                          {r.over != null && r.over !== 0 && <span className="t-num" style={{ fontSize: 11.5, fontWeight: 700, color: r.over > 0 ? 'var(--destructive)' : 'var(--success-strong)' }}>{r.over > 0 ? '+' : ''}{r.over}%</span>}
                          {r.perHour && <span className="t-num" style={{ fontSize: 11.5, color: 'var(--text-tertiary)' }}>{r.perHour} ₽/ч</span>}
                          {r.cac && <span className="t-num" style={{ fontSize: 11.5, color: 'var(--text-tertiary)' }}>CAC {fmtCompact(r.cac)} ₽</span>}
                        </span>
                      </div>
                      <Bar pct={r.spent / maxV * 100} color={r.over > 0 ? 'var(--destructive)' : 'var(--chart-1)'} />
                    </div>);
              })}
              </div>
            }
            </div>
          </Card>
        </div>

        <Card variant="glass" padding="lg" style={{ gridColumn: '1 / -1' }}>
          <CardHead title="Маржа по проектам" sub="Перерасход vs смета по каждому объекту" />
          <div className="ov-inset">
          {O2.COSTS.projects.rows.map((r, i) =>
          <div key={i} className="ov-cost-row">
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5 }}>
                <span style={{ fontSize: 13, fontWeight: 600 }}>{r.name}</span>
                <span style={{ display: 'flex', gap: 10 }}><span className="t-num" style={{ fontSize: 12.5, color: 'var(--text-tertiary)' }}>смета {fmtCompact(r.estimate)} ₽</span><span className="t-num" style={{ fontSize: 13, fontWeight: 700, color: r.over > 0 ? 'var(--destructive)' : 'var(--success-strong)' }}>{r.over > 0 ? '+' : ''}{r.over}%</span></span>
              </div>
              <Bar pct={r.spent / r.estimate * 100} color={r.over > 0 ? 'var(--destructive)' : 'var(--success)'} />
            </div>
          )}
          </div>
        </Card>
      </div>);

  }

  function AnaNotes() {
    return (
      <div className="ov ov-zone">
        <KpiRow items={[
        { label: 'Всего тредов', value: 5, icon: 'message-square', bg: 'var(--cat-elec-bg)', fg: 'var(--cat-elec-fg)', hint: 'по организации' },
        { label: 'Подтверждено', value: 2, icon: 'check-circle', bg: 'var(--success-soft)', fg: 'var(--success-strong)' },
        { label: 'Просрочено ack', value: 1, icon: 'alert-triangle', bg: '#fdecec', fg: 'var(--destructive)' },
        { label: 'Ср. время до ack', value: '1.4', unit: 'дн', icon: 'timer', bg: 'var(--cat-plumb-bg)', fg: 'var(--cat-plumb-fg)' }]
        } />
        <TableCard title="Все треды организации" sub="Заметки по проектам и статус подтверждения">
          <table className="cl-tbl"><thead><tr><th>Заметка</th><th>Проект</th><th>Автор</th><th>Ack</th><th>Возраст</th></tr></thead><tbody>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>Стяжка М150, демпфер по периметру</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td style={{ fontSize: 13 }}>—</td><td><Badge tone="warning" dot>1 из 2</Badge></td><td className="t-num">2 дня</td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>Гидроизоляция в 2 слоя, заход 200 мм</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td style={{ fontSize: 13 }}>—</td><td><Badge tone="success" dot>принято</Badge></td><td className="t-num">5 ч</td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>Пресс-тест труб 6 атм, 30 мин</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td style={{ fontSize: 13 }}>—</td><td><Badge tone="danger" dot>0 из 2</Badge></td><td className="t-num" style={{ color: 'var(--destructive)', fontWeight: 600 }}>4 дня</td></tr>
          </tbody></table>
        </TableCard>
      </div>);

  }

  function AnaQuality() {
    const Q = O().ANA_QUALITY;
    return (
      <div className="ov ov-zone">
        <KpiRow items={[
        { label: 'Pass rate', value: Q.passRate, unit: '%', delta: Q.deltaPass, deltaTone: 'up', hint: 'за месяц', icon: 'check-circle', bg: 'var(--success-soft)', fg: 'var(--success-strong)' },
        { label: 'Провалов', value: Q.fails, hint: 'за неделю', icon: 'x-circle', bg: '#fdecec', fg: 'var(--destructive)' },
        { label: 'Прогонов', value: Q.runs, hint: 'всего', icon: 'list-checks', bg: 'var(--cat-plumb-bg)', fg: 'var(--cat-plumb-fg)' }]
        } />
        <TableCard title="Checklist runs" sub="Результаты чек-листов по этапам и проектам">
          <table className="cl-tbl"><thead><tr><th>Чек-лист</th><th>Проект</th><th>Исполнитель</th><th>Результат</th><th>Дата</th></tr></thead><tbody>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>Скрытые работы — сантехника</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td style={{ fontSize: 13 }}>—</td><td><Badge tone="danger" dot>Провал · пресс-тест</Badge></td><td className="t-num">12 июн</td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>Плитка — приёмка</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td style={{ fontSize: 13 }}>—</td><td><Badge tone="success" dot>Пройден</Badge></td><td className="t-num">14 июн</td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>Электрика — скрытая</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td style={{ fontSize: 13 }}>—</td><td><Badge tone="warning" dot>В процессе</Badge></td><td className="t-num">15 июн</td></tr>
          </tbody></table>
        </TableCard>
      </div>);

  }

  function AnaPeople() {
    const people = O().TEAM.filter((p) => p.eff != null);
    return (
      <div className="ov ov-zone">
      <TableCard title="Производительность исполнителей" sub="Загрузка, часы и эффективность по людям">
        <table className="cl-tbl"><thead><tr><th>Человек</th><th>Загрузка</th><th>Часы/нед</th><th>₽/час</th><th>Эффективность</th></tr></thead><tbody>
          {people.map((p) =>
              <tr key={p.id}><td><div className="cell-person"><span className="row-ava" style={{ background: p.avaC, width: 30, height: 30, fontSize: 11 }}>{p.ava}</span><div><div className="cell-name">{p.name}</div><div className="cell-sub">{p.trade !== '—' ? p.trade : p.role}</div></div></div></td>
            <td><LoadDot load={p.load} /></td>
            <td className="t-num">{p.hours.toFixed(1)} ч</td>
            <td className="t-num">{p.rate ? p.rate + ' ₽' : '—'}</td>
            <td><span style={{ display: 'flex', alignItems: 'center', gap: 8 }}><span style={{ width: 60, height: 6, borderRadius: 999, background: 'var(--muted)', overflow: 'hidden' }}><span style={{ display: 'block', height: '100%', width: p.eff + '%', background: p.eff >= 95 ? 'var(--success)' : p.eff >= 88 ? 'var(--info)' : 'var(--warning)', borderRadius: 999 }} /></span><span className="t-num" style={{ fontWeight: 600, fontSize: 12.5 }}>{p.eff}%</span></span></td></tr>
              )}
        </tbody></table>
      </TableCard>
      </div>);

  }

  function AnaHours() {
    return (
      <div className="ov ov-zone">
        <KpiRow items={[
        { label: 'Часов за период', value: 218, delta: 12, deltaTone: 'up', hint: 'к плану', icon: 'clock', bg: 'var(--cat-plumb-bg)', fg: 'var(--cat-plumb-fg)' },
        { label: 'Корректировок', value: 6, hint: 'прорабом', icon: 'pencil', bg: 'var(--cat-elec-bg)', fg: 'var(--cat-elec-fg)' },
        { label: 'Утверждено', value: 94, unit: '%', hint: 'табелей', icon: 'check', bg: 'var(--success-soft)', fg: 'var(--success-strong)' }]
        } />
        <TableCard title="Табель · по людям и проектам" sub="План vs факт и статус утверждения">
          <table className="cl-tbl"><thead><tr><th>Человек</th><th>Проект</th><th>План</th><th>Факт</th><th>Статус</th></tr></thead><tbody>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">40 ч</td><td className="t-num">38.5 ч</td><td><Badge tone="success" dot>Утверждён</Badge></td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">40 ч</td><td className="t-num">46 ч</td><td><Badge tone="warning" dot>+6 ч овертайм</Badge></td></tr>
            <tr><td className="cell-name" style={{ fontWeight: 500 }}>—</td><td style={{ fontSize: 12.5, color: 'var(--text-secondary)' }}>—</td><td className="t-num">40 ч</td><td className="t-num">32 ч</td><td><Badge tone="info" dot>На проверке</Badge></td></tr>
          </tbody></table>
        </TableCard>
      </div>);

  }

  Object.assign(window, { TeamZone, ProjectDrawer, AnalyticsZone });
})();