<script lang="ts">
  import { onMount } from 'svelte';
  import { page } from '$app/state';
  import ImmichPicker from '$lib/components/shared/ImmichPicker.svelte';

  interface InventoryItem {
    id: number;
    name: string;
    order: string;
    sku: string;
    serial: string;
    status: string;
    price: number;
    tax: number;
    total: number;
    qty: number;
    tracking: string;
    vendor: string;
    buyerName: string;
    date: string;
    notes: string;
    photos: number;
    photoUrls: string[];
  }

  interface ItemDetailRaw {
    Id: number;
    Item: string;
    'Order Number': string;
    'Serial Numbers': string;
    SKU: string;
    Received: string;
    'Price Per Item': number;
    Tax: number;
    Total: number;
    QTY: number;
    'Tracking Number': string;
    Source: string;
    Name: string;
    Date: string;
    Notes: string;
    photos: any[];
    [key: string]: any;
  }

  let activeTab = $state<'issues' | 'review' | 'all'>('issues');
  let searchQuery = $state('');
  let detailOpen = $state(false);
  let selectedItem = $state<InventoryItem | null>(null);
  let selectedDetail = $state<ItemDetailRaw | null>(null);
  let nocodbUrl = $state('');

  let recentItems = $state<InventoryItem[]>([]);
  let issueItems = $state<InventoryItem[]>([]);
  let reviewItems = $state<InventoryItem[]>([]);
  let recentLoaded = $state(false);
  let loading = $state(true);
  let searching = $state(false);
  let searchResults = $state<InventoryItem[] | null>(null);
  let saving = $state(false);
  let debounceTimer: ReturnType<typeof setTimeout>;

  const issueCount = $derived(issueItems.length);
  const reviewCount = $derived(reviewItems.length);
  const recentCount = $derived(recentItems.length);

  const displayedItems = $derived(() => {
    if (searchResults !== null) return searchResults;
    if (activeTab === 'issues') return issueItems;
    if (activeTab === 'review') return reviewItems;
    return recentItems;
  });
  const activeCount = $derived(displayedItems().length);

  function mapIssue(raw: any): InventoryItem {
    return {
      id: raw.id,
      name: raw.item || '',
      order: raw.orderNumber || '',
      sku: raw.sku || '',
      serial: raw.serialNumbers || '',
      status: normalizeStatus(raw.received || ''),
      price: 0,
      tax: 0,
      total: 0,
      qty: 1,
      tracking: raw.trackingNumber || '',
      vendor: '',
      buyerName: '',
      date: '',
      notes: raw.notes || '',
      photos: 0,
      photoUrls: []
    };
  }

  const NOCODB_BASE = 'https://noco.quadjourney.com';

  function extractPhotoUrls(photos: any[]): string[] {
    if (!Array.isArray(photos)) return [];
    return photos
      .filter((p: any) => p && p.signedPath)
      .map((p: any) => `${NOCODB_BASE}/${p.signedPath}`);
  }

  function mapDetail(raw: ItemDetailRaw): InventoryItem {
    const photoUrls = extractPhotoUrls(raw.photos);
    return {
      id: raw.Id,
      name: raw.Item || '',
      order: raw['Order Number'] || '',
      sku: raw.SKU || '',
      serial: raw['Serial Numbers'] || '',
      status: normalizeStatus(raw.Received || ''),
      price: raw['Price Per Item'] || 0,
      tax: raw.Tax || 0,
      total: raw.Total || 0,
      qty: raw.QTY || 1,
      tracking: raw['Tracking Number'] || '',
      vendor: raw.Source || '',
      buyerName: raw.Name || '',
      date: raw.Date || '',
      notes: raw.Notes || '',
      photos: Array.isArray(raw.photos) ? raw.photos.length : 0,
      photoUrls
    };
  }

  function normalizeStatus(received: string): string {
    if (!received) return 'Pending';
    const lower = received.toLowerCase();
    if (lower === 'issue' || lower === 'issues') return 'Issue';
    if (lower === 'needs review') return 'Needs Review';
    if (lower === 'pending') return 'Pending';
    if (lower === 'closed') return 'Closed';
    return 'Received';
  }

  async function loadSummary() {
    try {
      const res = await fetch('/api/inventory/summary', { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        issueItems = (data.issues || []).map(mapIssue);
        reviewItems = (data.needsReview || []).map(mapIssue);
      }
    } catch { /* silent */ }
  }

  function mapSearchResult(r: any): InventoryItem {
    return {
      id: r.id,
      name: r.item || '',
      order: '', sku: '', serial: '',
      status: normalizeStatus(r.received || ''),
      price: 0, tax: 0, total: 0, qty: 1,
      tracking: '', vendor: '', buyerName: '', date: '',
      notes: '', photos: 0, photoUrls: []
    };
  }

  async function loadRecent() {
    if (recentLoaded) return;
    try {
      const res = await fetch('/api/inventory/recent?limit=30', { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        recentItems = (data.items || []).map(mapSearchResult);
        recentLoaded = true;
      }
    } catch { /* silent */ }
  }

  async function searchItems(query: string) {
    if (!query.trim()) { searchResults = null; return; }
    searching = true;
    try {
      const res = await fetch(`/api/inventory/search-records?q=${encodeURIComponent(query)}`, { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        searchResults = (data.results || []).map((r: any) => ({
          id: r.id,
          name: r.item || '',
          order: '', sku: '', serial: '',
          status: normalizeStatus(r.received || ''),
          price: 0, tax: 0, total: 0, qty: 1,
          tracking: '', vendor: '', buyerName: '', date: '',
          notes: '', photos: 0, photoUrls: []
        }));
      }
    } catch { searchResults = []; }
    finally { searching = false; }
  }

  async function loadItemDetail(id: number) {
    try {
      const res = await fetch(`/api/inventory/item-details/${id}`, { credentials: 'include' });
      if (res.ok) {
        const data = await res.json();
        selectedDetail = data.item;
        selectedItem = mapDetail(data.item);
        activePhoto = 0;
        nocodbUrl = data.nocodb_url || '';
        detailOpen = true;
      }
    } catch { /* silent */ }
  }

  async function updateField(field: string, value: string | number) {
    if (!selectedItem) return;
    saving = true;
    try {
      const res = await fetch(`/api/inventory/item/${selectedItem.id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ [field]: value }),
        credentials: 'include'
      });
      if (res.ok && selectedDetail) {
        (selectedDetail as any)[field] = value;
        selectedItem = mapDetail(selectedDetail);
      }
    } catch { /* silent */ }
    finally { saving = false; }
  }

  function onSearchInput() {
    clearTimeout(debounceTimer);
    if (!searchQuery.trim()) { searchResults = null; return; }
    debounceTimer = setTimeout(() => searchItems(searchQuery), 300);
  }

  function openDetail(item: InventoryItem) {
    loadItemDetail(item.id);
  }

  async function refreshVisibleData() {
    await loadSummary();
    if (activeTab === 'all') {
      recentLoaded = false;
      await loadRecent();
    }
    if (searchQuery.trim()) {
      await searchItems(searchQuery);
    }
  }

  async function closeDetail() {
    await refreshVisibleData();
    detailOpen = false;
    selectedItem = null;
    selectedDetail = null;
    activePhoto = 0;
  }

  const statusOptions = ['Issue', 'Needs Review', 'Pending', 'Received', 'Closed'];

  function statusToReceived(status: string): string {
    if (status === 'Issue') return 'Issues';
    if (status === 'Needs Review') return 'Needs Review';
    if (status === 'Pending') return 'Pending';
    if (status === 'Closed') return 'Closed';
    return new Date().toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
  }

  async function changeStatus(newStatus: string) {
    if (!selectedItem) return;
    const receivedValue = statusToReceived(newStatus);
    await updateField('Received', receivedValue);
  }

  function statusColor(status: string) {
    if (status === 'Issue' || status === 'Issues') return 'error';
    if (status === 'Needs Review') return 'warning';
    if (status === 'Received') return 'success';
    if (status === 'Pending') return 'warning';
    if (status === 'Closed') return 'muted';
    return 'muted';
  }

  function formatPrice(n: number) {
    return '$' + n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  }

  let editingField = $state('');
  let editValue = $state('');

  const editableFields: Record<string, { nocoField: string; type: 'text' | 'number' }> = {
    'Item': { nocoField: 'Item', type: 'text' },
    'Price Per Item': { nocoField: 'Price Per Item', type: 'number' },
    'Tax': { nocoField: 'Tax', type: 'number' },
    'Total': { nocoField: 'Total', type: 'number' },
    'QTY': { nocoField: 'QTY', type: 'number' },
    'SKU': { nocoField: 'SKU', type: 'text' },
    'Serial Numbers': { nocoField: 'Serial Numbers', type: 'text' },
    'Order Number': { nocoField: 'Order Number', type: 'text' },
    'Source': { nocoField: 'Source', type: 'text' },
    'Name': { nocoField: 'Name', type: 'text' },
    'Date': { nocoField: 'Date', type: 'text' },
    'Tracking Number': { nocoField: 'Tracking Number', type: 'text' },
    'Notes': { nocoField: 'Notes', type: 'text' },
  };

  function startEdit(nocoField: string, currentValue: any) {
    editingField = nocoField;
    editValue = currentValue != null ? String(currentValue) : '';
  }

  async function saveEdit() {
    if (!editingField || !selectedItem) return;
    const field = editableFields[editingField];
    const value = field?.type === 'number' ? Number(editValue) || 0 : editValue;
    await updateField(editingField, value);
    editingField = '';
    editValue = '';
  }

  function handleEditKeydown(e: KeyboardEvent) {
    if (e.key === 'Enter') saveEdit();
    if (e.key === 'Escape') { editingField = ''; editValue = ''; }
  }

  function rawField(field: string): any {
    return selectedDetail ? (selectedDetail as any)[field] : '';
  }

  async function duplicateItem() {
    if (!selectedItem) return;
    saving = true;
    try {
      const res = await fetch(`/api/inventory/duplicate/${selectedItem.id}`, {
        method: 'POST', credentials: 'include'
      });
      if (res.ok) {
        const data = await res.json();
        const newId = data.newId || data.id;
        if (newId) loadItemDetail(newId);
      }
    } catch { /* silent */ }
    finally { saving = false; }
  }

  async function sendToPhone() {
    if (!selectedItem) return;
    saving = true;
    try {
      await fetch('/api/inventory/send-to-phone', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ rowId: selectedItem.id }),
        credentials: 'include'
      });
    } catch { /* silent */ }
    finally { saving = false; }
  }

  let fileInput: HTMLInputElement;
  let uploading = $state(false);
  let uploadMenuOpen = $state(false);
  let immichOpen = $state(false);
  let activePhoto = $state(0);

  function triggerUpload() {
    fileInput?.click();
  }

  async function handleFileSelect(e: Event) {
    const input = e.target as HTMLInputElement;
    if (!input.files?.length || !selectedItem) return;
    uploading = true;
    try {
      const formData = new FormData();
      formData.append('rowId', String(selectedItem.id));
      for (const file of input.files) formData.append('photos', file);
      const res = await fetch('/api/inventory/upload', {
        method: 'POST',
        body: formData,
        credentials: 'include'
      });
      if (res.ok) loadItemDetail(selectedItem.id);
    } catch { /* silent */ }
    finally {
      uploading = false;
      input.value = '';
    }
  }

  async function handleImmichSelect(assetIds: string[]) {
    if (!selectedItem || !assetIds.length) return;
    uploading = true;
    try {
      await fetch('/api/inventory/upload-from-immich', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ rowId: selectedItem.id, assetIds, deleteAfter: true })
      });
      loadItemDetail(selectedItem.id);
    } catch { /* silent */ }
    finally { uploading = false; }
  }

  async function createNewItem() {
    saving = true;
    try {
      const res = await fetch('/api/inventory/create', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ Item: 'New Item' }),
        credentials: 'include'
      });
      if (res.ok) {
        const data = await res.json();
        if (data.id) loadItemDetail(data.id);
      }
    } catch { /* silent */ }
    finally { saving = false; }
  }

  onMount(async () => {
    await loadSummary();
    loading = false;
    const itemId = page.url.searchParams.get('item');
    if (itemId) loadItemDetail(Number(itemId));
  });
</script>

{#snippet editableRow(nocoField: string, displayValue: string, classes: string)}
  {#if editingField === nocoField}
    <div class="detail-row editing">
      <span class="field-label">{nocoField}</span>
      <input
        class="edit-input {classes}"
        type={editableFields[nocoField]?.type === 'number' ? 'number' : 'text'}
        bind:value={editValue}
        onkeydown={handleEditKeydown}
        onblur={saveEdit}
        autofocus
      />
    </div>
  {:else}
    <div class="detail-row editable" onclick={() => startEdit(nocoField, rawField(nocoField))}>
      <span class="field-label">{nocoField}</span>
      <span class="field-value {classes}">{displayValue}</span>
    </div>
  {/if}
{/snippet}

<div class="page">
  <div class="app-surface">
    <section class="inventory-command reveal">
      <div class="command-copy">
        <div class="command-label">Atelier inventory</div>
        <h1>Inventory</h1>
        <p>Review blockers, verify arrivals, and open records without leaving the live operating queue.</p>
      </div>
      <div class="command-actions">
        <div class="command-kicker">Live queue</div>
        <div class="command-stats">{issueCount + reviewCount} active · {recentCount} recent</div>
        <button class="btn-primary intro-btn" onclick={createNewItem}>New item</button>
      </div>
    </section>

    <section class="signal-strip stagger">
      <button class="signal-card" class:active={activeTab === 'issues'} onclick={() => activeTab = 'issues'}>
        <div class="signal-topline">
          <div class="signal-label">Issues</div>
          <div class="signal-value">{issueCount}</div>
        </div>
        <div class="signal-note">Blocked items that need a decision now.</div>
      </button>
      <button class="signal-card" class:active={activeTab === 'review'} onclick={() => activeTab = 'review'}>
        <div class="signal-topline">
          <div class="signal-label">Needs review</div>
          <div class="signal-value">{reviewCount}</div>
        </div>
        <div class="signal-note">Arrivals waiting on confirmation, cleanup, or sorting.</div>
      </button>
      <button class="signal-card" class:active={activeTab === 'all'} onclick={() => { activeTab = 'all'; loadRecent(); }}>
        <div class="signal-topline">
          <div class="signal-label">Recent</div>
          <div class="signal-value">{recentCount}</div>
        </div>
        <div class="signal-note">Fresh records for context beyond the active queues.</div>
      </button>
    </section>

    <section class="inventory-layout">
      <div class="inventory-main">
        <div class="toolbar-card">
          <div class="toolbar-head">
            <div>
              <div class="toolbar-label">Lookup</div>
              <div class="toolbar-title">Search and open records</div>
            </div>
            <div class="toolbar-meta">
              {#if searchQuery && searchResults !== null}
                {activeCount} result{activeCount !== 1 ? 's' : ''}
              {:else}
                Showing {activeCount}
              {/if}
            </div>
          </div>

          <div class="search-wrap">
            <svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
            <input
              type="text"
              class="search-input"
              placeholder="Search by item name, order number, serial number, SKU..."
              bind:value={searchQuery}
              oninput={onSearchInput}
            />
            {#if searchQuery}
              <button class="search-clear" onclick={() => { searchQuery = ''; searchResults = null; }}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
              </button>
            {/if}
          </div>

          {#if searchQuery && searchResults !== null}
            <div class="search-results-label">{displayedItems().length} result{displayedItems().length !== 1 ? 's' : ''} for "{searchQuery}"</div>
          {/if}
        </div>

        <div class="queue-header">
          <div>
            <div class="queue-label">Working queue</div>
            <div class="queue-title">
              {#if activeTab === 'issues'}
                Items with blockers
              {:else if activeTab === 'review'}
                Items waiting on verification
              {:else}
                Recent inventory records
              {/if}
            </div>
            <div class="queue-summary">
              {#if activeTab === 'issues'}
                Direct triage for damaged, mismatched, or unresolved items.
              {:else if activeTab === 'review'}
                Validate condition, fields, and photos before records settle.
              {:else}
                Recent records from the live inventory feed.
              {/if}
            </div>
          </div>
          <div class="queue-freshness">{loading ? 'Syncing…' : 'Live from inventory API'}</div>
        </div>

        <div class="items-card">
          {#each displayedItems() as item (item.id)}
            <button class="item-row" class:has-issue={item.status === 'Issue'} class:has-review={item.status === 'Needs Review'} onclick={() => openDetail(item)}>
              <div class="row-accent"></div>
              <div class="item-info">
                <div class="item-name">{item.name}</div>
                <div class="item-meta">
                  <span>Order #{item.order || '—'}</span>
                  <span>SKU {item.sku || '—'}</span>
                </div>
              </div>
              <div class="item-tail">
                <span class="status-badge {statusColor(item.status)}">{item.status}</span>
                <svg class="row-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
              </div>
            </button>
          {/each}
          {#if displayedItems().length === 0}
            <div class="empty">No items found</div>
          {/if}
        </div>
      </div>

      <aside class="inventory-side reveal">
        <div class="side-card accent-card">
          <div class="section-label">Attention</div>
          <div class="side-stat">
            <div class="side-value">{issueCount + reviewCount}</div>
            <div class="side-note">records still need a human pass before they can disappear into archive flow</div>
          </div>
        </div>
        <div class="side-card">
          <div class="section-label">Current mode</div>
          <div class="mode-panel">
            <div class="mode-title">
              {#if activeTab === 'issues'}
                Issue queue
              {:else if activeTab === 'review'}
                Review queue
              {:else}
                Recent records
              {/if}
            </div>
            <div class="mode-copy">
              {#if activeTab === 'issues'}
                Use this view when something is damaged, missing, duplicated, or just wrong.
              {:else if activeTab === 'review'}
                Use this view for arrivals that still need validation and cleanup.
              {:else}
                Use this view when you need broad recency context beyond the active blockers.
              {/if}
            </div>
          </div>
        </div>
        <div class="side-card">
          <div class="section-label">Field guide</div>
          <div class="side-list">
            <div>Search by item, order number, serial, or SKU.</div>
            <div>Open a row to change status, edit fields, or attach photos.</div>
            <div>Use the inspector as the source of truth while the queue stays stable behind it.</div>
          </div>
        </div>
      </aside>
    </section>
  </div>
</div>

{#if detailOpen && selectedItem}
  <div class="detail-overlay" onclick={closeDetail}>
    <div class="detail-sheet" onclick={(e) => e.stopPropagation()}>
      <div class="detail-header">
        {#if editingField === 'Item'}
          <input class="edit-input detail-title-edit" type="text" bind:value={editValue} onkeydown={handleEditKeydown} onblur={saveEdit} autofocus />
        {:else}
          <div class="detail-title editable" onclick={() => startEdit('Item', rawField('Item'))}>{selectedItem.name}</div>
        {/if}
        <button class="detail-close" onclick={closeDetail}>Close</button>
      </div>

      <div class="status-control">
        {#each statusOptions as status}
          <button class="status-seg" class:active={selectedItem.status === status} data-status={status} onclick={() => changeStatus(status)}>
            {status}
          </button>
        {/each}
      </div>

      <div class="detail-hero">
        <div class="detail-primary-photo">
          {#if selectedItem.photoUrls.length > 0}
            <img class="hero-photo-img" src={selectedItem.photoUrls[activePhoto]} alt="Item photo" loading="lazy" />
          {:else}
            <div class="photo-placeholder empty-photo"><span>No photos yet</span></div>
          {/if}
        </div>

        {#if selectedItem.photoUrls.length > 1}
          <div class="detail-photos">
            {#each selectedItem.photoUrls as url, index}
              <button class="photo-thumb" class:active={activePhoto === index} onclick={() => activePhoto = index}>
                <img class="photo-img" src={url} alt="Item photo" loading="lazy" />
              </button>
            {/each}
          </div>
        {/if}
      </div>

      <div class="actions-group">
        <div class="actions-row">
          <input type="file" accept="image/*" multiple class="hidden-input" bind:this={fileInput} onchange={handleFileSelect} />
          <button class="action-btn primary" onclick={() => uploadMenuOpen = !uploadMenuOpen} disabled={uploading}>{uploading ? 'Uploading...' : 'Upload photos'}</button>
          {#if uploadMenuOpen}
            <div class="upload-menu">
              <button class="upload-option" onclick={() => { uploadMenuOpen = false; triggerUpload(); }}>From device</button>
              <button class="upload-option" onclick={() => { uploadMenuOpen = false; immichOpen = true; }}>From Immich</button>
            </div>
          {/if}
          <button class="action-btn" onclick={sendToPhone}>Phone</button>
          <button class="action-btn sm" onclick={duplicateItem}>Duplicate</button>
        </div>
      </div>

      <div class="detail-body">
        <div class="detail-column">
          <div class="section-group">
            <div class="section-label">Purchase</div>
            <div class="detail-fields">
              {@render editableRow('Price Per Item', formatPrice(selectedItem.price), 'mono')}
              {@render editableRow('Tax', formatPrice(selectedItem.tax), 'mono')}
              {@render editableRow('Total', formatPrice(selectedItem.total), 'mono strong')}
              {@render editableRow('QTY', String(selectedItem.qty), '')}
            </div>
          </div>

          <div class="section-group">
            <div class="section-label">Notes</div>
            <div class="detail-fields">
              {@render editableRow('Notes', selectedItem.notes || 'Add notes...', '')}
            </div>
          </div>
        </div>

        <div class="detail-column">
          <div class="section-group">
            <div class="section-label">Item info</div>
            <div class="detail-fields">
              {@render editableRow('SKU', selectedItem.sku || '—', 'mono')}
              {@render editableRow('Serial Numbers', selectedItem.serial || '—', 'mono')}
              {@render editableRow('Order Number', selectedItem.order || '—', 'mono')}
              {@render editableRow('Source', selectedItem.vendor || '—', '')}
              {@render editableRow('Tracking Number', selectedItem.tracking || '—', 'mono')}
            </div>
          </div>
        </div>
      </div>

      <a class="action-btn ghost open-noco" href={nocodbUrl || '#'} target="_blank" rel="noopener">Open in NocoDB</a>
    </div>
  </div>
{/if}

{#if immichOpen}
  <ImmichPicker bind:open={immichOpen} onselect={handleImmichSelect} />
{/if}

<style>
  .page {
    padding-top: 0;
  }
  .app-surface {
    max-width: 1360px;
  }
  .inventory-command {
    display: flex;
    justify-content: space-between;
    align-items: end;
    gap: 24px;
    padding: 8px 0 18px;
  }
  .command-copy {
    max-width: 640px;
  }
  .command-label {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: #8c7b69;
    margin-bottom: 8px;
  }
  .command-copy h1 {
    margin: 0;
    font-size: clamp(2.1rem, 4.1vw, 3.5rem);
    line-height: 0.94;
    letter-spacing: -0.065em;
    color: #17120d;
  }
  .command-copy p {
    margin: 12px 0 0;
    max-width: 46ch;
    color: #5c5046;
    font-size: 1rem;
    line-height: 1.55;
  }
  .command-actions {
    min-width: 220px;
    display: grid;
    justify-items: end;
    gap: 8px;
  }
  .command-kicker {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: #8c7b69;
  }
  .command-stats {
    font-size: 1.15rem;
    letter-spacing: -0.04em;
    color: #221a13;
  }
  .intro-btn { background: #1e1812; border-color: #1e1812; color: white; box-shadow: none; }
  .intro-btn:hover { filter: none; transform: none; box-shadow: none; opacity: 0.92; }
  .signal-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
  .signal-card, .inventory-main, .side-card, .toolbar-card {
    border-radius: 28px; border: 1px solid rgba(35,26,17,0.08); background: rgba(255,252,248,0.68); backdrop-filter: blur(14px);
  }
  .signal-card { padding: 18px; text-align: left; transition: transform 160ms ease, background 160ms ease, border-color 160ms ease; }
  .signal-card:hover { transform: translateY(-2px); background: rgba(255,255,255,0.82); }
  .signal-card.active {
    border-color: rgba(179,92,50,0.2);
    background: linear-gradient(145deg, rgba(255,248,242,0.94), rgba(246,237,227,0.72));
  }
  .signal-topline {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
  }
  .signal-label, .toolbar-label, .section-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: #7d6f61; }
  .signal-value, .side-value { font-size: clamp(1.8rem, 4vw, 2.7rem); line-height: 0.95; letter-spacing: -0.05em; color: #1e1812; }
  .signal-note, .side-note, .side-list, .toolbar-meta, .item-meta { color: #4f463d; line-height: 1.6; }
  .inventory-layout { display: grid; grid-template-columns: minmax(0, 1.5fr) 290px; gap: 18px; align-items: start; }
  .inventory-main { padding: 16px; background: linear-gradient(180deg, rgba(255,252,248,0.84), rgba(244,237,229,0.74)); }
  .toolbar-card { padding: 16px 16px 12px; margin-bottom: 8px; background: rgba(255,255,255,0.42); }
  .toolbar-head { display: flex; align-items: end; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
  .toolbar-title { margin-top: 4px; font-size: 1.1rem; letter-spacing: -0.035em; color: #1e1812; }
  .inventory-side { display: grid; gap: 12px; }
  .side-card { padding: 20px; }
  .accent-card {
    background: linear-gradient(180deg, rgba(255,248,242,0.96), rgba(240,234,227,0.84));
  }
  .side-stat, .side-list { margin-top: 14px; }
  .queue-header {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 14px;
    padding: 8px 4px 14px;
  }
  .queue-label, .queue-freshness {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: #7d6f61;
  }
  .queue-title {
    margin-top: 4px;
    font-size: 1.35rem;
    letter-spacing: -0.04em;
    color: #1e1812;
  }
  .queue-summary {
    margin-top: 6px;
    color: #6a5d50;
    font-size: 0.94rem;
    line-height: 1.45;
  }
  .search-wrap { position: relative; margin-bottom: var(--sp-4); }
  .search-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: #7f7365; pointer-events: none; }
  .search-input {
    width: 100%;
    padding: var(--sp-3) var(--sp-10) var(--sp-3) 42px;
    border-radius: var(--radius);
    border: 1.5px solid rgba(35,26,17,0.12);
    background: rgba(255,255,255,0.92);
    color: #1e1812;
    font-size: var(--text-md);
    font-family: var(--font);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.5);
  }
  .search-input::placeholder { color: #8b7b6a; }
  .search-input:focus {
    outline: none;
    border-color: rgba(179,92,50,0.5);
    box-shadow: 0 0 0 4px rgba(179,92,50,0.08);
  }
  .search-clear {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: #7f7365;
  }
  .search-clear:hover { color: #1e1812; }
  .search-results-label { color: #5f564b; font-size: 13px; }
  .items-card { background: rgba(255,255,255,0.82); border-radius: 24px; border: 1px solid rgba(35,26,17,0.06); overflow: hidden; box-shadow: 0 16px 44px rgba(42,30,19,0.05); }
  .item-row { display: grid; grid-template-columns: 4px minmax(0, 1fr) auto; align-items: center; gap: 16px; padding: 18px 16px; width: 100%; background: none; border: none; text-align: left; transition: background 160ms ease, transform 160ms ease; }
  .item-row:hover { background: rgba(255,248,242,0.88); transform: translateX(2px); }
  .item-row + .item-row { border-top: 1px solid rgba(35,26,17,0.07); }
  .row-accent {
    align-self: stretch;
    border-radius: 999px;
    background: rgba(35,26,17,0.08);
  }
  .item-row.has-issue .row-accent { background: linear-gradient(180deg, #ff5d45, #ef3d2f); }
  .item-row.has-review .row-accent { background: linear-gradient(180deg, #f6a33a, #e28615); }
  .item-info { flex: 1; min-width: 0; }
  .item-name {
    font-size: 1rem;
    font-weight: 700;
    color: #1e1812;
    line-height: 1.25;
  }
  .item-row:hover .item-name { color: #140f0b; }
  .item-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 12px;
    margin-top: 6px;
    color: #5d5248;
    font-size: 0.88rem;
  }
  .item-tail {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-left: auto;
  }
  .status-badge.error { background: var(--error-dim); color: var(--error); }
  .status-badge.success { background: var(--success-dim); color: var(--success); }
  .status-badge.warning { background: var(--warning-bg); color: var(--warning); }
  .status-badge.muted { background: var(--card-hover); color: var(--text-4); }
  .status-badge { font-size: var(--text-xs); font-weight: 700; padding: 5px 10px; border-radius: 999px; flex-shrink: 0; }
  .row-chevron { width: 14px; height: 14px; color: #7d6f61; flex-shrink: 0; opacity: 0.7; }
  .empty { color: #5f564b; }
  .empty { padding: var(--sp-12); text-align: center; color: var(--text-3); font-size: var(--text-base); }
  .detail-overlay { position: fixed; inset: 0; background: rgba(17,13,10,0.42); z-index: 60; display: flex; justify-content: flex-end; backdrop-filter: blur(12px); }
  .detail-sheet { width: 680px; max-width: 100%; height: 100%; background: linear-gradient(180deg, #f8f1e8 0%, #f3eadc 100%); overflow-y: auto; padding: var(--sp-7); box-shadow: -20px 0 50px rgba(18,13,10,0.16); border-left: 1px solid rgba(35,26,17,0.08); color: #1e1812; animation: sheetIn 220ms ease; }
  .detail-header { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-3); margin-bottom: 16px; }
  .detail-title {
    font-size: 1.6rem;
    font-weight: 700;
    color: #1e1812;
    line-height: 1.12;
    letter-spacing: -0.04em;
    flex: 1;
    min-width: 0;
  }
  .status-control { display: flex; justify-content: center; gap: 0; margin: 0 8px 22px; background: rgba(255,255,255,0.72); border: 1px solid rgba(35,26,17,0.09); border-radius: var(--radius); padding: 3px; }
  .status-seg { flex: 1; padding: 8px 0; font-size: var(--text-sm); background: none; border: none; border-radius: 10px; }
  .status-seg.active[data-status="Issue"] { background: var(--error-dim); color: var(--error); }
  .status-seg.active[data-status="Pending"] { background: var(--warning-bg); color: var(--warning); }
  .status-seg.active[data-status="Received"] { background: var(--success-dim); color: var(--success); }
  .status-seg.active[data-status="Needs Review"] { background: rgba(217,119,6,0.12); color: #9a5d09; }
  .detail-hero {
    margin-bottom: var(--sp-5);
  }
  .detail-primary-photo {
    width: 100%;
    height: 280px;
    border-radius: 18px;
    overflow: hidden;
    background: rgba(255,255,255,0.58);
    border: 1px solid rgba(35,26,17,0.08);
  }
  .hero-photo-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    background: var(--card-hover);
  }
  .detail-photos { display: flex; gap: 10px; margin-top: 10px; overflow-x: auto; }
  .photo-thumb {
    border: none;
    background: none;
    padding: 0;
    border-radius: 12px;
    overflow: hidden;
    opacity: 0.7;
    transition: opacity 160ms ease, transform 160ms ease;
  }
  .photo-thumb.active,
  .photo-thumb:hover {
    opacity: 1;
    transform: translateY(-1px);
  }
  .photo-img, .photo-placeholder { width: 116px; height: 88px; border-radius: 12px; flex-shrink: 0; }
  .photo-img { object-fit: cover; background: var(--card-hover); display: block; }
  .photo-placeholder { background: rgba(255,255,255,0.58); border: 1px dashed rgba(35,26,17,0.13); display: flex; align-items: center; justify-content: center; }
  .empty-photo { width: 100%; height: 100%; }
  .actions-group { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-7); }
  .actions-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2); position: relative; }
  .action-btn { display: flex; align-items: center; justify-content: center; gap: 5px; padding: 8px 14px; border-radius: var(--radius-md); background: rgba(255,255,255,0.8); border: 1px solid rgba(35,26,17,0.1); font-size: var(--text-sm); color: #1e1812; }
  .action-btn.primary { background: #1e1812; border-color: #1e1812; color: white; }
  .action-btn.ghost { background: none; color: #6b6256; }
  .action-btn.sm { padding: 6px 11px; }
  .open-noco { margin-top: 8px; }
  .detail-body {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: 14px;
  }
  .detail-column {
    display: grid;
    gap: 14px;
    align-content: start;
  }
  .section-group {
    display: grid;
    gap: 8px;
  }
  .detail-fields { background: rgba(255,255,255,0.76); border-radius: var(--radius); border: 1px solid rgba(35,26,17,0.08); overflow: hidden; }
  .detail-row { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; }
  .detail-row + .detail-row { border-top: 1px solid rgba(35,26,17,0.08); }
  .field-label { font-size: var(--text-sm); color: #6b5f53; opacity: 1; }
  .field-value { font-size: var(--text-base); color: #1e1812; text-align: right; }
  .detail-row.editable, .detail-title.editable { cursor: pointer; }
  .detail-row.editable:hover { background: rgba(255,248,242,0.62); }
  .edit-input { width: 100%; padding: 6px 10px; border-radius: var(--radius-sm); border: 1px solid var(--accent); background: rgba(255,255,255,0.9); color: #1e1812; }
  .detail-title-edit { font-size: var(--text-lg); font-weight: 600; text-align: left; flex: 1; min-width: 0; }
  .upload-menu { position: absolute; left: 0; right: 0; top: 100%; margin-top: var(--sp-1); z-index: 10; background: rgba(255,250,244,0.96); border: 1px solid rgba(35,26,17,0.09); border-radius: 10px; overflow: hidden; box-shadow: 0 10px 30px rgba(18,13,10,0.1); }
  .upload-option { display: flex; align-items: center; width: 100%; padding: 12px 16px; background: none; border: none; text-align: left; color: #1e1812; }
  .upload-option + .upload-option { border-top: 1px solid rgba(35,26,17,0.08); }
  .hidden-input { display: none; }
  .open-noco { color: #5f564b; }
  .open-noco:hover { color: #1e1812; }
  .mode-panel {
    margin-top: 14px;
  }
  .mode-title {
    font-size: 1.15rem;
    letter-spacing: -0.04em;
    color: #20170f;
  }
  .mode-copy {
    margin-top: 8px;
    color: #5f564b;
    line-height: 1.55;
  }
  .reveal {
    animation: riseIn 280ms ease;
  }
  .stagger .signal-card:nth-child(1) { animation: riseIn 220ms ease; }
  .stagger .signal-card:nth-child(2) { animation: riseIn 260ms ease; }
  .stagger .signal-card:nth-child(3) { animation: riseIn 300ms ease; }
  @keyframes riseIn {
    from {
      opacity: 0;
      transform: translateY(8px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  @keyframes sheetIn {
    from {
      opacity: 0;
      transform: translateX(20px);
    }
    to {
      opacity: 1;
      transform: translateX(0);
    }
  }
  @media (max-width: 768px) {
    .inventory-command,
    .signal-strip,
    .inventory-layout { grid-template-columns: 1fr; }
    .inventory-command {
      display: grid;
      align-items: start;
      gap: 14px;
    }
    .command-actions {
      justify-items: start;
    }
    .detail-sheet { width: 100%; padding: var(--sp-5); }
    .queue-header,
    .toolbar-head { flex-direction: column; align-items: flex-start; }
    .item-row { align-items: flex-start; }
    .item-tail { gap: 8px; }
    .detail-primary-photo {
      height: 220px;
    }
    .detail-body {
      grid-template-columns: 1fr;
    }
  }
</style>
