(function(){
  const doc = document;
  const monthNames=['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'];
  const qs = (s,r=doc)=>r.querySelector(s);
  const qsa = (s,r=doc)=>Array.from(r.querySelectorAll(s));

  function reindexCollection(form){
    qsa('.collection-item[data-repeatable-item]', form).forEach((item,index)=>{
      qsa('input, textarea, select', item).forEach(field=>{
        if(!field.name) return;
        field.name = field.name.replace(/items\[\d+\]/, `items[${index}]`);
        field.name = field.name.replace(/house_main_upload\[\d+\]/, `house_main_upload[${index}]`);
        field.name = field.name.replace(/gallery_image_upload\[\d+\]/, `gallery_image_upload[${index}]`);
        field.name = field.name.replace(/house_gallery_upload_\d+\[\]/, `house_gallery_upload_${index}[]`);
        field.name = field.name.replace(/review_avatar_upload\[\d+\]/, `review_avatar_upload[${index}]`);
        field.name = field.name.replace(/review_photos_upload_\d+\[\]/, `review_photos_upload_${index}[]`);
        field.name = field.name.replace(/faq_image_upload\[\d+\]/, `faq_image_upload[${index}]`);
      });
    });
  }

  function refreshCollectionTitles(form){
    qsa('.collection-item[data-repeatable-item]', form).forEach(item=>{
      const src = qs('[data-title-source]', item);
      const altInput = qs('input[name$="[alt]"]', item);
      const title = qs('[data-item-title]', item);
      const titleValue = (altInput && altInput.value.trim()) || (src && src.value.trim()) || 'Новый элемент';
      if(title) title.textContent = titleValue;
      let previewWrap = qs('.admin-image-preview', item);
      const imageInput = qs('[data-image-input]', item);
      const value = imageInput ? imageInput.value.trim() : '';
      if(value){
        if(!previewWrap){
          previewWrap = doc.createElement('div');
          previewWrap.className = 'admin-image-preview';
          item.insertBefore(previewWrap, item.children[Math.min(3, item.children.length)]);
        }
        previewWrap.innerHTML = `<img src="${value}" alt="">`;
      } else if (previewWrap){
        previewWrap.remove();
      }
    });
  }

  function bindCollectionForm(){
    const form = qs('[data-collection-form]');
    if(!form) return;
    const collectionName = form.dataset.collectionName || 'houses';
    const defaults = {
      houses: {title:'Новый домик', price:'', weekend_price:'', holiday_price:'', meta:'', capacity:'', area:'', description:'', full_description:'', image:'', view:'', features:'', gallery:''},
      rates: {house:'Новый тариф', season:'Базовый', min_nights:'1', weekday_price:'', weekend_price:'', holiday_price:'', notes:''},
      faq: {question:'Новый вопрос', answer:''},
      reviews: {name:'Новый отзыв', location:'', date:'', photo:'', rating:'5', photos:'', text:''},
      gallery: {src:'', alt:'Новое фото', caption:''}
    };

    function field(index,name,label,type='input', extra=''){
      const value = (defaults[collectionName] || {})[name] || '';
      if(type === 'textarea') return `<label><span>${label}</span><textarea ${extra} name="items[${index}][${name}]">${value}</textarea></label>`;
      return `<label><span>${label}</span><input ${extra} name="items[${index}][${name}]" value="${value}"></label>`;
    }
    function template(index){
      if(collectionName === 'houses') return `<section class="collection-item grid" data-repeatable-item data-item-type="houses"><div class="collection-item__head"><div><strong data-item-title>Новый домик</strong><div class="muted">Карточка домика, описание, главное фото и галерея.</div></div><button class="button button--ghost button--small" type="button" data-remove-item>Удалить</button></div><div class="grid grid-2"><label><span>Название</span><input data-title-source name="items[${index}][title]" value="Новый домик"></label><label><span>Цена будни / базовая</span><input name="items[${index}][price]" value=""></label></div><div class="grid grid-3"><label><span>Короткое meta</span><input name="items[${index}][meta]" value=""></label><label><span>Вместимость</span><input name="items[${index}][capacity]" value=""></label><label><span>Площадь / формат</span><input name="items[${index}][area]" value=""></label></div><div class="grid grid-2"><label><span>Цена выходные</span><input name="items[${index}][weekend_price]" value=""></label><label><span>Цена праздники</span><input name="items[${index}][holiday_price]" value=""></label></div><div class="grid grid-2"><label><span>Краткое описание</span><textarea name="items[${index}][description]"></textarea></label><label><span>Подробное описание</span><textarea name="items[${index}][full_description]"></textarea></label></div><div class="grid grid-2"><label><span>Главное изображение (URL)</span><input data-image-input name="items[${index}][image]" value=""></label><label><span>Загрузить главное изображение</span><input type="file" name="house_main_upload[${index}]" accept=".jpg,.jpeg,.png,.webp,.gif"></label></div><div class="grid grid-2"><label><span>Особенность / вид</span><input name="items[${index}][view]" value=""></label><label><span>Фишки</span><textarea name="items[${index}][features]"></textarea></label></div><div class="grid grid-2"><label><span>Галерея</span><textarea name="items[${index}][gallery]"></textarea></label><label><span>Добавить фото в галерею</span><input type="file" name="house_gallery_upload_${index}[]" multiple accept=".jpg,.jpeg,.png,.webp,.gif"></label></div></section>`;
      if(collectionName === 'rates') return `<section class="collection-item grid" data-repeatable-item data-item-type="rates"><div class="collection-item__head"><div><strong data-item-title>Новый тариф</strong><div class="muted">Тарифная строка для домика.</div></div><button class="button button--ghost button--small" type="button" data-remove-item>Удалить</button></div><div class="grid grid-3"><label><span>Домик</span><input data-title-source name="items[${index}][house]" value="Новый тариф"></label><label><span>Сезон / тариф</span><input name="items[${index}][season]" value="Базовый"></label><label><span>Мин. ночей</span><input name="items[${index}][min_nights]" value="1"></label></div><div class="grid grid-3"><label><span>Цена будни</span><input name="items[${index}][weekday_price]"></label><label><span>Цена выходные</span><input name="items[${index}][weekend_price]"></label><label><span>Цена праздники</span><input name="items[${index}][holiday_price]"></label></div><label><span>Примечание</span><textarea name="items[${index}][notes]"></textarea></label></section>`;
      if(collectionName === 'faq') return `<section class="collection-item grid" data-repeatable-item data-item-type="faq"><div class="collection-item__head"><div><strong data-item-title>Новый вопрос</strong><div class="muted">Вопрос и ответ для FAQ.</div></div><div class="collection-item__tools"><button class="button button--ghost button--small button--icon" type="button" data-move-up title="Поднять выше">↑</button><button class="button button--ghost button--small button--icon" type="button" data-move-down title="Опустить ниже">↓</button><button class="button button--ghost button--small" type="button" data-remove-item>Удалить</button></div></div><div class="grid grid-2"><label><span>Вопрос</span><input data-title-source name="items[${index}][question]" value="Новый вопрос"></label><label><span>URL изображения к ответу</span><input data-image-input name="items[${index}][image]"></label></div><div class="grid grid-2"><label><span>Загрузить изображение</span><input type="file" name="faq_image_upload[${index}]" accept=".jpg,.jpeg,.png,.webp,.gif"></label><div class="admin-image-preview"></div></div><label><span>Ответ</span><textarea name="items[${index}][answer]" rows="5"></textarea></label></section>`;
      if(collectionName === 'reviews') return `<section class="collection-item grid review-editor" data-repeatable-item data-item-type="reviews"><div class="collection-item__head"><div><strong data-item-title>Новый отзыв</strong><div class="muted">Фото гостя, рейтинг, текст и дополнительные фото.</div></div><button class="button button--ghost button--small" type="button" data-remove-item>Удалить</button></div><div class="grid grid-3"><label><span>Имя гостя</span><input data-title-source name="items[${index}][name]" value="Новый отзыв"></label><label><span>Локация / подпись</span><input name="items[${index}][location]"></label><label><span>Дата / сезон</span><input name="items[${index}][date]"></label></div><div class="grid grid-3"><label><span>Фото гостя (URL)</span><input data-image-input name="items[${index}][photo]"></label><label><span>Загрузить фото гостя</span><input type="file" name="review_avatar_upload[${index}]" accept=".jpg,.jpeg,.png,.webp,.gif"></label><label><span>Рейтинг</span><input name="items[${index}][rating]" value="5"></label></div><div class="grid grid-2"><label><span>Доп. фото</span><textarea name="items[${index}][photos]"></textarea></label><label><span>Добавить доп. фото</span><input type="file" name="review_photos_upload_${index}[]" multiple accept=".jpg,.jpeg,.png,.webp,.gif"></label></div><label><span>Текст отзыва</span><textarea name="items[${index}][text]"></textarea></label></section>`;
      return `<section class="collection-item grid gallery-item" data-repeatable-item data-item-type="gallery"><div class="collection-item__head"><div><strong data-item-title>Новое фото</strong><div class="muted">Слайд фотогалереи на сайте. Меняй порядок стрелками ↑ ↓.</div></div><div class="collection-item__tools"><button class="button button--ghost button--small button--icon" type="button" data-move-up title="Поднять выше">↑</button><button class="button button--ghost button--small button--icon" type="button" data-move-down title="Опустить ниже">↓</button><button class="button button--ghost button--small" type="button" data-remove-item>Удалить</button></div></div><div class="gallery-order"><div class="admin-image-preview"></div><div class="gallery-fields"><div class="grid grid-2"><label><span>URL фото</span><input data-image-input data-title-source name="items[${index}][src]"></label><label><span>Загрузить фото</span><input type="file" name="gallery_image_upload[${index}]" accept=".jpg,.jpeg,.png,.webp,.gif"></label></div><div class="grid grid-2"><label><span>Alt / название</span><input name="items[${index}][alt]" value="Новое фото"></label><label><span>Краткая подпись</span><input name="items[${index}][caption]"></label></div></div></div></section>`;
    }

    form.addEventListener('click', (e)=>{
      const removeBtn = e.target.closest('[data-remove-item]');
      const moveUpBtn = e.target.closest('[data-move-up]');
      if(moveUpBtn){
        e.preventDefault();
        const item = moveUpBtn.closest('[data-repeatable-item]');
        if(item && item.previousElementSibling && item.previousElementSibling.matches('[data-repeatable-item]')){
          item.parentNode.insertBefore(item, item.previousElementSibling);
          reindexCollection(form);
          refreshCollectionTitles(form);
        }
        return;
      }
      const moveDownBtn = e.target.closest('[data-move-down]');
      if(moveDownBtn){
        e.preventDefault();
        const item = moveDownBtn.closest('[data-repeatable-item]');
        if(item){
          let next = item.nextElementSibling;
          while(next && !next.matches('[data-repeatable-item]')) next = next.nextElementSibling;
          if(next) next.after(item);
          reindexCollection(form);
          refreshCollectionTitles(form);
        }
        return;
      }
      if(removeBtn){
        e.preventDefault();
        const item = removeBtn.closest('[data-repeatable-item]');
        if(!item) return;
        const count = qsa('.collection-item[data-repeatable-item]', form).length;
        if(count <= 1){
          qsa('input, textarea, select', item).forEach(field=>{ field.value=''; if(field.name.endsWith('[rating]')) field.value='5'; });
        } else {
          item.remove();
        }
        reindexCollection(form);
        refreshCollectionTitles(form);
        return;
      }
      if(e.target.closest('[data-add-item]')){
        e.preventDefault();
        const index = qsa('.collection-item[data-repeatable-item]', form).length;
        const wrap = doc.createElement('div');
        wrap.innerHTML = template(index);
        const node = wrap.firstElementChild;
        const submitBar = form.lastElementChild;
        form.insertBefore(node, submitBar);
        reindexCollection(form);
        refreshCollectionTitles(form);
        node.scrollIntoView({behavior:'smooth', block:'center'});
      }
    });

    form.addEventListener('input', (e)=>{
      if(e.target.matches('[data-title-source], [data-image-input]')) refreshCollectionTitles(form);
    });

    refreshCollectionTitles(form);
  }

  function bindSortables(){
    const sortables=doc.querySelectorAll('[data-sortable]');
    sortables.forEach(container=>{
      let dragged=null;
      container.querySelectorAll('[data-sort-item]').forEach(item=>{
        item.draggable=true;
        item.addEventListener('dragstart',()=>{dragged=item; item.classList.add('is-dragging');});
        item.addEventListener('dragend',()=>{item.classList.remove('is-dragging'); dragged=null; syncOrder(container);});
        item.addEventListener('dragover',e=>{
          e.preventDefault();
          if(!dragged || dragged===item) return;
          const rect=item.getBoundingClientRect();
          const after=(e.clientY-rect.top) > rect.height/2;
          container.insertBefore(dragged, after ? item.nextSibling : item);
        });
      });
    });
    function syncOrder(container){
      const output=document.querySelector(container.dataset.output);
      if(!output) return;
      output.value=[...container.querySelectorAll('[data-sort-item]')].map(el=>el.dataset.id).join(',');
    }
  }

  function bindAvailability(){
    const root=doc.querySelector('[data-calendar-admin]');
    if(!root) return;
    const payloadField=doc.querySelector('#availability_payload');
    let state={global:[], houses:{}};
    let houses={};
    const availabilityNode = doc.querySelector('#admin-availability-data');
    const housesNode = doc.querySelector('#admin-houses-data');
    try{ state=JSON.parse((availabilityNode && availabilityNode.textContent) || '{}') || state; }catch(e){ console.error(e); }
    try{ houses=JSON.parse((housesNode && housesNode.textContent) || '{}') || {}; }catch(e){ console.error(e); }
    if(!Array.isArray(state.global)) state.global=[];
    if(!state.houses || typeof state.houses !== 'object') state.houses={};
    let currentTarget='global';
    let currentMonth=new Date(new Date().getFullYear(), new Date().getMonth(), 1);
    function toYmd(date){ return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,'0')}-${String(date.getDate()).padStart(2,'0')}`; }
    function getSet(target){ if(target==='global') return new Set(state.global || []); if(!Array.isArray(state.houses[target])) state.houses[target]=[]; return new Set(state.houses[target]); }
    function commit(target,set){ const arr=Array.from(set).filter(Boolean).sort(); if(target==='global') state.global=arr; else state.houses[target]=arr; if(payloadField) payloadField.value=JSON.stringify(state); }
    function render(){
      const set=getSet(currentTarget);
      const month=currentMonth.getMonth();
      const year=currentMonth.getFullYear();
      const first=new Date(year, month, 1);
      const startWeekday=(first.getDay()+6)%7;
      const daysInMonth=new Date(year, month+1, 0).getDate();
      let html = `<div class="calendar-target-title">Редактируется: <strong>${currentTarget==='global' ? 'Все домики' : (houses[currentTarget] || currentTarget)}</strong></div>`;
      html += `<div class="calendar-head"><button type="button" class="calendar-head__nav" data-admin-nav="prev" aria-label="Предыдущий месяц">‹</button><div class="calendar-head__title">${monthNames[month]} ${year}</div><button type="button" class="calendar-head__nav" data-admin-nav="next" aria-label="Следующий месяц">›</button></div>`;
      html += '<div class="calendar-month"><div class="calendar-weekdays"><span>Пн</span><span>Вт</span><span>Ср</span><span>Чт</span><span>Пт</span><span>Сб</span><span>Вс</span></div><div class="calendar-days">';
      for(let i=0;i<startWeekday;i++) html += '<span class="calendar-day calendar-day--empty"></span>';
      for(let d=1; d<=daysInMonth; d++){
        const dt=new Date(year, month, d); const key=toYmd(dt); const isClosed=set.has(key);
        html += `<button type="button" class="calendar-day ${isClosed?'is-closed':''}" data-admin-date="${key}">${d}</button>`;
      }
      html += `</div></div><div class="panel" style="margin-top:14px"><strong>Закрытые даты</strong><div style="margin-top:8px;color:#666;line-height:1.65">${Array.from(set).sort().join(', ') || 'нет закрытых дат'}</div></div>`;
      root.innerHTML=html;
      qsa('[data-calendar-target]').forEach(btn=>btn.classList.toggle('is-active', btn.dataset.calendarTarget===currentTarget));
      if(payloadField) payloadField.value=JSON.stringify(state);
    }
    root.addEventListener('click', (e)=>{
      const nav=e.target.closest('[data-admin-nav]');
      if(nav){ e.preventDefault(); currentMonth = new Date(currentMonth.getFullYear(), currentMonth.getMonth() + (nav.dataset.adminNav==='next' ? 1 : -1), 1); render(); return; }
      const day=e.target.closest('[data-admin-date]');
      if(day){ e.preventDefault(); const key=day.dataset.adminDate; const currentSet=getSet(currentTarget); if(currentSet.has(key)) currentSet.delete(key); else currentSet.add(key); commit(currentTarget,currentSet); render(); }
    });
    qsa('[data-calendar-target]').forEach(btn=>btn.addEventListener('click',()=>{ currentTarget=btn.dataset.calendarTarget || 'global'; render(); }));
    if(payloadField) payloadField.value=JSON.stringify(state);
    render();
  }

  function bindGallerySortables(){
    qsa('[data-sortable-gallery]').forEach(container=>{
      let dragged=null;
      qsa('[data-sort-item]', container).forEach(item=>{
        item.draggable=true;
        item.addEventListener('dragstart', ()=>{ dragged=item; item.classList.add('is-dragging'); });
        item.addEventListener('dragend', ()=>{ item.classList.remove('is-dragging'); dragged=null; });
        item.addEventListener('dragover', (e)=>{
          e.preventDefault();
          if(!dragged || dragged===item) return;
          const rect=item.getBoundingClientRect();
          const after=(e.clientX-rect.left) > rect.width/2;
          container.insertBefore(dragged, after ? item.nextSibling : item);
        });
      });
    });
  }

  bindSortables();
  bindCollectionForm();
  bindAvailability();
  bindGallerySortables();
})();

(function(){
  function setCollapsedState(panel, collapsed, bodySelector){
    const body = panel && panel.querySelector(bodySelector || '.accordion-panel__body, [data-card-body]');
    const btn = panel && panel.querySelector('[data-panel-toggle], [data-card-toggle]');
    if(!panel || !body || !btn) return;
    if(bodySelector === '[data-card-body]'){
      body.classList.toggle('is-collapsed', collapsed);
    } else {
      panel.classList.toggle('is-collapsed', collapsed);
      panel.classList.toggle('is-open', !collapsed);
    }
    btn.textContent = collapsed ? 'Развернуть' : 'Свернуть';
  }

  document.addEventListener('click', function(e){
    const panelBtn = e.target.closest('[data-panel-toggle]');
    if(panelBtn){
      e.preventDefault();
      const panel = panelBtn.closest('[data-collapse-panel]');
      if(!panel || panel.closest('[data-native-collapse-root]')) return;
      const collapsed = !panel.classList.contains('is-collapsed');
      setCollapsedState(panel, collapsed, '.accordion-panel__body');
      if(!collapsed && panel.matches('[data-session-card]')){
        const target = panel.querySelector('[data-session-actions]');
        const key = panel.getAttribute('data-session-key') || '';
        if(target && key && !target.dataset.loaded){ loadDetail(key, target); }
      }
      return;
    }
    const cardBtn = e.target.closest('[data-card-toggle]');
    if(cardBtn){
      e.preventDefault();
      const card = cardBtn.closest('[data-collapsible-card]');
      if(card && card.closest('[data-native-collapse-root]')) return;
      const body = card && card.querySelector('[data-card-body]');
      if(!card || !body) return;
      const collapsed = !body.classList.contains('is-collapsed');
      setCollapsedState(card, collapsed, '[data-card-body]');
      return;
    }
    const pagerBtn = e.target.closest('[data-activity-page]');
    if(pagerBtn && window.__activityController){
      e.preventDefault();
      const type = pagerBtn.getAttribute('data-activity-type') || 'recent';
      const page = parseInt(pagerBtn.getAttribute('data-activity-page') || '1', 10) || 1;
      window.__activityController.setPage(type, page);
    }
  });

  const refreshBtn=document.querySelector('[data-refresh-activity]');
  const auto=document.querySelector('[data-autorefresh-activity]');
  const onlineTable=document.querySelector('[data-online-table]');
  const recentTable=document.querySelector('[data-recent-table]');
  const daysBars=document.querySelector('[data-days-bars]');
  const hoursBars=document.querySelector('[data-hours-bars]');
  const sessionsList=document.querySelector('[data-sessions-list]');
  const recentPagination=document.querySelector('[data-recent-pagination]');
  const sessionsPagination=document.querySelector('[data-sessions-pagination]');
  if(!refreshBtn || !window.ACTIVITY_URL) return;

  const state = { recentPage: 1, sessionsPage: 1 };
  window.__activityController = {
    setPage(type, page){
      if(type === 'sessions') state.sessionsPage = page;
      else state.recentPage = page;
      loadActivity();
    }
  };

  function esc(v){ return String(v == null ? '' : v).replace(/[&<>"']/g, function(s){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[s]); }); }
  function formatTime(ts){ return new Date((ts||0)*1000).toLocaleString('ru-RU'); }
  function shorten(value, max){
    const s = String(value == null ? '' : value);
    return s.length > max ? s.slice(0, max - 1) + '…' : s;
  }
  function renderBars(node, map, mode){
    if(!node) return;
    const entries = Array.isArray(map) ? map.map((v,i)=>[String(i).padStart(2,'0')+':00',v]) : Object.entries(map||{}).slice(-14);
    const max = Math.max(1, ...entries.map(function(entry){ return Number(entry[1]||0); }));
    node.innerHTML = entries.map(function(entry){ var label=entry[0], value=Number(entry[1]||0), width=Math.max(4, Math.round((value/max)*100)); return '<div class="activity-bar"><span>'+esc(label)+'</span><div><i style="width:'+width+'%"></i></div><strong>'+value+'</strong></div>'; }).join('') || '<div class="muted">Нет данных</div>';
  }
  function renderPager(node, meta, type){
    if(!node || !meta) return;
    const page = Number(meta.page || 1);
    const pages = Number(meta.pages || 1);
    if(pages <= 1){ node.innerHTML=''; return; }
    let html = '<div class="activity-pagination__inner">';
    html += '<button type="button" class="button button--ghost button--sm" data-activity-type="'+type+'" data-activity-page="'+Math.max(1, page-1)+'" '+(page<=1?'disabled':'')+'>←</button>';
    for(let p=Math.max(1,page-2); p<=Math.min(pages,page+2); p++){
      html += '<button type="button" class="button button--sm '+(p===page?'':'button--ghost')+'" data-activity-type="'+type+'" data-activity-page="'+p+'">'+p+'</button>';
    }
    html += '<button type="button" class="button button--ghost button--sm" data-activity-type="'+type+'" data-activity-page="'+Math.min(pages, page+1)+'" '+(page>=pages?'disabled':'')+'>→</button>';
    html += '<span class="muted">Страница '+page+' из '+pages+'</span></div>';
    node.innerHTML = html;
  }
  async function loadDetail(sessionKey, target){
    if(!target || target.dataset.loading === '1') return;
    target.dataset.loading = '1';
    try{
      const res = await fetch(window.ACTIVITY_DETAIL_URL + encodeURIComponent(sessionKey), {cache:'no-store'});
      const data = await res.json();
      if(!data.ok) return;
      target.innerHTML = (data.actions||[]).map(function(item){
        return '<tr><td>'+esc(formatTime(item.time))+'</td><td>'+esc(item.action||'—')+'</td><td>'+esc(item.page||'—')+'</td><td title="'+esc(item.details||'—')+'">'+esc(shorten(item.details||'—', 120))+'</td></tr>';
      }).join('') || '<tr><td colspan="4">Нет действий</td></tr>';
      target.dataset.loaded = '1';
    }catch(e){
      console.error(e);
      target.innerHTML = '<tr><td colspan="4">Не удалось загрузить действия</td></tr>';
    } finally {
      target.dataset.loading = '0';
    }
  }
  function sessionCard(item, idx){
    const sid = 'sess_'+idx;
    return '<article class="activity-session accordion-panel is-collapsed" data-collapse-panel data-session-card data-session-key="'+esc(item.key||'')+'">'
      + '<div class="activity-session__head accordion-panel__head">'
      + '<div><h4>'+esc(item.ip||'—')+' · '+esc(item.country||'—')+'</h4><p class="muted">Источник: '+esc(item.referrer_host||'—')+' · UTM: '+esc(item.utm_source||'—')+'/'+esc(item.utm_medium||'—')+' · Страница: '+esc(item.current_page||'—')+'</p></div>'
      + '<button class="button button--ghost button--sm" type="button" data-panel-toggle>Развернуть</button></div>'
      + '<div class="accordion-panel__body"><div class="activity-session__meta">'
      + '<span><strong>Landing:</strong> '+esc(shorten(item.landing_url||'—', 90))+'</span>'
      + '<span><strong>Текущий URL:</strong> '+esc(shorten(item.current_url||'—', 90))+'</span>'
      + '<span><strong>Последнее действие:</strong> '+esc(item.last_action||'—')+'</span>'
      + '<span><strong>Hits:</strong> '+esc(item.hits||0)+'</span>'
      + '<span><strong>Последняя активность:</strong> '+esc(formatTime(item.last_seen||0))+'</span>'
      + '<span><strong>Referrer:</strong> '+esc(shorten(item.referrer||'—', 90))+'</span>'
      + '<span><strong>User-Agent:</strong> '+esc(shorten(item.user_agent||'—', 120))+'</span>'
      + '</div><div class="table-wrap"><table class="admin-table"><thead><tr><th>Время</th><th>Действие</th><th>Страница</th><th>Детали</th></tr></thead><tbody id="'+sid+'" data-session-actions><tr><td colspan="4">Открой карточку, чтобы загрузить действия</td></tr></tbody></table></div></div></article>';
  }
  async function loadActivity(){
    try{
      const url = window.ACTIVITY_URL + '&recent_page=' + state.recentPage + '&sessions_page=' + state.sessionsPage;
      const res=await fetch(url,{cache:'no-store'});
      const data=await res.json();
      if(!data.ok) return;
      const oc=document.querySelector('[data-online-count]');
      const ac=document.querySelector('[data-actions-count]');
      const dc=document.querySelector('[data-days-count]');
      const sc=document.querySelector('[data-sessions-count]');
      if(oc) oc.textContent=String(data.online_count || 0);
      if(ac) ac.textContent=String((data.recent_pagination && data.recent_pagination.total) || 0);
      if(dc) dc.textContent=String(Object.keys((data.summary||{}).days || {}).length);
      if(sc) sc.textContent=String((data.sessions_pagination && data.sessions_pagination.total) || 0);
      if(onlineTable){
        onlineTable.innerHTML=(data.online||[]).map(function(item){ return '<tr><td>'+esc(item.ip||'—')+'</td><td>'+esc(item.country||'—')+'</td><td title="'+esc(item.current_page||'—')+'">'+esc(shorten(item.current_page||'—', 48))+'</td><td>'+esc(item.referrer_host||item.utm_source||'—')+'</td><td>'+esc(item.hits||0)+'</td><td>'+esc(formatTime(item.last_seen||0))+'</td></tr>'; }).join('') || '<tr><td colspan="6">Сейчас никого нет онлайн</td></tr>';
      }
      if(recentTable){
        recentTable.innerHTML=(data.recent||[]).map(function(item){ return '<tr><td>'+esc(formatTime(item.time||0))+'</td><td>'+esc(item.ip||'—')+'</td><td>'+esc(item.country||'—')+'</td><td title="'+esc(item.page||'—')+'">'+esc(shorten(item.page||'—', 32))+'</td><td>'+esc(item.referrer_host||item.utm_source||'—')+'</td><td>'+esc(item.action||'—')+'</td><td title="'+esc(item.details||'—')+'">'+esc(shorten(item.details||'—', 90))+'</td></tr>'; }).join('') || '<tr><td colspan="7">Нет данных</td></tr>';
      }
      renderBars(daysBars, (data.summary||{}).days || {}, 'days');
      renderBars(hoursBars, (data.summary||{}).hours || [], 'hours');
      renderPager(recentPagination, data.recent_pagination, 'recent');
      renderPager(sessionsPagination, data.sessions_pagination, 'sessions');
      if(sessionsList){
        sessionsList.innerHTML=(data.sessions||[]).map(sessionCard).join('') || '<div class="muted">Нет сохранённых сессий</div>';
      }
    }catch(e){
      console.error(e);
      if(sessionsList) sessionsList.innerHTML='<div class="notice notice--error">Не удалось загрузить аналитику. Обнови страницу или попробуй ещё раз.</div>';
    }
  }
  refreshBtn.addEventListener('click', loadActivity);
  loadActivity();
  setInterval(function(){ if(!auto || auto.checked) loadActivity(); },10000);
})();
(function(){
  const form=document.querySelector('[data-header-preview-form]');
  if(!form) return;
  const preview=document.querySelector('[data-header-preview]');
  const brandInput=form.querySelector('[data-preview-brand]');
  const phoneInput=form.querySelector('[data-preview-phone]');
  const taglineInput=form.querySelector('[data-preview-tagline]');
  const ctaInput=form.querySelector('[data-preview-cta]');
  const layoutInput=form.querySelector('[data-preview-layout]');
  const themeInput=form.querySelector('[data-preview-theme]');
  const socialsInput=form.querySelector('[data-preview-socials]');
  const phoneToggle=form.querySelector('[data-preview-phone-toggle]');
  const taglineToggle=form.querySelector('[data-preview-tagline-toggle]');
  const brandText=document.querySelector('[data-preview-brand-text]');
  const phoneText=document.querySelector('[data-preview-phone-text]');
  const taglineText=document.querySelector('[data-preview-tagline-text]');
  const ctaText=document.querySelector('[data-preview-cta-text]');
  const socialWrap=document.querySelector('[data-preview-social-icons]');
  function sync(){
    if(brandText && brandInput) brandText.textContent=brandInput.value.trim() || 'feyaframe.com';
    if(phoneText && phoneInput) phoneText.textContent=phoneInput.value.trim() || '+7 (999) 999-99-99';
    if(taglineText && taglineInput) taglineText.textContent=taglineInput.value.trim() || 'Подпись бренда';
    if(ctaText && ctaInput) ctaText.textContent=ctaInput.value.trim() || 'Забронировать';
    if(preview && themeInput){
      preview.classList.remove('header-preview--glass','header-preview--light','header-preview--dark');
      preview.classList.add('header-preview--'+themeInput.value);
    }
    if(preview && layoutInput){
      preview.classList.toggle('header-preview--compact', layoutInput.value === 'compact');
    }
    if(phoneText && phoneToggle) phoneText.classList.toggle('is-hidden', !phoneToggle.checked);
    if(taglineText && taglineToggle) taglineText.classList.toggle('is-hidden', !taglineToggle.checked);
    if(socialWrap && socialsInput) socialWrap.classList.toggle('is-hidden', !['inline','both'].includes(socialsInput.value));
  }
  form.addEventListener('input', sync);
  form.addEventListener('change', sync);
  sync();
})();


(function(){
  const doc = document;
  function enableSortableMediaGrid(grid){
    if(!grid) return;
    let dragEl = null;
    grid.querySelectorAll('.admin-media-card').forEach(card=>{
      card.draggable = true;
      card.addEventListener('dragstart', ()=>{ dragEl = card; card.classList.add('is-dragging'); });
      card.addEventListener('dragend', ()=>{ card.classList.remove('is-dragging'); dragEl = null; });
      card.addEventListener('dragover', (e)=>{
        e.preventDefault();
        const target = card;
        if(!dragEl || target===dragEl) return;
        const rect = target.getBoundingClientRect();
        const before = (e.clientX - rect.left) < rect.width/2;
        if(before) target.parentNode.insertBefore(dragEl, target);
        else target.parentNode.insertBefore(dragEl, target.nextSibling);
      });
    });
  }
  document.querySelectorAll('.admin-media-grid--sortable').forEach(enableSortableMediaGrid);
})();

(function(){
  function flashButton(btn, text){
    if(!btn) return;
    const original = btn.dataset.originalLabel || btn.textContent;
    btn.dataset.originalLabel = original;
    btn.textContent = text;
    window.setTimeout(()=>{ btn.textContent = original; }, 1400);
  }

  document.addEventListener('click', async (e)=>{
    const btn = e.target.closest('[data-copy-text]');
    if(!btn) return;
    e.preventDefault();
    const value = btn.getAttribute('data-copy-text') || '';
    try{
      if(navigator.clipboard && navigator.clipboard.writeText){
        await navigator.clipboard.writeText(value);
      } else {
        const field = document.createElement('textarea');
        field.value = value;
        document.body.appendChild(field);
        field.select();
        document.execCommand('copy');
        field.remove();
      }
      flashButton(btn, 'Скопировано');
    }catch(err){
      flashButton(btn, 'Не удалось');
    }
  });
})();
