<script>
  import { goto, invalidateAll } from '$app/navigation';
  import { page } from '$app/stores';
  import { makeSlug } from '$lib/shared/slugify.js';

  export let data;

  let deleting = {};
  let dismissing = {};
  let markingRead = {};
  let adminSearch = data.adminQ;
  let searchTimer;

  // Edit state
  let editingId = null;      // which personality is open for editing
  let editForm = {};         // form field values
  let editSaving = false;
  let editError = '';

  // Replace binary state
  let replaceId = null;
  let replacePreview = null; // { current, incoming }
  let replaceBytes = null;
  let replaceSaving = false;
  let replaceError = '';
  let replaceInput;          // file input ref

  function startEdit(p) {
    editingId = p.id;
    editError = '';
    editForm = {
      name:           p.name,
      prs_name:       p.prs_name ?? '',
      manufacturer:   p.manufacturer ?? '',
      notes:          p.notes ?? '',
      tags:           JSON.parse(p.tags ?? '[]').join(', '),
      creator_handle: p.creator_handle ?? ''
    };
  }

  function cancelEdit() {
    editingId = null;
    editError = '';
    replacePreview = null;
    replaceBytes = null;
    replaceError = '';
  }

  async function saveEdit() {
    editSaving = true;
    editError = '';
    try {
      const res = await fetch('/api/admin/edit-personality', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          id:             editingId,
          name:           editForm.name,
          prs_name:       editForm.prs_name,
          manufacturer:   editForm.manufacturer,
          notes:          editForm.notes,
          tags:           editForm.tags.split(',').map(t => t.trim()).filter(Boolean),
          creator_handle: editForm.creator_handle
        })
      });
      if (!res.ok) {
        const b = await res.json().catch(() => ({}));
        throw new Error(b.message ?? `Error ${res.status}`);
      }
      await invalidateAll();
      cancelEdit();
    } catch (err) {
      editError = err.message;
    } finally {
      editSaving = false;
    }
  }

  async function handleReplaceFile(event) {
    const file = event.currentTarget.files?.[0];
    if (!file) return;
    replaceError = '';
    replacePreview = null;
    replaceBytes = null;
    event.currentTarget.value = '';

    try {
      const buf = await file.arrayBuffer();
      const data = Array.from(new Uint8Array(buf));

      // Preview first
      const res = await fetch('/api/admin/replace-binary', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id: replaceId, data, preview: true })
      });
      if (!res.ok) {
        const b = await res.json().catch(() => ({}));
        throw new Error(b.message ?? `Error ${res.status}`);
      }
      const result = await res.json();
      replacePreview = result;
      replaceBytes = data;
    } catch (err) {
      replaceError = err.message;
    }
  }

  async function confirmReplace() {
    replaceSaving = true;
    replaceError = '';
    try {
      const res = await fetch('/api/admin/replace-binary', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id: replaceId, data: replaceBytes, preview: false })
      });
      if (!res.ok) {
        const b = await res.json().catch(() => ({}));
        throw new Error(b.message ?? `Error ${res.status}`);
      }
      await invalidateAll();
      replacePreview = null;
      replaceBytes = null;
      replaceId = null;
    } catch (err) {
      replaceError = err.message;
    } finally {
      replaceSaving = false;
    }
  }

  function navigate(params) {
    const u = new URL($page.url);
    for (const [k, v] of Object.entries(params)) {
      if (v) u.searchParams.set(k, v);
      else u.searchParams.delete(k);
    }
    goto(u.toString(), { keepFocus: true });
  }

  function onAdminSearch() {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(() => navigate({ q: adminSearch, page: '1' }), 350);
  }

  async function markRead(id, all = false) {
    const key = all ? '__all__' : id;
    markingRead[key] = true;
    await fetch('/api/admin/mark-read', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(all ? { all: true } : { id })
    });
    await invalidateAll();
    markingRead[key] = false;
  }

  async function dismissReport(id) {
    dismissing[id] = true;
    await fetch('/api/admin/dismiss-report', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    await invalidateAll();
    dismissing[id] = false;
  }

  async function deletePersonality(id, fromReport = false) {
    const key = fromReport ? `r_${id}` : id;
    if (!confirm('Soft-delete this personality? It will be removed from the library and hard-deleted after 60 days.')) return;
    deleting[key] = true;
    await fetch('/api/admin/delete-personality', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id })
    });
    await invalidateAll();
    deleting[key] = false;
  }

  function formatDate(iso) {
    return new Date(iso).toLocaleDateString(undefined, { month:'short', day:'numeric', year:'numeric' });
  }

  function formatTime(iso) {
    return new Date(iso).toLocaleString();
  }

  const reasonLabels = {
    'incorrect-data':  'Incorrect data',
    'duplicate':       'Duplicate',
    'inappropriate':   'Inappropriate',
    'spam':            'Spam / test',
    'other':           'Other'
  };
</script>

<!-- Stats strip -->
<div style="display:grid; grid-template-columns:repeat(5,1fr); gap:1px;
            background:var(--border); border-radius:4px; overflow:hidden;
            margin-bottom:24px; border:1px solid var(--border);">
  {#each [
    { label:'Total Personalities', value: data.stats.total,          color:'var(--amber)' },
    { label:'Published Today',     value: data.stats.today,          color:'var(--green)' },
    { label:'Open Reports',        value: data.stats.openReports,    color: data.stats.openReports > 0    ? 'var(--red)' : 'var(--text2)' },
    { label:'Unread Messages',     value: data.stats.unreadMessages, color: data.stats.unreadMessages > 0 ? 'var(--cyan)' : 'var(--text2)' },
    { label:'Soft Deleted',        value: data.stats.deleted,        color:'var(--text3)' },
  ] as stat}
    <div style="background:var(--surface); padding:16px 20px;">
      <div class="label" style="margin-bottom:6px;">{stat.label}</div>
      <div style="font-family:'DM Mono',monospace; font-size:28px; font-weight:500;
                  color:{stat.color}; text-shadow:0 0 12px {stat.color}40; line-height:1;">
        {stat.value}
      </div>
    </div>
  {/each}
</div>

<!-- Messages section -->
<div class="panel" style="margin-bottom:24px; overflow:hidden;">
  <div style="padding:14px 18px; border-bottom:1px solid var(--border);
              display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;">
    <div style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:15px;
                letter-spacing:0.06em; text-transform:uppercase; color:var(--text);">
      Messages
      {#if data.stats.unreadMessages > 0}
        <span style="margin-left:8px; padding:2px 8px; border-radius:3px;
                     background:var(--cyan-dim); border:1px solid rgba(45,212,200,0.3);
                     color:var(--cyan); font-size:11px;">{data.stats.unreadMessages} unread</span>
      {/if}
    </div>
    <div style="display:flex; gap:6px; flex-wrap:wrap; align-items:center;">
      {#each [['unread','Unread'],['all','All']] as [val, label]}
        <button class="btn" style="padding:4px 10px; font-size:11px;
          {data.messageFilter === val ? 'background:var(--cyan-dim); border-color:var(--cyan); color:var(--cyan);' : ''}"
          type="button" on:click={() => navigate({ messages: val })}>
          {label}
        </button>
      {/each}
      {#if data.stats.unreadMessages > 0}
        <button class="btn" style="padding:4px 10px; font-size:11px;" type="button"
                disabled={!!markingRead['__all__']}
                on:click={() => markRead(null, true)}>
          {markingRead['__all__'] ? '…' : 'Mark all read'}
        </button>
      {/if}
    </div>
  </div>

  {#if data.messages.length === 0}
    <div style="padding:32px; text-align:center; font-family:'DM Mono',monospace;
                font-size:12px; color:var(--text3);">
      No messages in this view.
    </div>
  {:else}
    {#each data.messages as msg}
      <div style="padding:14px 18px; border-bottom:1px solid var(--border);
                  {msg.read ? 'opacity:0.55;' : ''}">
        <div style="display:flex; align-items:flex-start; justify-content:space-between;
                    gap:12px; flex-wrap:wrap;">
          <div style="min-width:0; flex:1;">
            <div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:4px;">
              {#if !msg.read}
                <span style="width:6px; height:6px; border-radius:50%;
                             background:var(--cyan); flex-shrink:0;
                             box-shadow:0 0 6px rgba(45,212,200,0.6);"></span>
              {/if}
              <span style="font-family:'Barlow Condensed',sans-serif; font-weight:700;
                           font-size:15px; letter-spacing:0.03em; color:var(--text);">
                {msg.subject}
              </span>
              <span style="font-family:'Barlow Condensed',sans-serif; font-size:12px;
                           color:var(--amber); font-weight:600;">
                {msg.name || 'Anonymous'}
              </span>
              {#if msg.email}
                <a href="/cdn-cgi/l/email-protection#205b4d53470e454d41494c5d" style="font-family:'DM Mono',monospace; font-size:11px; color:var(--cyan);
                          text-decoration:none;">
                  {msg.email}
                </a>
              {/if}
            </div>
            <div style="font-size:13px; color:var(--text2); line-height:1.6;
                        margin-bottom:6px; white-space:pre-wrap;">
              {msg.message}
            </div>
            <div style="font-family:'DM Mono',monospace; font-size:10px; color:var(--text3);">
              {formatTime(msg.created_at)}
            </div>
          </div>
          {#if !msg.read}
            <button class="btn" style="padding:5px 10px; font-size:12px; flex-shrink:0;"
                    type="button"
                    disabled={!!markingRead[msg.id]}
                    on:click={() => markRead(msg.id)}>
              {markingRead[msg.id] ? '…' : 'Mark read'}
            </button>
          {/if}
        </div>
      </div>
    {/each}
  {/if}
</div>

<!-- Reports section -->
<div class="panel" style="margin-bottom:24px; overflow:hidden;">
  <div style="padding:14px 18px; border-bottom:1px solid var(--border);
              display:flex; align-items:center; justify-content:space-between; gap:12px;">
    <div style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:15px;
                letter-spacing:0.06em; text-transform:uppercase; color:var(--text);">
      Reports
      {#if data.stats.openReports > 0}
        <span style="margin-left:8px; padding:2px 8px; border-radius:3px;
                     background:var(--red-dim); border:1px solid rgba(248,113,113,0.3);
                     color:var(--red); font-size:11px;">{data.stats.openReports} open</span>
      {/if}
    </div>
    <div style="display:flex; gap:4px;">
      {#each [['open','Open'],['dismissed','Dismissed'],['all','All']] as [val, label]}
        <button class="btn" style="padding:4px 10px; font-size:11px;
          {data.reportFilter === val ? 'background:var(--amber-dim); border-color:var(--amber); color:var(--amber);' : ''}"
          type="button" on:click={() => navigate({ reports: val })}>
          {label}
        </button>
      {/each}
    </div>
  </div>

  {#if data.reports.length === 0}
    <div style="padding:32px; text-align:center; font-family:'DM Mono',monospace;
                font-size:12px; color:var(--text3);">
      No reports in this view.
    </div>
  {:else}
    {#each data.reports as report}
      <div style="padding:14px 18px; border-bottom:1px solid var(--border);
                  {report.resolved > 0 ? 'opacity:0.5;' : ''}">
        <div style="display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-wrap:wrap;">
          <div style="min-width:0;">
            <div style="display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:4px;">
              <a href="/p/{report.personality_id}/{makeSlug(report.personality_name ?? '')}"
                 target="_blank"
                 style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:15px;
                        letter-spacing:0.03em; color:var(--text); text-decoration:none;">
                {report.personality_name ?? report.personality_id}
              </a>
              {#if report.manufacturer}
                <span style="font-size:12px; color:var(--text3);">{report.manufacturer}</span>
              {/if}
              {#if report.deleted_at}
                <span style="font-family:'Barlow Condensed',sans-serif; font-size:10px; font-weight:700;
                             padding:1px 5px; border-radius:2px; letter-spacing:0.08em;
                             background:var(--red-dim); border:1px solid rgba(248,113,113,0.3); color:var(--red);">
                  DELETED
                </span>
              {/if}
            </div>
            <div style="font-family:'DM Mono',monospace; font-size:11px; color:var(--amber); margin-bottom:3px;">
              {reasonLabels[report.reason] ?? report.reason}
            </div>
            {#if report.notes}
              <div style="font-size:12px; color:var(--text2); margin-bottom:3px;">"{report.notes}"</div>
            {/if}
            <div style="font-family:'DM Mono',monospace; font-size:10px; color:var(--text3);">
              Reported {formatTime(report.created_at)}
              {#if report.resolved === 1} · Dismissed
              {:else if report.resolved === 2} · Removed
              {/if}
            </div>
          </div>
          {#if report.resolved === 0}
            <div style="display:flex; gap:6px; flex-shrink:0;">
              <button class="btn" style="padding:5px 10px; font-size:12px;" type="button"
                      disabled={!!dismissing[report.id]}
                      on:click={() => dismissReport(report.id)}>
                {dismissing[report.id] ? '…' : 'Dismiss'}
              </button>
              {#if !report.deleted_at}
                <button class="btn btn-danger" style="padding:5px 10px; font-size:12px;" type="button"
                        disabled={!!deleting[`r_${report.personality_id}`]}
                        on:click={() => deletePersonality(report.personality_id, true)}>
                  {deleting[`r_${report.personality_id}`] ? '…' : 'Soft Delete'}
                </button>
              {/if}
            </div>
          {/if}
        </div>
      </div>
    {/each}
  {/if}
</div>

<!-- Personalities section -->
<div class="panel" style="overflow:hidden;">
  <div style="padding:14px 18px; border-bottom:1px solid var(--border);
              display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;">
    <div style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:15px;
                letter-spacing:0.06em; text-transform:uppercase; color:var(--text);">
      All Personalities
      <span style="font-weight:400; font-size:12px; color:var(--text3); margin-left:8px;">
        {data.totalPersonalities} total
      </span>
    </div>
    <input class="input" style="max-width:260px;"
           type="search" placeholder="Search…"
           bind:value={adminSearch}
           on:input={onAdminSearch} />
  </div>

  <div style="overflow-x:auto;">
    <table style="width:100%; border-collapse:collapse;">
      <thead>
        <tr style="background:var(--raised);">
          {#each ['Fixture','Manufacturer','Ch','By','Published','Status',''] as h}
            <th style="padding:9px 14px; text-align:left; font-family:'Barlow Condensed',sans-serif;
                       font-size:11px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase;
                       color:var(--text2); border-bottom:1px solid var(--border); white-space:nowrap;">
              {h}
            </th>
          {/each}
        </tr>
      </thead>
      <tbody>
        {#each data.personalities as p}
          <!-- Data row -->
          <tr style="border-bottom:{editingId === p.id ? 'none' : '1px solid var(--border)'};
                     {p.deleted_at ? 'opacity:0.45;' : ''}
                     background:{editingId === p.id ? 'var(--raised)' : ''};
                     transition:background 0.1s;"
              on:mouseenter={(e) => { if (editingId !== p.id) e.currentTarget.style.background='var(--raised)'; }}
              on:mouseleave={(e) => { if (editingId !== p.id) e.currentTarget.style.background=''; }}>
            <td style="padding:9px 14px;">
              <a href="/p/{p.id}/{makeSlug(p.name)}" target="_blank"
                 style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:14px;
                        letter-spacing:0.03em; color:var(--text); text-decoration:none;">
                {p.name}
              </a>
              {#if p.prs_name && p.prs_name !== p.name}
                <div style="font-family:'DM Mono',monospace; font-size:10px; color:var(--amber);">PRS: {p.prs_name}</div>
              {/if}
            </td>
            <td style="padding:9px 14px; font-size:12px; color:var(--text2);">{p.manufacturer || '—'}</td>
            <td style="padding:9px 14px; font-family:'DM Mono',monospace; font-size:13px; color:var(--amber);">{p.channel_count}</td>
            <td style="padding:9px 14px; font-size:12px; color:var(--text3);">{p.creator_handle || '—'}</td>
            <td style="padding:9px 14px; font-family:'DM Mono',monospace; font-size:11px; color:var(--text3); white-space:nowrap;">{formatDate(p.created_at)}</td>
            <td style="padding:9px 14px;">
              {#if p.deleted_at}
                <span style="font-family:'Barlow Condensed',sans-serif; font-size:10px; font-weight:700;
                             padding:1px 6px; border-radius:2px; letter-spacing:0.08em;
                             background:var(--red-dim); border:1px solid rgba(248,113,113,0.3); color:var(--red);">
                  Deleted {formatDate(p.deleted_at)}
                </span>
              {:else}
                <span style="font-family:'Barlow Condensed',sans-serif; font-size:10px; font-weight:700;
                             padding:1px 6px; border-radius:2px; letter-spacing:0.08em;
                             background:var(--green-dim); border:1px solid rgba(74,222,128,0.2); color:var(--green);">
                  Live
                </span>
              {/if}
            </td>
            <td style="padding:9px 10px; white-space:nowrap;">
              <div style="display:flex; gap:4px;">
                {#if !p.deleted_at}
                  {#if editingId === p.id}
                    <button class="btn" style="padding:4px 8px; font-size:11px; color:var(--text3);"
                            type="button" on:click={cancelEdit}>Cancel</button>
                  {:else}
                    <button class="btn" style="padding:4px 8px; font-size:11px;"
                            type="button" on:click={() => startEdit(p)}>Edit</button>
                    <button class="btn btn-danger" style="padding:4px 8px; font-size:11px;" type="button"
                            disabled={!!deleting[p.id]}
                            on:click={() => deletePersonality(p.id)}>
                      {deleting[p.id] ? '…' : 'Delete'}
                    </button>
                  {/if}
                {/if}
              </div>
            </td>
          </tr>

          <!-- Inline edit panel -->
          {#if editingId === p.id}
            <tr style="border-bottom:1px solid var(--border);">
              <td colspan="7" style="padding:0; background:var(--bg);">
                <div style="padding:16px 18px; border-top:1px solid var(--border2);">
                  <div style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:12px;
                              letter-spacing:0.1em; text-transform:uppercase; color:var(--amber);
                              margin-bottom:14px;">
                    Editing: {p.name}
                  </div>

                  <!-- Metadata fields -->
                  <div style="display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-bottom:12px;">
                    <div>
                      <label class="label" style="display:block; margin-bottom:5px;">Library Name</label>
                      <input class="input" type="text" maxlength="120" bind:value={editForm.name} />
                    </div>
                    <div>
                      <label class="label" style="display:block; margin-bottom:5px;">
                        PRS Name
                        <span style="font-family:'DM Mono',monospace; font-size:10px; font-weight:400;
                                     text-transform:none; color:var(--text3); margin-left:4px;">(12 char max)</span>
                      </label>
                      <input class="input" style="font-family:'DM Mono',monospace;"
                             type="text" maxlength="12" bind:value={editForm.prs_name} />
                    </div>
                    <div>
                      <label class="label" style="display:block; margin-bottom:5px;">Manufacturer</label>
                      <input class="input" type="text" maxlength="128" bind:value={editForm.manufacturer} />
                    </div>
                    <div>
                      <label class="label" style="display:block; margin-bottom:5px;">Creator Handle</label>
                      <input class="input" type="text" maxlength="64" bind:value={editForm.creator_handle} />
                    </div>
                    <div>
                      <label class="label" style="display:block; margin-bottom:5px;">
                        Tags
                        <span style="font-family:'DM Mono',monospace; font-size:10px; font-weight:400;
                                     text-transform:none; color:var(--text3); margin-left:4px;">(comma separated)</span>
                      </label>
                      <input class="input" type="text" bind:value={editForm.tags}
                             placeholder="e.g. verified, 16-bit, spot" />
                    </div>
                    <div>
                      <label class="label" style="display:block; margin-bottom:5px;">Notes</label>
                      <input class="input" type="text" maxlength="1000" bind:value={editForm.notes} />
                    </div>
                  </div>

                  <!-- Metadata actions -->
                  <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                    <button class="btn btn-primary" style="padding:6px 14px;" type="button"
                            disabled={editSaving} on:click={saveEdit}>
                      {editSaving ? 'Saving…' : 'Save Changes'}
                    </button>
                    <button class="btn" style="padding:6px 14px;" type="button" on:click={cancelEdit}>Cancel</button>
                    {#if editError}
                      <span style="font-size:12px; color:var(--red);">{editError}</span>
                    {/if}
                  </div>

                  <!-- Replace binary section -->
                  <div style="border-top:1px solid var(--border); padding-top:14px;">
                    <div style="font-family:'Barlow Condensed',sans-serif; font-weight:700; font-size:12px;
                                letter-spacing:0.1em; text-transform:uppercase; color:var(--text2);
                                margin-bottom:10px;">Replace Binary (.prs file)</div>

                    {#if replaceId !== p.id || !replacePreview}
                      <div style="display:flex; align-items:center; gap:8px;">
                        <button class="btn" style="padding:6px 12px; font-size:12px;" type="button"
                                on:click={() => { replaceId = p.id; replacePreview = null; replaceBytes = null; replaceError = ''; replaceInput?.click(); }}>
                          Choose .prs file…
                        </button>
                        <span style="font-size:12px; color:var(--text3);">
                          Current: {p.channel_count}ch · PRS name: {p.prs_name || '(none)'}
                        </span>
                      </div>
                    {/if}

                    <!-- Diff preview -->
                    {#if replaceId === p.id && replacePreview}
                      <div style="padding:12px 14px; border-radius:3px; border:1px solid var(--border2);
                                  background:var(--raised); margin-bottom:10px;">
                        <div style="font-family:'Barlow Condensed',sans-serif; font-size:12px; font-weight:700;
                                    letter-spacing:0.08em; text-transform:uppercase; color:var(--text2); margin-bottom:8px;">
                          Change Summary
                        </div>
                        <div style="display:grid; grid-template-columns:auto 1fr 1fr; gap:6px 16px; font-size:12px; align-items:center;">
                          <span style="color:var(--text3); font-family:'Barlow Condensed',sans-serif; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;">Field</span>
                          <span style="color:var(--text3); font-family:'Barlow Condensed',sans-serif; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;">Current</span>
                          <span style="color:var(--text3); font-family:'Barlow Condensed',sans-serif; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;">Incoming</span>

                          <span style="color:var(--text2);">PRS Name</span>
                          <span style="font-family:'DM Mono',monospace; color:var(--text);">{replacePreview.current.prs_name || '—'}</span>
                          <span style="font-family:'DM Mono',monospace;
                                       color:{replacePreview.incoming.prs_name !== replacePreview.current.prs_name ? 'var(--amber)' : 'var(--text)'};">
                            {replacePreview.incoming.prs_name || '—'}
                            {#if replacePreview.incoming.prs_name !== replacePreview.current.prs_name}
                              <span style="color:var(--amber); margin-left:4px;">← changed</span>
                            {/if}
                          </span>

                          <span style="color:var(--text2);">Channels</span>
                          <span style="font-family:'DM Mono',monospace; color:var(--text);">{replacePreview.current.channel_count}</span>
                          <span style="font-family:'DM Mono',monospace;
                                       color:{replacePreview.incoming.channel_count !== replacePreview.current.channel_count ? 'var(--amber)' : 'var(--text)'};">
                            {replacePreview.incoming.channel_count}
                            {#if replacePreview.incoming.channel_count !== replacePreview.current.channel_count}
                              <span style="color:var(--amber); margin-left:4px;">← changed</span>
                            {/if}
                          </span>
                        </div>
                      </div>

                      <div style="display:flex; align-items:center; gap:8px;">
                        <button class="btn btn-primary" style="padding:6px 14px; font-size:12px;" type="button"
                                disabled={replaceSaving} on:click={confirmReplace}>
                          {replaceSaving ? 'Replacing…' : 'Confirm Replace'}
                        </button>
                        <button class="btn" style="padding:6px 12px; font-size:12px;" type="button"
                                on:click={() => { replacePreview = null; replaceBytes = null; replaceId = null; }}>
                          Cancel
                        </button>
                        <button class="btn" style="padding:6px 12px; font-size:12px;" type="button"
                                on:click={() => { replacePreview = null; replaceBytes = null; replaceInput?.click(); }}>
                          Choose different file
                        </button>
                        {#if replaceError}
                          <span style="font-size:12px; color:var(--red);">{replaceError}</span>
                        {/if}
                      </div>
                    {/if}

                    {#if replaceError && !replacePreview}
                      <div style="margin-top:8px; font-size:12px; color:var(--red);">{replaceError}</div>
                    {/if}
                  </div>
                </div>
              </td>
            </tr>
          {/if}
        {/each}
      </tbody>
    </table>
  </div>

  <!-- Hidden file input for binary replacement -->
  <input bind:this={replaceInput} type="file" accept=".prs,application/octet-stream"
         style="display:none;" on:change={handleReplaceFile} />

  <!-- Pagination -->
  {#if data.totalPages > 1}
    <div style="padding:12px 18px; border-top:1px solid var(--border);
                display:flex; align-items:center; gap:6px; justify-content:flex-end;">
      {#each Array.from({length: data.totalPages}, (_, i) => i+1) as p}
        <button class="btn" style="padding:4px 10px; font-family:'DM Mono',monospace; font-size:12px;
          {p === data.adminPage ? 'background:var(--amber-dim); border-color:var(--amber); color:var(--amber);' : ''}"
          type="button" on:click={() => navigate({ page: String(p) })}>
          {p}
        </button>
      {/each}
    </div>
