// ov2-app.jsx — main Overview v2 application

const { TTProvider, useTT, Delta, Sparkline, StackedArea, Heatmap, PaceRow, HeroCard, TopBar, Pulse, Drawer, SkeletonOverview, HelpIcon } = window.OV2_UI;
const Heatmap14 = window.Heatmap14;

const OV_DEFAULTS = /*EDITMODE-BEGIN*/{
  "state": "default",
  "theme": "light",
  "lang": "ru",
  "density": "default",
  "view": "desktop",
  "tab": "overview",
  "attrModel": "time",
  "privacyMode": false,
  "dedupClean": false,
  "period": "30d",
  "compare": "prev"
}/*EDITMODE-END*/;

const OV_PERIOD_VALUES = ['7d', '30d', '90d', 'ytd'];
const OV_COMPARE_VALUES = ['prev', 'ly', 'avg90'];
const ovSafePeriod = (value) => OV_PERIOD_VALUES.includes(value) ? value : '30d';
const ovSafeCompare = (value) => OV_COMPARE_VALUES.includes(value) ? value : 'prev';
const ovOptionLabel = (options, value, fallback) => {
  const found = (options || []).find((opt) => opt.value === value);
  return found ? found.label : fallback;
};

/* ===== Marketing strip ===== */
const MarketingStrip = ({ data, t, help, onCardClick, compareLabel }) => {
  return (
    <div className="row-4">
      <div className="card mk-card clickable" onClick={() => onCardClick('spend')}>
        <div className="hero-head">
          <div className="hero-lbl">{t.hero.spend}</div>
          <HelpIcon help={help.spend} />
        </div>
        <div className="hero-num" style={{ fontSize: 22 }}>{data.spend.value}</div>
        <div className="hero-secondary">{data.spend.sub}</div>
        {data.spend.delta && (
          <div className="hero-foot">
            <Delta sign={data.spend.deltaSign}>{data.spend.delta}</Delta>
            <span className="delta-cmp">{compareLabel}</span>
          </div>
        )}
      </div>
      <div className="card mk-card clickable" onClick={() => onCardClick('roas')}>
        <div className="hero-head">
          <div className="hero-lbl">{t.hero.roas}</div>
          <HelpIcon help={help.roas} />
        </div>
        <div className="hero-num" style={{ fontSize: 22 }}>{data.roas.value}</div>
        <div className="hero-foot">
          <Delta sign={data.roas.deltaSign}>{data.roas.delta}</Delta>
          <span className="delta-cmp">{compareLabel}</span>
        </div>
      </div>
      <div className="card mk-card clickable" onClick={() => onCardClick('cac')}>
        {data.cac.alert && <span className="hero-alert-dot" style={{ right: 32 }}></span>}
        <div className="hero-head">
          <div className="hero-lbl">{t.hero.cac}</div>
          <HelpIcon help={help.cac} />
        </div>
        <div className="hero-num" style={{ fontSize: 22 }}>{data.cac.value}</div>
        <div className="hero-foot">
          <Delta sign={data.cac.deltaSign}>{data.cac.delta}</Delta>
          <span className="delta-cmp">{compareLabel}</span>
        </div>
        <div className="hero-secondary" style={{ fontSize: 11 }}>{data.cac.sub}</div>
      </div>
      <div className="card mk-card clickable" onClick={() => onCardClick('direct')}>
        <div className="hero-head">
          <div className="hero-lbl">{t.hero.direct}</div>
          <HelpIcon help={help.direct} />
        </div>
        <div className="hero-num" style={{ fontSize: 22 }}>{data.direct.value}</div>
        <div className="hero-foot">
          <Delta sign={data.direct.deltaSign}>{data.direct.delta}</Delta>
        </div>
        <div className="hero-secondary" style={{ fontSize: 11 }}>{data.direct.sub}</div>
      </div>
    </div>
  );
};

/* ===== Loyalty card ===== */
const LoyaltyCard = ({ data, t, help, onOpenDrawer }) => {
  const helpKeys = ['repeat', 'review', 'newReviews'];
  const drawerKeys = ['loyaltyRepeat', 'loyaltyReviewScore', 'loyaltyNewReviews'];
  return (
    <div className="card" data-screen-label="09 Loyalty">
      <div className="card-head">
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <div className="card-title">{t.loyalty.title}</div>
          <HelpIcon help={help.loyalty} />
        </div>
      </div>
      {data.map((row, i) => (
        <div
          className="loy-row clickable"
          key={i}
          role="button"
          tabIndex={0}
          onClick={() => onOpenDrawer && onOpenDrawer(drawerKeys[i])}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.preventDefault();
              if (onOpenDrawer) onOpenDrawer(drawerKeys[i]);
            }
          }}
        >
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <div className="loy-lbl">{row.lbl}</div>
              <HelpIcon help={help[helpKeys[i]]} />
            </div>
            <div className="loy-val">
              {row.val}
              {row.sub && <span className="text-3" style={{ fontSize: 14, fontWeight: 400 }}>{row.sub}</span>}
            </div>
          </div>
          <div className="loy-right">
            {row.delta && <Delta sign={row.deltaSign}>{row.delta}</Delta>}
            {row.mini && <div className="loy-mini">{row.mini}</div>}
          </div>
        </div>
      ))}
    </div>
  );
};

/* ===== Bookings table ===== */
const BK_MS = 24 * 60 * 60 * 1000;
const bkParse = (iso) => new Date(`${iso}T12:00:00`);
const bkIso = (date) => {
  const d = new Date(date);
  const m = String(d.getMonth() + 1).padStart(2, '0');
  const day = String(d.getDate()).padStart(2, '0');
  return `${d.getFullYear()}-${m}-${day}`;
};
const bkAddDays = (iso, days) => {
  const d = bkParse(iso);
  d.setDate(d.getDate() + days);
  return bkIso(d);
};
const bkStartOfWeek = (iso) => {
  const d = bkParse(iso);
  const diff = (d.getDay() + 6) % 7;
  d.setDate(d.getDate() - diff);
  return bkIso(d);
};
const bkEndOfWeek = (iso) => bkAddDays(bkStartOfWeek(iso), 6);
const bkGlobalRange = (globalPeriod, today) => {
  const safe = ovSafePeriod(globalPeriod);
  if (safe === '7d') return { start: bkAddDays(today, -6), end: today };
  if (safe === '90d') return { start: bkAddDays(today, -89), end: today };
  if (safe === 'ytd') {
    const td = bkParse(today);
    return { start: bkIso(new Date(td.getFullYear(), 0, 1, 12)), end: today };
  }
  return { start: bkAddDays(today, -29), end: today };
};
const bkNights = (b) => Math.max(1, Math.round((bkParse(b.departure) - bkParse(b.arrival)) / BK_MS));
const bkLeadDays = (b) => Math.max(0, Math.round((bkParse(b.arrival) - bkParse(b.bookingDate)) / BK_MS));
const bkRevenue = (b) => (b.status === 'cancelled' || b.status === 'no_show') ? 0 : b.revenue;
const bkLocale = (lang) => lang === 'ru' ? 'ru-RU' : 'en-US';
const bkDate = (iso, lang) => new Intl.DateTimeFormat(bkLocale(lang), { month: 'short', day: 'numeric' }).format(bkParse(iso)).replace('.', '');
const bkMonth = (iso, lang) => new Intl.DateTimeFormat(bkLocale(lang), { month: 'long' }).format(bkParse(iso));
const bkRange = (start, end, lang) => `${bkDate(start, lang)} – ${bkDate(end, lang)}`;
const bkGuests = (b) => `${b.guests.adults}A${b.guests.children ? ` · ${b.guests.children}C` : ''}`;
const bkOrdinal = (n) => {
  if (n === 1) return '1st';
  if (n === 2) return '2nd';
  if (n === 3) return '3rd';
  return `${n}th`;
};
const bkStatusClass = (status) => ({
  in_house: 'in-house',
  confirmed: 'confirmed',
  checked_out: 'checked-out',
  cancelled: 'cancelled',
  no_show: 'no-show',
}[status] || 'confirmed');
const bkDiscoveryKey = (b) => b.discovery || '—';
const bkWithin = (b, range) => b.arrival <= range.end && b.departure > range.start;
const bkOptionSort = (a, b) => String(a).localeCompare(String(b));

const BookingsTableBlock = ({ lang, privacyMode, onOpenDrawer, mobile, globalPeriod, globalPeriodLabel }) => {
  const t = window.I18N_OV2[lang].bookingsTable;
  const help = window.HELP_OV2[lang].bookingsTable;
  const bookings = window.OV2.bookings || [];
  const today = window.OV2.today || bkIso(new Date());
  const [periodKey, setPeriodKey] = React.useState('week');
  const [customRange, setCustomRange] = React.useState(null);
  const [customDraft, setCustomDraft] = React.useState({ start: today, end: bkAddDays(today, 1) });
  const [customOpen, setCustomOpen] = React.useState(false);
  const [openMenu, setOpenMenu] = React.useState(null);
  const [view, setView] = React.useState('compact');
  const [filters, setFilters] = React.useState({ status: [], cabin: [], channel: [], country: [], discovery: [] });
  const [sort, setSort] = React.useState({ key: 'arrival', dir: 'asc' });
  const [warningDismissed, setWarningDismissed] = React.useState(() => {
    try { return window.localStorage.getItem('sv_discovery_warning_dismissed') === '1'; }
    catch (e) { return false; }
  });

  React.useEffect(() => {
    const close = (e) => {
      if (!e.target.closest('.bk-table-menu-wrap') && !e.target.closest('.bk-table-dropdown')) setOpenMenu(null);
    };
    document.addEventListener('mousedown', close);
    return () => document.removeEventListener('mousedown', close);
  }, []);

  const periodOptions = React.useMemo(() => {
    const thisStart = bkStartOfWeek(today);
    const thisEnd = bkEndOfWeek(today);
    const prevStart = bkAddDays(thisStart, -7);
    const prevEnd = bkAddDays(thisEnd, -7);
    const td = bkParse(today);
    const monthStart = bkIso(new Date(td.getFullYear(), td.getMonth(), 1, 12));
    const prevMonthStart = bkIso(new Date(td.getFullYear(), td.getMonth() - 1, 1, 12));
    const prevMonthEnd = bkIso(new Date(td.getFullYear(), td.getMonth(), 0, 12));
    const globalLabel = globalPeriodLabel || t.periodGlobal;
    const globalText = t.periodGlobalWithLabel ? t.periodGlobalWithLabel.replace('{label}', globalLabel) : `${t.periodGlobal} (${globalLabel})`;
    return [
      { key: 'global', short: globalLabel, label: globalText, range: bkGlobalRange(globalPeriod, today), divider: true },
      { key: 'today', short: t.today, label: `${t.today} (${bkDate(today, lang)})`, range: { start: today, end: today } },
      { key: 'tomorrow', short: t.tomorrow, label: `${t.tomorrow} (${bkDate(bkAddDays(today, 1), lang)})`, range: { start: bkAddDays(today, 1), end: bkAddDays(today, 1) } },
      { key: 'week', short: t.thisWeek, label: `${t.thisWeek} (${bkRange(thisStart, thisEnd, lang)})`, range: { start: thisStart, end: thisEnd } },
      { key: 'prevWeek', short: t.previousWeek, label: `${t.previousWeek} (${bkRange(prevStart, prevEnd, lang)})`, range: { start: prevStart, end: prevEnd } },
      { key: 'month', short: t.thisMonth, label: `${t.thisMonth} (${bkRange(monthStart, today, lang)})`, range: { start: monthStart, end: today } },
      { key: 'prevMonth', short: t.previousMonth, label: `${t.previousMonth} (${bkMonth(prevMonthStart, lang)})`, range: { start: prevMonthStart, end: prevMonthEnd } },
      {
        key: 'custom',
        short: customRange ? bkRange(customRange.start, customRange.end, lang) : t.customRange,
        label: customRange ? `${t.customRange} (${bkRange(customRange.start, customRange.end, lang)})` : t.customRange,
        range: customRange || { start: today, end: bkAddDays(today, 1) },
      },
    ];
  }, [today, lang, t, customRange, globalPeriod, globalPeriodLabel]);

  const activePeriod = periodOptions.find((o) => o.key === periodKey) || periodOptions[3];
  const periodRows = React.useMemo(() => bookings.filter((b) => bkWithin(b, activePeriod.range)), [bookings, activePeriod]);

  const options = React.useMemo(() => ({
    status: Object.keys(t.statuses).map((value) => ({ value, label: t.statuses[value] })),
    cabin: (window.OV2.cabins || []).map((value) => ({ value, label: value })),
    channel: [...new Set(bookings.map((b) => b.channel))].sort(bkOptionSort).map((value) => ({ value, label: value })),
    country: [...new Set(bookings.map((b) => b.country.code))].sort(bkOptionSort).map((value) => {
      const found = bookings.find((b) => b.country.code === value);
      return { value, label: `${found.country.flag} ${value}` };
    }),
    discovery: [...new Set(bookings.map((b) => bkDiscoveryKey(b)))].sort(bkOptionSort).map((value) => ({ value, label: value })),
  }), [bookings, t.statuses]);

  const hasFilters = Object.values(filters).some((arr) => arr.length);
  const filteredRows = React.useMemo(() => periodRows.filter((b) => {
    if (filters.status.length && !filters.status.includes(b.status)) return false;
    if (filters.cabin.length && !filters.cabin.includes(b.cabin)) return false;
    if (filters.channel.length && !filters.channel.includes(b.channel)) return false;
    if (filters.country.length && !filters.country.includes(b.country.code)) return false;
    if (filters.discovery.length && !filters.discovery.includes(bkDiscoveryKey(b))) return false;
    return true;
  }), [periodRows, filters]);

  const sortedRows = React.useMemo(() => {
    const rows = [...filteredRows];
    rows.sort((a, b) => {
      let av;
      let bv;
      if (sort.key === 'status') { av = t.statuses[a.status]; bv = t.statuses[b.status]; }
      else if (sort.key === 'country') { av = a.country.code; bv = b.country.code; }
      else if (sort.key === 'dates') { av = a.arrival; bv = b.arrival; }
      else if (sort.key === 'guests') { av = a.guests.adults + a.guests.children; bv = b.guests.adults + b.guests.children; }
      else if (sort.key === 'discovery') { av = bkDiscoveryKey(a); bv = bkDiscoveryKey(b); }
      else if (sort.key === 'revenue') { av = bkRevenue(a); bv = bkRevenue(b); }
      else if (sort.key === 'leadTime') { av = bkLeadDays(a); bv = bkLeadDays(b); }
      else if (sort.key === 'repeatVisitCount') { av = a.repeatVisitCount; bv = b.repeatVisitCount; }
      else { av = a[sort.key]; bv = b[sort.key]; }
      const cmp = typeof av === 'number' ? av - bv : String(av || '').localeCompare(String(bv || ''));
      return sort.dir === 'asc' ? cmp : -cmp;
    });
    return rows;
  }, [filteredRows, sort, t.statuses]);

  const visibleRows = sortedRows.slice(0, mobile ? 6 : 10);
  const displayedEmptyPct = visibleRows.length
    ? Math.round((visibleRows.filter((b) => !b.discovery).length / visibleRows.length) * 100)
    : 0;
  const showDiscoveryWarning = displayedEmptyPct > 50 && !warningDismissed;
  const inHouseToday = bookings.filter((b) => b.status === 'in_house' && b.arrival <= today && b.departure > today).length;
  const activeRows = filteredRows.filter((b) => b.status !== 'cancelled' && b.status !== 'no_show');
  const stats = {
    count: filteredRows.length,
    nights: activeRows.reduce((sum, b) => sum + bkNights(b), 0),
    revenue: filteredRows.reduce((sum, b) => sum + bkRevenue(b), 0),
    adults: activeRows.reduce((sum, b) => sum + b.guests.adults, 0),
    children: activeRows.reduce((sum, b) => sum + b.guests.children, 0),
  };
  const subline = `${stats.count} ${t.aggregateBookings} · ${stats.nights} ${t.aggregateNights} · €${stats.revenue.toLocaleString('en-US')} ${t.aggregateRevenue} · ${inHouseToday} ${t.aggregateInHouse}`;
  const totalGuests = `${stats.adults}A${stats.children ? ` · ${stats.children}C` : ''}`;

  const toggleFilter = (kind, value) => {
    setFilters((prev) => {
      const set = new Set(prev[kind]);
      if (set.has(value)) set.delete(value);
      else set.add(value);
      return { ...prev, [kind]: Array.from(set) };
    });
  };
  const clearFilter = (kind, value) => setFilters((prev) => ({ ...prev, [kind]: prev[kind].filter((v) => v !== value) }));
  const clearAllFilters = () => setFilters({ status: [], cabin: [], channel: [], country: [], discovery: [] });
  const setSortKey = (key) => setSort((prev) => prev.key === key ? { key, dir: prev.dir === 'asc' ? 'desc' : 'asc' } : { key, dir: 'asc' });
  const choosePeriod = (key) => {
    if (key === 'custom') {
      setCustomDraft(customRange || { start: today, end: bkAddDays(today, 1) });
      setCustomOpen(true);
      setOpenMenu(null);
      return;
    }
    setPeriodKey(key);
    setOpenMenu(null);
  };
  const dismissWarning = () => {
    setWarningDismissed(true);
    try { window.localStorage.setItem('sv_discovery_warning_dismissed', '1'); } catch (e) {}
  };

  const filterLabel = (kind, value) => {
    const found = (options[kind] || []).find((o) => o.value === value);
    return found ? found.label : value;
  };
  const activePills = Object.keys(filters).flatMap((kind) => filters[kind].map((value) => ({ kind, value, label: `${t.filters[kind]}: ${filterLabel(kind, value)}` })));
  const discoveryTitle = (b) => t.confidence[b.discoveryConfidence || 'unknown'] || t.confidence.unknown;

  const FilterChip = ({ kind }) => (
    <div className="bk-table-menu-wrap">
      <button
        type="button"
        className={`bk-table-chip ${filters[kind].length ? 'active' : ''}`}
        onClick={() => setOpenMenu(openMenu === kind ? null : kind)}
      >
        {t.filters[kind]}{filters[kind].length ? ` (${filters[kind].length})` : ''}
        <I name="chevron-down" size={12}/>
      </button>
      {openMenu === kind && (
        <div className="bk-table-dropdown">
          {(options[kind] || []).map((opt) => (
            <button type="button" className="bk-table-dropdown-item" key={opt.value} onClick={() => toggleFilter(kind, opt.value)}>
              <span className={`bk-table-check ${filters[kind].includes(opt.value) ? 'checked' : ''}`}></span>
              <span>{opt.label}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  );

  const SortHead = ({ sortKey, children, className }) => (
    <th className={className || ''}>
      <button type="button" className="bk-table-sort" onClick={() => setSortKey(sortKey)}>
        {children}
        {sort.key === sortKey && <I name={sort.dir === 'asc' ? 'chevron-up' : 'chevron-down'} size={12}/>}
      </button>
    </th>
  );

  const BookingName = ({ b }) => (
    <span className="bk-table-guest">
      <span>{privacyMode ? b.guestNameMasked : b.guestName}</span>
      {b.repeatVisitCount > 1 && <span className="bk-table-repeat">{t.repeat} {b.repeatVisitCount}x</span>}
    </span>
  );

  const RevenueCell = ({ b }) => (
    <span className="bk-table-revenue">
      {b.status === 'cancelled' || b.status === 'no_show' ? (
        <React.Fragment>€0 {b.originalRevenue && <s>€{b.originalRevenue}</s>}</React.Fragment>
      ) : `€${b.revenue.toLocaleString('en-US')}`}
    </span>
  );

  const TableRows = () => (
    <React.Fragment>
      {visibleRows.map((b) => (
        <tr key={b.id} className="bk-table-row" onClick={() => onOpenDrawer('booking')}>
          <td>
            <span className="bk-table-status">
              <span className={`bk-table-dot ${bkStatusClass(b.status)}`}></span>
              {t.statuses[b.status]}
            </span>
          </td>
          <td className="bk-table-cabin">{b.cabin}</td>
          <td><BookingName b={b} /></td>
          <td><span title={b.country.name}>{b.country.flag} {b.country.code}</span></td>
          <td>{bkDate(b.arrival, lang)} → {bkDate(b.departure, lang)} · {bkNights(b)}{t.nightsShort}</td>
          <td>{bkGuests(b)}</td>
          <td>{b.channel}</td>
          <td>
            <span className="bk-table-discovery">
              <span className={`bk-table-disc-dot ${b.discoveryConfidence || 'unknown'}`} title={discoveryTitle(b)}></span>
              {b.discovery || '—'}
            </span>
          </td>
          {view === 'detailed' && (
            <React.Fragment>
              <td>{bkDate(b.bookingDate, lang)}</td>
              <td>{bkLeadDays(b)}{t.daysBefore}</td>
              <td className="bk-table-note" title={b.notes || ''}>{b.notes || '—'}</td>
              <td>{bkOrdinal(b.repeatVisitCount)}</td>
            </React.Fragment>
          )}
          <td className="num"><RevenueCell b={b} /></td>
        </tr>
      ))}
    </React.Fragment>
  );

  const EmptyState = () => {
    if (periodRows.length === 0) return <div className="bk-table-empty">{t.emptyPeriod}</div>;
    if (hasFilters && filteredRows.length === 0) {
      return (
        <div className="bk-table-empty">
          {t.emptyFilters} <button type="button" onClick={clearAllFilters}>× {t.resetFilters}</button>
        </div>
      );
    }
    return null;
  };

  const MobileCards = () => (
    <div className="bk-table-mobile-cards">
      {visibleRows.map((b) => (
        <button type="button" className="bk-table-mobile-card" key={b.id} onClick={() => onOpenDrawer('booking')}>
          <div className="bk-table-mobile-top">
            <span className="bk-table-status">
              <span className={`bk-table-dot ${bkStatusClass(b.status)}`}></span>
              {b.cabin}
            </span>
            <RevenueCell b={b} />
          </div>
          <div className="bk-table-mobile-guest"><BookingName b={b} /></div>
          <div className="bk-table-mobile-line">{bkDate(b.arrival, lang)} → {bkDate(b.departure, lang)} · {bkNights(b)}{t.nightsShort} · {bkGuests(b)}</div>
          <div className="bk-table-mobile-meta">{b.country.flag} {b.country.code} · {b.channel} · {b.discovery || '—'}</div>
        </button>
      ))}
      <div className="bk-table-mobile-total">
        <div>
          <div>{t.total}</div>
          <span>{stats.count} {t.bookings} · {stats.nights}{t.nightsShort} · {totalGuests}</span>
        </div>
        <strong>€{stats.revenue.toLocaleString('en-US')}</strong>
      </div>
    </div>
  );

  return (
    <div className="card bk-table-card" data-screen-label="08 Bookings table">
      <div className="bk-table-header">
        <div className="bk-table-title-wrap">
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <div className="card-title">{t.title}</div>
            <HelpIcon help={help} />
          </div>
          <div className="bk-table-sub">{subline}</div>
        </div>
        <div className="bk-table-controls">
          <div className="bk-table-menu-wrap bk-table-period-wrap">
            <button type="button" className="bk-table-btn" onClick={() => setOpenMenu(openMenu === 'period' ? null : 'period')}>
              <I name="calendar" size={14}/>
              {activePeriod.short}
              <I name="chevron-down" size={12}/>
            </button>
            {openMenu === 'period' && (
              <div className="bk-table-dropdown period">
                {periodOptions.map((opt) => (
                  <React.Fragment key={opt.key}>
                    <button type="button" className={`bk-table-dropdown-item ${periodKey === opt.key ? 'selected' : ''}`} onClick={() => choosePeriod(opt.key)}>
                      <span>{opt.label}</span>
                    </button>
                    {opt.divider && <div className="bk-table-dropdown-sep"></div>}
                  </React.Fragment>
                ))}
              </div>
            )}
          </div>

          {mobile ? (
            <FilterChip kind="status" />
          ) : (
            <div className="bk-table-filter-group">
              {['status', 'cabin', 'channel', 'country', 'discovery'].map((kind) => <FilterChip kind={kind} key={kind} />)}
            </div>
          )}

          {!mobile && (
            <div className="bk-table-segmented">
              <button type="button" className={view === 'compact' ? 'active' : ''} onClick={() => setView('compact')}>{t.compact}</button>
              <button type="button" className={view === 'detailed' ? 'active' : ''} onClick={() => setView('detailed')}>{t.detailed}</button>
            </div>
          )}
          {!mobile && <button type="button" className="bk-table-icon-btn" title={t.export}><I name="download" size={15}/></button>}
        </div>
      </div>

      {showDiscoveryWarning && (
        <div className="bk-table-banner warn">
          <I name="alert-triangle" size={14}/>
          <span>{t.discoveryWarning} {displayedEmptyPct}% {t.discoveryAdvice}</span>
          <button type="button" onClick={dismissWarning}>× {t.dismiss}</button>
        </div>
      )}

      {periodKey !== 'global' && (
        <div className="bk-table-banner info">
          <I name="calendar" size={14}/>
          <span>{t.customPeriod}: {activePeriod.label}</span>
          <button type="button" onClick={() => setPeriodKey('global')}>× {t.resetGlobal}</button>
        </div>
      )}

      {activePills.length > 0 && (
        <div className="bk-table-active-filters" aria-label={t.activeFilters}>
          {activePills.map((pill) => (
            <button type="button" className="bk-table-pill" key={`${pill.kind}-${pill.value}`} onClick={() => clearFilter(pill.kind, pill.value)}>
              {pill.label} <span>×</span>
            </button>
          ))}
          <button type="button" className="bk-table-clear" onClick={clearAllFilters}>× {t.clearAll}</button>
        </div>
      )}

      {visibleRows.length === 0 ? (
        <EmptyState />
      ) : mobile ? (
        <MobileCards />
      ) : (
        <div className="bk-table-wrap">
          <table className="bk-table">
            <colgroup>
              <col style={{ width: 110 }} />
              <col style={{ width: 110 }} />
              <col style={{ width: 140 }} />
              <col style={{ width: 80 }} />
              <col style={{ width: 130 }} />
              <col style={{ width: 90 }} />
              <col style={{ width: 110 }} />
              <col style={{ width: 130 }} />
              {view === 'detailed' && (
                <React.Fragment>
                  <col style={{ width: 90 }} />
                  <col style={{ width: 80 }} />
                  <col style={{ width: 140 }} />
                  <col style={{ width: 80 }} />
                </React.Fragment>
              )}
              <col style={{ width: 100 }} />
            </colgroup>
            <thead>
              <tr>
                <SortHead sortKey="status">{t.columns.status}</SortHead>
                <SortHead sortKey="cabin">{t.columns.cabin}</SortHead>
                <SortHead sortKey="guestName">{t.columns.guest}</SortHead>
                <SortHead sortKey="country">{t.columns.country}</SortHead>
                <SortHead sortKey="dates">{t.columns.dates}</SortHead>
                <SortHead sortKey="guests">{t.columns.guests}</SortHead>
                <SortHead sortKey="channel">{t.columns.channel}</SortHead>
                <SortHead sortKey="discovery">{t.columns.discovery}</SortHead>
                {view === 'detailed' && (
                  <React.Fragment>
                    <SortHead sortKey="bookingDate">{t.columns.bookingDate}</SortHead>
                    <SortHead sortKey="leadTime">{t.columns.leadTime}</SortHead>
                    <SortHead sortKey="notes">{t.columns.notes}</SortHead>
                    <SortHead sortKey="repeatVisitCount">{t.columns.repeatStatus}</SortHead>
                  </React.Fragment>
                )}
                <SortHead sortKey="revenue" className="num">{t.columns.revenue}</SortHead>
              </tr>
            </thead>
            <tbody><TableRows /></tbody>
            <tfoot>
              <tr className="bk-table-total-row">
                <td>{t.total}</td>
                <td>{stats.count} {t.bookings}</td>
                <td></td>
                <td></td>
                <td>{stats.nights}{t.nightsShort}</td>
                <td>{totalGuests}</td>
                <td></td>
                <td></td>
                {view === 'detailed' && (
                  <React.Fragment>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                  </React.Fragment>
                )}
                <td className="num">€{stats.revenue.toLocaleString('en-US')}</td>
              </tr>
            </tfoot>
          </table>
        </div>
      )}

      {!mobile && sortedRows.length > visibleRows.length && (
        <button type="button" className="bk-table-footer-link" onClick={() => onOpenDrawer('bookingsList')}>
          {t.showAll} {sortedRows.length} {t.bookings} →
        </button>
      )}

      {customOpen && (
        <div className="bk-table-modal-overlay" onMouseDown={() => setCustomOpen(false)}>
          <div className="bk-table-modal" onMouseDown={(e) => e.stopPropagation()}>
            <div className="bk-table-modal-head">
              <div>
                <div className="card-title">{t.customModalTitle}</div>
                <div className="bk-table-sub">{t.customModalSub}</div>
              </div>
              <button type="button" className="drawer-close" onClick={() => setCustomOpen(false)}><I name="x" size={16}/></button>
            </div>
            <label className="bk-table-field">
              <span>{t.from}</span>
              <input type="date" value={customDraft.start} onChange={(e) => setCustomDraft({ ...customDraft, start: e.target.value })} />
            </label>
            <label className="bk-table-field">
              <span>{t.to}</span>
              <input type="date" value={customDraft.end} onChange={(e) => setCustomDraft({ ...customDraft, end: e.target.value })} />
            </label>
            <div className="bk-table-modal-actions">
              <button type="button" className="tb-select" onClick={() => setCustomOpen(false)}>{t.cancel}</button>
              <button
                type="button"
                className="tb-select active"
                onClick={() => {
                  const start = customDraft.start <= customDraft.end ? customDraft.start : customDraft.end;
                  const end = customDraft.start <= customDraft.end ? customDraft.end : customDraft.start;
                  setCustomRange({ start, end });
                  setPeriodKey('custom');
                  setCustomOpen(false);
                }}
              >{t.apply}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

/* ===== Desktop main view ===== */
const DesktopOverview = ({ state, theme, lang, privacyMode, onOpenDrawer, period, compare }) => {
  const t = window.I18N_OV2[lang];
  const help = window.HELP_OV2[lang];
  const isAlert = state === 'alert';
  const safePeriod = ovSafePeriod(period);
  const safeCompare = ovSafeCompare(compare);
  const data = window.OV2.deriveForPeriod(window.OV2.default, safePeriod, safeCompare, isAlert);
  const periodLabel = ovOptionLabel(t.period.options, safePeriod, t.period.lbl);
  const compareLabel = ovOptionLabel(t.compare.options, safeCompare, t.compare.lbl);
  const paceData = isAlert ? window.OV2.paceAlert : window.OV2.pace;
  const [hidden, setHidden] = React.useState({});

  return (
    <div className="page" data-screen-label={isAlert ? "02 Alert" : "01 Default"}>
      {/* Pulse strip */}
      <div className="section" style={{ marginTop: 16 }}>
        <Pulse t={t} alertMode={isAlert} help={help.pulseItems} onOpenDrawer={onOpenDrawer} />
      </div>

      {/* Compact KPI deck + loyalty */}
      <div className="overview-metrics-top section">
        <div className="overview-kpi-stack">
          <div className="row-4">
            <HeroCard
              lbl={t.hero.revenue}
              num={data.revenue.value}
              deltaText={(data.revenue.delta > 0 ? '+' : '') + data.revenue.delta + '%'}
              deltaSign={data.revenue.deltaSign}
              spark={data.revenue.spark}
              sparkColor="var(--chart-1)"
              help={help.revenue}
              cmpText={compareLabel}
              onClick={() => onOpenDrawer('revenue')}
            />
            <HeroCard
              lbl={t.hero.rpg}
              num={data.rpg.value}
              deltaText={(data.rpg.delta > 0 ? '+' : '') + data.rpg.delta + '%'}
              deltaSign={data.rpg.deltaSign}
              spark={data.rpg.spark}
              sparkColor="var(--chart-2)"
              help={help.rpg}
              cmpText={compareLabel}
              onClick={() => onOpenDrawer('rpg')}
            />
            <HeroCard
              lbl={t.hero.occupancy}
              num={data.occupancy.value}
              sub={` / ${data.occupancy.total}`}
              deltaText={data.occupancy.delta}
              deltaSign={data.occupancy.deltaSign}
              spark={data.occupancy.spark}
              sparkColor="var(--chart-3)"
              help={help.occupancy}
              cmpText={compareLabel}
              onClick={() => onOpenDrawer('occupancy')}
            />
            <HeroCard
              lbl={t.hero.gop}
              num={data.gop.value}
              deltaText={data.gop.delta}
              deltaSign={data.gop.deltaSign}
              alert={data.gop.alert}
              spark={data.gop.spark}
              sparkColor="var(--chart-4)"
              help={help.gop}
              cmpText={compareLabel}
              onClick={() => onOpenDrawer('gop')}
            />
          </div>
          <MarketingStrip data={data} t={t} help={help} compareLabel={compareLabel} onCardClick={(k) => onOpenDrawer(k)} />
        </div>
        <LoyaltyCard data={data.loyalty} t={t} help={help} onOpenDrawer={onOpenDrawer} />
      </div>

      {/* Heatmap 14 */}
      <div className="section">
        <Heatmap14 lang={lang} />
      </div>

      {/* Revenue trend */}
      <div className="section">
        <div className="card" data-screen-label="05 Revenue trend">
          <div className="card-head">
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div className="card-title">{t.chart.title}</div>
              <HelpIcon help={help.chart} />
            </div>
            <div className="card-mix">{t.chart.mix}</div>
          </div>
          <StackedArea data={data.chartStreams} t={t} hidden={hidden} />
          <div className="chart-legend">
            {[
              { k: 'rooms', c: 'var(--chart-1)', l: t.chart.legend.rooms },
              { k: 'spa', c: 'var(--chart-2)', l: t.chart.legend.spa },
              { k: 'fnb', c: 'var(--chart-3)', l: t.chart.legend.fnb },
              { k: 'other', c: 'var(--chart-4)', l: t.chart.legend.other },
            ].map(it => (
              <div
                key={it.k}
                className={`legend-item ${hidden[it.k] ? 'muted' : ''}`}
                onClick={() => setHidden(h => ({ ...h, [it.k]: !h[it.k] }))}
              >
                <span className="legend-sw" style={{ background: it.c }}></span>{it.l}
              </div>
            ))}
            <div className="legend-item muted" title={t.chart.padelHint}>
              <span className="legend-sw" style={{ background: 'var(--chart-5)' }}></span>
              {t.chart.legend.padel}
              <span className="legend-pad-badge">{t.chart.padelHint}</span>
            </div>
          </div>
        </div>
      </div>

      {/* Bookings table */}
      <div className="section">
        <BookingsTableBlock lang={lang} privacyMode={privacyMode} onOpenDrawer={onOpenDrawer} globalPeriod={safePeriod} globalPeriodLabel={periodLabel} />
      </div>

      {/* Pace */}
      <div className="section">
        <div className="card" data-screen-label="07 Pace">
          <div className="card-head">
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div className="card-title">{t.pace.title}</div>
              <HelpIcon help={help.pace} />
            </div>
            <div className="card-sub">{t.pace.otb}</div>
          </div>
          <div>
            {paceData.map((row, i) => <PaceRow key={i} row={row} help={help.paceRows && help.paceRows[i]} />)}
          </div>
        </div>
      </div>
    </div>
  );
};

/* ===== Mobile main view ===== */
const MobileOverview = ({ state, lang, privacyMode, onOpenDrawer, period, compare }) => {
  const t = window.I18N_OV2[lang];
  const help = window.HELP_OV2[lang];
  const isAlert = state === 'alert';
  const safePeriod = ovSafePeriod(period);
  const safeCompare = ovSafeCompare(compare);
  const data = window.OV2.deriveForPeriod(window.OV2.default, safePeriod, safeCompare, isAlert);
  const periodLabel = ovOptionLabel(t.period.options, safePeriod, t.period.lbl);
  const paceData = isAlert ? window.OV2.paceAlert : window.OV2.pace;

  return (
    <div className="mobile-wrap" data-screen-label="09 Mobile">
      <div className="mobile-frame">
        <div className="m-topbar">
          <div className="tb-logo" style={{ fontSize: 13 }}>{t.appName}</div>
          <div style={{ display: 'flex', gap: 8 }}>
            <button className="drawer-close"><I name="bell" size={16}/></button>
            <div className="tb-avatar" style={{ width: 28, height: 28, fontSize: 11 }}>МК</div>
          </div>
        </div>
        <div className="m-tabs">
          {t.tabs.map((tab, i) => (
            <button key={tab} className={`m-tab ${i === 0 ? 'active' : ''}`}>{tab}</button>
          ))}
        </div>

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0 4px 12px' }}>
          <button className="tb-select" style={{ height: 30, fontSize: 12 }}><I name="calendar" size={12}/>{periodLabel}</button>
          <div style={{ fontSize: 11, color: 'var(--text-3)' }}>{t.updated}</div>
        </div>

        {/* Pulse — wraps to 2 rows on mobile */}
        <div className="card" style={{ padding: '12px 14px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, position: 'relative' }}>
          {[
            { key: 'pulse_inhouse', icon: 'home', val: '4/5', lbl: lang === 'en' ? 'cabins' : 'домиков', help: help.pulseItems && help.pulseItems.inhouse },
            { key: 'pulse_arrivals', icon: 'log-in', val: '2', lbl: lang === 'en' ? 'arrivals' : 'заезда', help: help.pulseItems && help.pulseItems.arrivals },
            { key: 'pulse_departures', icon: 'log-out', val: '1', lbl: lang === 'en' ? 'departure' : 'выезд', help: help.pulseItems && help.pulseItems.departures },
            { key: 'pulse_spa', icon: 'sparkles', val: '6', lbl: lang === 'en' ? 'spa' : 'спа', help: help.pulseItems && help.pulseItems.spa },
            { key: 'pulse_messages', icon: 'message', val: isAlert ? 7 : 3, lbl: lang === 'en' ? 'msgs' : 'сообщ.', help: help.pulseItems && help.pulseItems.messages, badge: true },
          ].map((item) => (
            <div
              key={item.key}
              className="pulse-strip-element-clickable"
              role="button"
              tabIndex={0}
              onClick={() => onOpenDrawer(item.key)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' || e.key === ' ') {
                  e.preventDefault();
                  onOpenDrawer(item.key);
                }
              }}
              style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}
            >
              <I name={item.icon} size={14}/>
              <span className="pulse-val" style={{ fontSize: 12 }}>{item.val}</span>
              <span className="text-3" style={{ fontSize: 11 }}>{item.lbl}</span>
              {item.badge && <span className="pulse-badge" style={{ minWidth: 14, height: 14, fontSize: 10 }}>!</span>}
              <HelpIcon help={item.help} />
            </div>
          ))}
        </div>

        {/* Hero — 2x2 on mobile */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginTop: 12 }}>
          {[
            { lbl: t.hero.revenue, num: data.revenue.value, dt: (data.revenue.delta > 0 ? '+' : '') + data.revenue.delta + '%', ds: data.revenue.deltaSign, sp: data.revenue.spark, sc: 'var(--chart-1)', help: help.revenue },
            { lbl: t.hero.rpg, num: data.rpg.value, dt: (data.rpg.delta > 0 ? '+' : '') + data.rpg.delta + '%', ds: data.rpg.deltaSign, sp: data.rpg.spark, sc: 'var(--chart-2)', help: help.rpg },
            { lbl: t.hero.occupancy, num: `${data.occupancy.value}/${data.occupancy.total}`, dt: data.occupancy.delta, ds: data.occupancy.deltaSign, sp: data.occupancy.spark, sc: 'var(--chart-3)', help: help.occupancy },
            { lbl: t.hero.gop, num: data.gop.value, dt: data.gop.delta, ds: data.gop.deltaSign, sp: data.gop.spark, sc: 'var(--chart-4)', alert: data.gop.alert, help: help.gop },
          ].map((c, i) => (
            <div className="card" key={i} style={{ padding: 14, minHeight: 110, position: 'relative' }}>
              {c.alert && <span className="hero-alert-dot"></span>}
              <div style={{ display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'space-between' }}>
                <div className="hero-lbl" style={{ fontSize: 10 }}>{c.lbl}</div>
                <HelpIcon help={c.help} />
              </div>
              <div style={{ fontSize: 20, fontWeight: 500, marginTop: 4, fontFeatureSettings: '"tnum"', letterSpacing: '-0.02em' }}>{c.num}</div>
              <div style={{ marginTop: 4 }}><Delta sign={c.ds}>{c.dt}</Delta></div>
              <div style={{ marginTop: 8 }}><Sparkline data={c.sp} color={c.sc} fill height={20} /></div>
            </div>
          ))}
        </div>

        <div style={{ marginTop: 12 }}>
          <Heatmap14 lang={lang} />
        </div>

        <BookingsTableBlock lang={lang} privacyMode={privacyMode} onOpenDrawer={onOpenDrawer} mobile globalPeriod={safePeriod} globalPeriodLabel={periodLabel} />

        {/* Marketing summary — list */}
        <div className="card" style={{ marginTop: 12, padding: '4px 14px' }}>
          {[
            { lbl: t.hero.spend, val: data.spend.value, sub: data.spend.sub, help: help.spend },
            { lbl: t.hero.roas, val: data.roas.value, delta: data.roas.delta, ds: data.roas.deltaSign, help: help.roas },
            { lbl: t.hero.cac, val: data.cac.value, delta: data.cac.delta, ds: data.cac.deltaSign, alert: data.cac.alert, help: help.cac },
            { lbl: t.hero.direct, val: data.direct.value, delta: data.direct.delta, ds: data.direct.deltaSign, help: help.direct },
          ].map((row, i) => (
            <div key={i} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 0', borderTop: i ? '1px solid var(--border)' : 'none' }}>
              <div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <div className="hero-lbl" style={{ fontSize: 10 }}>{row.lbl}</div>
                  <HelpIcon help={row.help} />
                </div>
                <div style={{ fontSize: 16, fontWeight: 500, marginTop: 2, fontFeatureSettings: '"tnum"' }}>
                  {row.val}
                  {row.alert && <span style={{ display: 'inline-block', width: 6, height: 6, borderRadius: 999, background: 'var(--neg)', marginLeft: 6, verticalAlign: 4 }}></span>}
                </div>
                {row.sub && <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 2 }}>{row.sub}</div>}
              </div>
              {row.delta && <Delta sign={row.ds}>{row.delta}</Delta>}
            </div>
          ))}
        </div>

        {/* Pace */}
        <div className="card" style={{ marginTop: 12 }}>
          <div className="card-head" style={{ marginBottom: 10 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div className="card-title" style={{ fontSize: 14 }}>{t.pace.title}</div>
              <HelpIcon help={help.pace} />
            </div>
          </div>
          {paceData.map((row, i) => (
            <div key={i} style={{ padding: '10px 0', borderTop: i ? '1px solid var(--border)' : 'none' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
                <span style={{ fontSize: 12, display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                  {row.label}
                  <HelpIcon help={help.paceRows && help.paceRows[i]} />
                </span>
                <span style={{ fontSize: 12, fontFeatureSettings: '"tnum"', color: 'var(--text-2)' }}><strong style={{ color: 'var(--text)', fontWeight: 500 }}>{row.num}</strong> · {row.pct}%</span>
              </div>
              <div className="pace-bar"><div className={`pace-bar-fill ${row.barKind}`} style={{ width: row.pct + '%' }}></div></div>
              <div style={{ marginTop: 6 }}><Delta sign={row.cmpKind === 'pos' ? 'pos' : row.cmpKind === 'neg' ? 'neg' : 'flat'}>{row.cmp}</Delta></div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

/* ===== States bar (control strip at bottom for switching) ===== */
const StatesBar = ({ state, theme, view, lang, onState, onTheme, onView, onLang }) => {
  return (
    <div className="states-bar">
      <button className={state === 'default' ? 'on' : ''} onClick={() => onState('default')}>Default</button>
      <button className={state === 'alert' ? 'on' : ''} onClick={() => onState('alert')}>Alert</button>
      <button className={state === 'skeleton' ? 'on' : ''} onClick={() => onState('skeleton')}>Skeleton</button>
      <button className={state === 'empty' ? 'on' : ''} onClick={() => onState('empty')}>Empty</button>
      <button className={state === 'drawer' ? 'on' : ''} onClick={() => onState('drawer')}>Drawer</button>
      <div className="vsep"></div>
      <button className={theme === 'light' ? 'on' : ''} onClick={() => onTheme('light')}><I name="sun" size={12}/></button>
      <button className={theme === 'dark' ? 'on' : ''} onClick={() => onTheme('dark')}><I name="moon" size={12}/></button>
      <div className="vsep"></div>
      <button className={view === 'desktop' ? 'on' : ''} onClick={() => onView('desktop')}>Desktop</button>
      <button className={view === 'mobile' ? 'on' : ''} onClick={() => onView('mobile')}>Mobile</button>
      <div className="vsep"></div>
      <button className={lang === 'ru' ? 'on' : ''} onClick={() => onLang('ru')}>RU</button>
      <button className={lang === 'en' ? 'on' : ''} onClick={() => onLang('en')}>EN</button>
    </div>
  );
};

/* ===== App ===== */
const App = () => {
  const [tw, setTweak] = useTweaks(OV_DEFAULTS);
  const [drawerOpen, setDrawerOpen] = React.useState(false);
  const [drawerKey, setDrawerKey] = React.useState('gop');
  const [drawerPayload, setDrawerPayload] = React.useState(null);
  const [mktDrawer, setMktDrawer] = React.useState(null);
  const [mktMetricDrawer, setMktMetricDrawer] = React.useState(null);
  const [bkgDrawer, setBkgDrawer] = React.useState(null);
  const [custDrawer, setCustDrawer] = React.useState(null);

  const openDrawer = React.useCallback((k, payload) => {
    setDrawerKey(k || 'gop');
    setDrawerPayload(payload || null);
    setDrawerOpen(true);
  }, []);

  React.useEffect(() => {
    document.documentElement.dataset.theme = tw.theme;
    document.documentElement.dataset.density = tw.density;
  }, [tw.theme, tw.density]);

  React.useEffect(() => {
    if (tw.state === 'drawer') setDrawerOpen(true);
  }, [tw.state]);

  React.useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const urlPeriod = params.get('period');
    const urlCompare = params.get('compare');
    const edits = {};
    if (OV_PERIOD_VALUES.includes(urlPeriod)) edits.period = urlPeriod;
    if (OV_COMPARE_VALUES.includes(urlCompare)) edits.compare = urlCompare;
    if (Object.keys(edits).length) setTweak(edits);
  }, []);

  React.useEffect(() => {
    const period = ovSafePeriod(tw.period);
    const compare = ovSafeCompare(tw.compare);
    const params = new URLSearchParams(window.location.search);
    if (period !== '30d') params.set('period', period);
    else params.delete('period');
    if (compare !== 'prev') params.set('compare', compare);
    else params.delete('compare');
    const search = params.toString();
    const newUrl = window.location.pathname + (search ? `?${search}` : '') + window.location.hash;
    window.history.replaceState(null, '', newUrl);
  }, [tw.period, tw.compare]);

  const t = window.I18N_OV2[tw.lang];
  const currentPeriod = ovSafePeriod(tw.period);
  const currentCompare = ovSafeCompare(tw.compare);
  const showSkeleton = tw.state === 'skeleton';
  const showMobile = tw.view === 'mobile';

  return (
    <TTProvider>
      {!showMobile && (
        <TopBar
          t={t}
          theme={tw.theme}
          lang={tw.lang}
          density={tw.density}
          state={tw.state}
          tab={tw.tab}
          period={currentPeriod}
          compare={currentCompare}
          onPeriodChange={(v) => setTweak({ period: ovSafePeriod(v) })}
          onCompareChange={(v) => setTweak({ compare: ovSafeCompare(v) })}
          onTab={(v) => setTweak('tab', v)}
        />
      )}

      {showSkeleton ? (
        <SkeletonOverview />
      ) : showMobile ? (
        <MobileOverview state={tw.state === 'alert' ? 'alert' : 'default'} lang={tw.lang} privacyMode={!!tw.privacyMode} period={currentPeriod} compare={currentCompare} onOpenDrawer={openDrawer} />
      ) : tw.tab === 'revenue' ? (
        <window.RevenueTab
          state={tw.state === 'alert' ? 'alert' : 'default'}
          lang={tw.lang}
          onOpenDrawer={openDrawer}
        />
      ) : tw.tab === 'booking' ? (
        <window.BookingTab
          tweaks={{ state: tw.state === 'alert' ? 'alert' : 'default' }}
          lang={tw.lang}
          onOpenBkgDrawer={(k) => setBkgDrawer(k)}
        />
      ) : tw.tab === 'traffic' ? (
        <window.TrafficTab
          state={tw.state === 'alert' ? 'alert' : tw.state === 'skeleton' ? 'skeleton' : 'default'}
          lang={tw.lang}
        />
      ) : tw.tab === 'customers' ? (
        <window.CustomerInsightsTab
          state={tw.state === 'alert' ? 'alert' : tw.state === 'skeleton' ? 'skeleton' : tw.state === 'empty' ? 'empty' : 'default'}
          lang={tw.lang}
          privacyMode={!!tw.privacyMode}
          dedupCount={tw.dedupClean ? 0 : 12}
          onOpenGuest={(name) => setCustDrawer({ type: 'guest', name })}
          onOpenSegment={(seg) => setCustDrawer({ type: 'segment', seg })}
          onOpenCohort={(c) => setCustDrawer({ type: 'cohort', cohort: c })}
          onOpenSource={(src) => setCustDrawer({ type: 'source', src })}
          onOpenAtRisk={() => setCustDrawer({ type: 'atrisk' })}
          onOpenChurn={(kind) => setCustDrawer({ type: 'atrisk', filter: kind })}
        />
      ) : tw.tab === 'marketing' ? (
        <window.MarketingTab
          state={tw.state === 'alert' ? 'alert' : 'default'}
          lang={tw.lang}
          attrModel={tw.attrModel || 'time'}
          onAttrModel={(v) => setTweak('attrModel', v)}
          onOpenMktDrawer={(k) => setMktDrawer(k)}
          onOpenMetricDrawer={(k) => setMktMetricDrawer(k)}
        />
      ) : (
        <DesktopOverview
          state={tw.state === 'alert' ? 'alert' : 'default'}
          theme={tw.theme}
          lang={tw.lang}
          privacyMode={!!tw.privacyMode}
          period={currentPeriod}
          compare={currentCompare}
          onOpenDrawer={openDrawer}
        />
      )}

      <Drawer
        open={drawerOpen}
        onClose={() => { setDrawerOpen(false); setDrawerPayload(null); if (tw.state === 'drawer') setTweak('state', 'default'); }}
        metricKey={drawerKey}
        drawerPayload={drawerPayload}
        lang={tw.lang}
        privacyMode={!!tw.privacyMode}
        onOpenDrawer={openDrawer}
        onNavigateBooking={() => { setDrawerOpen(false); setTweak('tab', 'booking'); }}
      />

      <window.MktDrawerHost openKey={mktDrawer} onClose={() => setMktDrawer(null)} lang={tw.lang} />

      <window.MktMetricDrawerHost openKey={mktMetricDrawer} onClose={() => setMktMetricDrawer(null)} lang={tw.lang} />

      <window.BkgDrawerHost openKey={bkgDrawer} onClose={() => setBkgDrawer(null)} lang={tw.lang} />

      {window.CustDrawerHost && <window.CustDrawerHost open={custDrawer} onClose={() => setCustDrawer(null)} lang={tw.lang} privacyMode={!!tw.privacyMode} onOpenGuest={(name) => setCustDrawer({ type: 'guest', name })} />}

      <StatesBar
        state={tw.state}
        theme={tw.theme}
        view={tw.view}
        lang={tw.lang}
        onState={(v) => { setTweak('state', v); if (v !== 'drawer') setDrawerOpen(false); }}
        onTheme={(v) => setTweak('theme', v)}
        onView={(v) => setTweak('view', v)}
        onLang={(v) => setTweak('lang', v)}
      />

      <TweaksPanel title="Overview tweaks">
        <TweakSection title="Состояние">
          <TweakSelect
            label="State"
            value={tw.state}
            options={[
              { value: 'default', label: 'Default' },
              { value: 'alert', label: 'Alert state' },
              { value: 'skeleton', label: 'Skeleton (loading)' },
              { value: 'empty', label: 'Empty / no data' },
              { value: 'drawer', label: 'Open drawer' },
            ]}
            onChange={(v) => { setTweak('state', v); if (v !== 'drawer') setDrawerOpen(false); else setDrawerOpen(true); }}
          />
        </TweakSection>
        <TweakSection title="Внешний вид">
          <TweakRadio
            label="Theme"
            value={tw.theme}
            options={[
              { value: 'light', label: 'Light' },
              { value: 'dark', label: 'Dark' },
            ]}
            onChange={(v) => setTweak('theme', v)}
          />
          <TweakRadio
            label="Плотность"
            value={tw.density}
            options={[
              { value: 'compact', label: 'Compact' },
              { value: 'default', label: 'Default' },
              { value: 'comfy', label: 'Comfy' },
            ]}
            onChange={(v) => setTweak('density', v)}
          />
          <TweakRadio
            label="View"
            value={tw.view}
            options={[
              { value: 'desktop', label: 'Desktop' },
              { value: 'mobile', label: 'Mobile' },
            ]}
            onChange={(v) => setTweak('view', v)}
          />
          <TweakRadio
            label="Язык"
            value={tw.lang}
            options={[
              { value: 'ru', label: 'RU' },
              { value: 'en', label: 'EN' },
            ]}
            onChange={(v) => setTweak('lang', v)}
          />
        </TweakSection>
        <TweakSection title="Customer Insights">
          <TweakToggle
            label="Privacy mode (mask names)"
            value={!!tw.privacyMode}
            onChange={(v) => setTweak('privacyMode', v)}
          />
          <TweakToggle
            label="Dedup: clean (no duplicates)"
            value={!!tw.dedupClean}
            onChange={(v) => setTweak('dedupClean', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </TTProvider>
  );
};

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