import { useEffect, useState, useRef, useCallback, useLayoutEffect } from 'react';

// ── Client-side file inspection ──────────────────────────────────────────────

function inspectFile(file) {
  return new Promise((resolve) => {
    const url = URL.createObjectURL(file);
    const done = (result) => { URL.revokeObjectURL(url); resolve(result); };

    if (file.type.startsWith('image/')) {
      const img = new Image();
      img.onload = () => done({ width: img.naturalWidth, height: img.naturalHeight, duration: null });
      img.onerror = () => done({ width: null, height: null, duration: null });
      img.src = url;
    } else if (file.type.startsWith('video/')) {
      const video = document.createElement('video');
      video.preload = 'metadata';
      video.onloadedmetadata = () =>
        done({ width: video.videoWidth, height: video.videoHeight, duration: video.duration });
      video.onerror = () => done({ width: null, height: null, duration: null });
      video.src = url;
    } else if (file.type.startsWith('audio/')) {
      const audio = document.createElement('audio');
      audio.preload = 'metadata';
      audio.onloadedmetadata = () => done({ width: null, height: null, duration: audio.duration });
      audio.onerror = () => done({ width: null, height: null, duration: null });
      audio.src = url;
    } else {
      done({ width: null, height: null, duration: null });
    }
  });
}

// Capture a still frame from a video file for thumbnail preview
function captureVideoFrame(file) {
  return new Promise((resolve) => {
    const url = URL.createObjectURL(file);
    const video = document.createElement('video');
    const canvas = document.createElement('canvas');
    video.muted = true;
    video.preload = 'metadata';
    video.onloadeddata = () => { video.currentTime = 0.5; };
    video.onseeked = () => {
      canvas.width = Math.min(video.videoWidth, 400);
      canvas.height = Math.round(canvas.width * (video.videoHeight / video.videoWidth));
      canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
      URL.revokeObjectURL(url);
      resolve(canvas.toDataURL('image/jpeg', 0.7));
    };
    video.onerror = () => { URL.revokeObjectURL(url); resolve(null); };
    video.src = url;
  });
}

// ── Helpers ──────────────────────────────────────────────────────────────────

function formatBytes(n) {
  if (!n) return '—';
  if (n < 1024) return `${n} B`;
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
  if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
  return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
}

function formatDuration(sec) {
  if (!sec) return null;
  const m = Math.floor(sec / 60);
  const s = Math.floor(sec % 60);
  return `${m}:${String(s).padStart(2, '0')}`;
}

const TYPE_COLORS = {
  image: '#4a9eff',
  video: '#e06c4a',
  audio: '#6cb86e',
  other: '#999',
};

// ── Components ───────────────────────────────────────────────────────────────

// ── Preview modal ─────────────────────────────────────────────────────────────

function PreviewModal({ asset, onClose }) {
  // Close on Escape
  useLayoutEffect(() => {
    function onKey(e) { if (e.key === 'Escape') onClose(); }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  const [copied, setCopied] = useState(false);
  function copyUrl() {
    navigator.clipboard.writeText(asset.url);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  }

  const dims = asset.width && asset.height ? `${asset.width}×${asset.height}` : null;
  const dur  = formatDuration(asset.duration_seconds);
  const size = formatBytes(asset.file_size_bytes);

  return (
    <div style={s.modalOverlay} onClick={onClose}>
      <div style={s.modalBox} onClick={e => e.stopPropagation()}>

        {/* Close */}
        <button style={s.modalClose} onClick={onClose}>✕</button>

        {/* Media */}
        <div style={s.modalMedia}>
          {asset.asset_type === 'video' && (
            <video src={asset.url} controls autoPlay style={s.modalVideo} />
          )}
          {asset.asset_type === 'image' && (
            <img src={asset.url} alt="" style={s.modalImage} />
          )}
          {asset.asset_type === 'audio' && (
            <div style={s.modalAudioWrap}>
              <div style={s.modalAudioIcon}>♫</div>
              <audio src={asset.url} controls style={{ width: '100%' }} autoPlay />
            </div>
          )}
        </div>

        {/* Info bar */}
        <div style={s.modalInfo}>
          <div style={s.modalFilename}>
            {asset.original_filename || asset.filename}
          </div>
          <div style={s.meta}>
            <span style={{ ...s.typeBadge, position: 'static', background: TYPE_COLORS[asset.asset_type] }}>
              {asset.asset_type}
            </span>
            {dims && <span>{dims}</span>}
            {dur  && <span>{dur}</span>}
            {size && <span>{size}</span>}
          </div>

          {/* Attribution */}
          {(asset.license || asset.copyright_holder || asset.source_url || asset.uploader) && (
            <div style={s.modalAttribution}>
              {asset.copyright_holder && (
                <span>© {asset.copyright_holder}</span>
              )}
              {asset.license && (
                <span style={s.modalLicenseBadge}>{asset.license}</span>
              )}
              {asset.uploader && (
                <span style={{ color: '#666' }}>uploaded by {asset.uploader}</span>
              )}
              {asset.source_url && (
                <a href={asset.source_url} target="_blank" rel="noreferrer" style={s.modalSourceLink}>
                  View source ↗
                </a>
              )}
            </div>
          )}

          <button style={{ ...s.btn, maxWidth: 120, marginTop: 8 }} onClick={copyUrl}>
            {copied ? '✓ Copied' : 'Copy URL'}
          </button>
        </div>
      </div>
    </div>
  );
}

function AssetCard({ asset, onDelete, onPreview, onUpdate }) {
  const [copied, setCopied]             = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(false);
  const [hovered, setHovered]           = useState(false);
  const [editing, setEditing]           = useState(false);
  const [draft, setDraft]               = useState({});
  const [saving, setSaving]             = useState(false);

  function copyUrl() {
    navigator.clipboard.writeText(asset.url);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  }

  async function handleDelete() {
    if (!confirmDelete) { setConfirmDelete(true); return; }
    await fetch(`/api/assets/${asset.id}`, { method: 'DELETE' });
    onDelete(asset.id);
  }

  function startEdit() {
    setDraft({
      description:      asset.description      ?? '',
      license:          asset.license          ?? '',
      copyright_holder: asset.copyright_holder ?? '',
      source_url:       asset.source_url       ?? '',
      uploader:         asset.uploader         ?? '',
    });
    setEditing(true);
  }

  async function saveEdit() {
    setSaving(true);
    try {
      const r = await fetch(`/api/assets/${asset.id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(draft),
      });
      const d = await r.json();
      if (r.ok) { onUpdate(d.asset); setEditing(false); }
    } finally {
      setSaving(false);
    }
  }

  const dims = asset.width && asset.height ? `${asset.width}×${asset.height}` : null;
  const dur  = formatDuration(asset.duration_seconds);
  const size = formatBytes(asset.file_size_bytes);
  const canPreview = asset.url && ['video', 'image', 'audio'].includes(asset.asset_type);
  const hasAttribution = asset.license || asset.copyright_holder || asset.source_url || asset.uploader;

  return (
    <div style={s.card} onMouseLeave={() => { setConfirmDelete(false); setHovered(false); }}>
      {/* Thumbnail */}
      <div
        style={{ ...s.thumb, cursor: canPreview ? 'pointer' : 'default' }}
        onClick={() => canPreview && onPreview(asset)}
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
      >
        {asset.asset_type === 'image' && asset.url ? (
          <img src={asset.url} alt="" style={s.thumbImg} />
        ) : asset.asset_type === 'video' ? (
          <video src={asset.url} preload="metadata" muted
                 style={{ ...s.thumbImg, pointerEvents: 'none' }} />
        ) : asset.asset_type === 'audio' ? (
          <div style={{ ...s.thumbPlaceholder, background: '#1a2e1a' }}>
            <span style={s.typeIcon}>♫</span>
          </div>
        ) : (
          <div style={{ ...s.thumbPlaceholder, background: '#2a2a2a' }}>
            <span style={s.typeIcon}>📄</span>
          </div>
        )}
        {canPreview && hovered && (
          <div style={s.thumbHover}>
            <span style={s.thumbHoverIcon}>{asset.asset_type === 'audio' ? '▶' : '⛶'}</span>
          </div>
        )}
        <span style={{ ...s.typeBadge, background: TYPE_COLORS[asset.asset_type] }}>
          {asset.asset_type}
        </span>
      </div>

      {/* Info */}
      <div style={s.cardBody}>
        <div style={s.filename} title={asset.original_filename}>
          {asset.original_filename || asset.filename}
        </div>
        <div style={s.meta}>
          {dims && <span>{dims}</span>}
          {dur  && <span>{dur}</span>}
          {size && <span>{size}</span>}
        </div>
        {asset.description && !editing && (
          <div style={s.desc}>{asset.description}</div>
        )}
        {/* Attribution summary */}
        {hasAttribution && !editing && (
          <div style={s.cardAttribution}>
            {asset.copyright_holder && (
              <span style={s.cardAttrItem}>© {asset.copyright_holder}</span>
            )}
            {asset.license && (
              <span style={{ ...s.cardAttrItem, ...s.licenseBadge }}>{asset.license}</span>
            )}
            {asset.source_url && (
              <a href={asset.source_url} target="_blank" rel="noreferrer"
                 style={s.sourceLink} onClick={e => e.stopPropagation()}>
                source ↗
              </a>
            )}
            {asset.uploader && !asset.copyright_holder && (
              <span style={s.cardAttrItem}>↑ {asset.uploader}</span>
            )}
          </div>
        )}
        {/* Inline edit form */}
        {editing && (
          <div style={s.editForm}>
            {[
              { key: 'description',      label: 'Description',      placeholder: 'Optional description' },
              { key: 'license',          label: 'License',          placeholder: 'e.g. Pexels License, CC BY 4.0' },
              { key: 'copyright_holder', label: 'Copyright holder', placeholder: 'Photographer / creator name' },
              { key: 'source_url',       label: 'Source URL',       placeholder: 'https://www.pexels.com/video/…' },
              { key: 'uploader',         label: 'Uploaded by',      placeholder: 'Your name' },
            ].map(({ key, label, placeholder }) => (
              <div key={key} style={s.editRow}>
                <label style={s.editLabel}>{label}</label>
                <input
                  style={s.editInput}
                  value={draft[key]}
                  placeholder={placeholder}
                  onChange={e => setDraft(d => ({ ...d, [key]: e.target.value }))}
                />
              </div>
            ))}
            <div style={{ display: 'flex', gap: 6, marginTop: 8 }}>
              <button style={{ ...s.btn, ...s.uploadBtn, flex: 'none', padding: '4px 12px', fontSize: 12 }}
                      onClick={saveEdit} disabled={saving}>
                {saving ? 'Saving…' : 'Save'}
              </button>
              <button style={s.btn} onClick={() => setEditing(false)}>Cancel</button>
            </div>
          </div>
        )}
      </div>

      {/* Actions */}
      <div style={s.actions}>
        <button style={s.btn} onClick={copyUrl}>{copied ? '✓ Copied' : 'Copy URL'}</button>
        <button style={s.btn} onClick={startEdit}>Edit</button>
        <button style={{ ...s.btn, ...(confirmDelete ? s.btnDanger : {}) }} onClick={handleDelete}>
          {confirmDelete ? 'Confirm?' : 'Delete'}
        </button>
      </div>
    </div>
  );
}

function PendingCard({ item }) {
  return (
    <div style={{ ...s.card, opacity: 0.7, border: '1px dashed #555' }}>
      <div style={s.thumb}>
        {item.preview ? (
          <img src={item.preview} alt="" style={s.thumbImg} />
        ) : item.videoThumb ? (
          <img src={item.videoThumb} alt="" style={s.thumbImg} />
        ) : (
          <div style={{ ...s.thumbPlaceholder, background: '#1a1a2a' }}>
            <span style={s.typeIcon}>
              {item.file.type.startsWith('video/') ? '▶' :
               item.file.type.startsWith('audio/') ? '♫' : '📄'}
            </span>
          </div>
        )}
        {item.uploading && (
          <div style={s.uploadOverlay}>Uploading…</div>
        )}
      </div>
      <div style={s.cardBody}>
        <div style={s.filename}>{item.file.name}</div>
        <div style={s.meta}>
          {item.meta.width && item.meta.height && (
            <span>{item.meta.width}×{item.meta.height}</span>
          )}
          {item.meta.duration && <span>{formatDuration(item.meta.duration)}</span>}
          <span>{formatBytes(item.file.size)}</span>
        </div>
      </div>
    </div>
  );
}

// ── Main page ─────────────────────────────────────────────────────────────────

export default function AssetsPage() {
  const [assets, setAssets]     = useState([]);
  const [filter, setFilter]     = useState('all');
  const [search, setSearch]     = useState('');
  const [loading, setLoading]   = useState(true);
  const [loadError, setLoadError] = useState(null);
  const [uploadErrors, setUploadErrors] = useState([]);
  const [pending, setPending]   = useState([]);   // files staged for upload
  const [uploading, setUploading] = useState(false);
  const [dragOver, setDragOver] = useState(false);
  const [previewAsset, setPreviewAsset] = useState(null);
  const fileInputRef = useRef();

  // Load assets
  const loadAssets = useCallback(async () => {
    setLoadError(null);
    try {
      const params = new URLSearchParams();
      if (filter !== 'all') params.set('type', filter);
      if (search) params.set('q', search);
      const r = await fetch(`/api/assets?${params}`);
      if (!r.ok) throw new Error(`Server error ${r.status}`);
      const d = await r.json();
      setAssets(d.assets || []);
    } catch (err) {
      setLoadError(err.message);
    } finally {
      setLoading(false);
    }
  }, [filter, search]);

  useEffect(() => { loadAssets(); }, [loadAssets]);

  // Stage files for upload after client-side inspection
  async function stageFiles(fileList) {
    const files = Array.from(fileList);
    const staged = await Promise.all(files.map(async (file) => {
      const meta = await inspectFile(file);
      const preview = file.type.startsWith('image/') ? URL.createObjectURL(file) : null;
      const videoThumb = file.type.startsWith('video/') ? await captureVideoFrame(file) : null;
      return { file, meta, preview, videoThumb, uploading: false };
    }));
    setPending(prev => [...prev, ...staged]);
  }

  function handleFileInput(e) {
    stageFiles(e.target.files);
    e.target.value = '';
  }

  function handleDrop(e) {
    e.preventDefault();
    setDragOver(false);
    stageFiles(e.dataTransfer.files);
  }

  // Upload all staged files
  async function uploadAll() {
    if (uploading || !pending.length) return;
    setUploading(true);
    setUploadErrors([]);
    const uploaded = [];
    const errors = [];

    for (let i = 0; i < pending.length; i++) {
      const { file, meta } = pending[i];
      setPending(prev => prev.map((p, idx) => idx === i ? { ...p, uploading: true } : p));

      try {
        const fd = new FormData();
        fd.append('file', file);
        if (meta.width    != null) fd.append('width',    meta.width);
        if (meta.height   != null) fd.append('height',   meta.height);
        if (meta.duration != null) fd.append('duration', meta.duration);

        const r = await fetch('/api/assets/upload', { method: 'POST', body: fd });
        const d = await r.json();
        if (r.ok) {
          uploaded.push(d.asset);
        } else {
          errors.push(`${file.name}: ${d.error || r.status}`);
        }
      } catch (err) {
        errors.push(`${file.name}: ${err.message}`);
      }
    }

    setAssets(prev => [...uploaded, ...prev]);
    setPending([]);
    setUploadErrors(errors);
    setUploading(false);
  }

  function removePending(idx) {
    setPending(prev => {
      const copy = [...prev];
      if (copy[idx].preview) URL.revokeObjectURL(copy[idx].preview);
      copy.splice(idx, 1);
      return copy;
    });
  }

  function handleDeleteAsset(id) {
    setAssets(prev => prev.filter(a => a.id !== id));
  }

  function handleUpdateAsset(updated) {
    setAssets(prev => prev.map(a => a.id === updated.id ? { ...a, ...updated } : a));
  }

  const FILTERS = ['all', 'image', 'video', 'audio'];

  return (
    <div style={s.page}>
      {/* Header */}
      <div style={s.header}>
        <h1 style={s.title}>Asset Library</h1>
        <button style={s.uploadBtn} onClick={() => fileInputRef.current.click()}>
          + Upload Files
        </button>
        <input
          ref={fileInputRef}
          type="file"
          multiple
          accept="image/*,video/*,audio/*"
          style={{ display: 'none' }}
          onChange={handleFileInput}
        />
      </div>

      {/* Drop zone — always visible, expands when dragging */}
      <div
        style={{ ...s.dropZone, ...(dragOver ? s.dropZoneActive : {}) }}
        onDragOver={e => { e.preventDefault(); setDragOver(true); }}
        onDragLeave={() => setDragOver(false)}
        onDrop={handleDrop}
        onClick={() => !pending.length && fileInputRef.current.click()}
      >
        {dragOver
          ? 'Drop to stage files'
          : 'Drag & drop images, videos, or audio here'}
      </div>

      {/* Staged files */}
      {pending.length > 0 && (
        <div style={s.section}>
          <div style={s.sectionHeader}>
            <span style={s.sectionTitle}>
              Staged — {pending.length} file{pending.length > 1 ? 's' : ''}
            </span>
            <div style={{ display: 'flex', gap: 8 }}>
              <button style={s.btn} onClick={() => setPending([])}>Clear</button>
              <button style={{ ...s.btn, ...s.uploadBtn }} onClick={uploadAll} disabled={uploading}>
                {uploading ? 'Uploading…' : `Upload ${pending.length} file${pending.length > 1 ? 's' : ''}`}
              </button>
            </div>
          </div>
          <div style={s.grid}>
            {pending.map((item, i) => (
              <div key={i} style={{ position: 'relative' }}>
                <PendingCard item={item} />
                {!item.uploading && (
                  <button
                    style={s.removeBtn}
                    onClick={() => removePending(i)}
                    title="Remove"
                  >×</button>
                )}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Filter + search bar */}
      <div style={s.toolbar}>
        <div style={s.tabs}>
          {FILTERS.map(f => (
            <button
              key={f}
              style={{ ...s.tab, ...(filter === f ? s.tabActive : {}) }}
              onClick={() => setFilter(f)}
            >
              {f.charAt(0).toUpperCase() + f.slice(1)}
              {f !== 'all' && (
                <span style={s.tabCount}>
                  {assets.filter(a => a.asset_type === f).length || ''}
                </span>
              )}
            </button>
          ))}
        </div>
        <input
          style={s.searchInput}
          placeholder="Search by filename…"
          value={search}
          onChange={e => setSearch(e.target.value)}
        />
      </div>

      {/* Upload errors */}
      {uploadErrors.length > 0 && (
        <div style={s.errorBox}>
          <strong>Upload failed:</strong>
          <ul style={{ margin: '4px 0 0 0', paddingLeft: 20 }}>
            {uploadErrors.map((e, i) => <li key={i}>{e}</li>)}
          </ul>
          <button style={s.errorDismiss} onClick={() => setUploadErrors([])}>✕</button>
        </div>
      )}

      {/* Asset grid */}
      {loading ? (
        <p style={{ color: '#888' }}>Loading…</p>
      ) : loadError ? (
        <div style={s.errorBox}>
          Backend unavailable: {loadError}
          <button style={s.errorDismiss} onClick={loadAssets}>Retry</button>
        </div>
      ) : assets.length === 0 ? (
        <p style={{ color: '#888' }}>
          {search || filter !== 'all' ? 'No assets match.' : 'No assets yet. Upload some files above.'}
        </p>
      ) : (
        <div style={s.grid}>
          {assets.map(asset => (
            <AssetCard key={asset.id} asset={asset} onDelete={handleDeleteAsset}
                       onPreview={setPreviewAsset} onUpdate={handleUpdateAsset} />
          ))}
        </div>
      )}
      {/* Preview modal */}
      {previewAsset && (
        <PreviewModal asset={previewAsset} onClose={() => setPreviewAsset(null)} />
      )}
    </div>
  );
}

// ── Styles ────────────────────────────────────────────────────────────────────

const s = {
  page:        { fontFamily: 'sans-serif', maxWidth: 1200, margin: '0 auto', padding: '2rem 1rem', background: '#0f0f17', minHeight: '100vh', color: '#e0e0e0' },
  header:      { display: 'flex', alignItems: 'center', gap: 16, marginBottom: '1.5rem' },
  title:       { margin: 0, fontSize: 24, fontWeight: 700 },
  uploadBtn:   { marginLeft: 'auto', padding: '8px 18px', background: '#4a9eff', color: '#fff', border: 'none', borderRadius: 6, cursor: 'pointer', fontWeight: 600, fontSize: 14 },

  dropZone:       { border: '2px dashed #333', borderRadius: 10, padding: '2rem', textAlign: 'center', color: '#555', cursor: 'pointer', marginBottom: '1.5rem', transition: 'all 0.15s', fontSize: 14 },
  dropZoneActive: { borderColor: '#4a9eff', background: '#0a1a2e', color: '#4a9eff' },

  section:       { marginBottom: '2rem' },
  sectionHeader: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 },
  sectionTitle:  { fontWeight: 600, fontSize: 14, color: '#aaa' },

  toolbar:     { display: 'flex', alignItems: 'center', gap: 12, marginBottom: '1.5rem', flexWrap: 'wrap' },
  tabs:        { display: 'flex', gap: 4 },
  tab:         { padding: '6px 14px', background: 'transparent', border: '1px solid #333', borderRadius: 20, cursor: 'pointer', color: '#888', fontSize: 13, display: 'flex', alignItems: 'center', gap: 6 },
  tabActive:   { background: '#1e2a3a', borderColor: '#4a9eff', color: '#4a9eff' },
  tabCount:    { background: '#333', borderRadius: 10, padding: '1px 6px', fontSize: 11 },
  searchInput: { padding: '6px 12px', background: '#1a1a2a', border: '1px solid #333', borderRadius: 6, color: '#e0e0e0', fontSize: 13, width: 220, outline: 'none' },

  grid:        { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 16 },

  card:        { background: '#16161f', border: '1px solid #2a2a3a', borderRadius: 10, overflow: 'hidden', display: 'flex', flexDirection: 'column' },
  thumb:       { position: 'relative', height: 140, background: '#0a0a12', flexShrink: 0 },
  thumbImg:    { width: '100%', height: '100%', objectFit: 'cover', display: 'block' },
  thumbPlaceholder: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' },
  typeIcon:    { fontSize: 36, opacity: 0.5 },
  typeBadge:   { position: 'absolute', top: 8, right: 8, padding: '2px 8px', borderRadius: 4, fontSize: 11, fontWeight: 600, color: '#fff' },
  uploadOverlay: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.6)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: '#fff' },

  cardBody:    { padding: '10px 12px', flex: 1 },
  filename:    { fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', marginBottom: 4 },
  meta:        { display: 'flex', gap: 8, flexWrap: 'wrap', fontSize: 11, color: '#666' },
  desc:        { fontSize: 11, color: '#888', marginTop: 4, overflow: 'hidden', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' },

  actions:     { display: 'flex', borderTop: '1px solid #2a2a3a', padding: '8px 10px', gap: 6 },
  btn:         { flex: 1, padding: '5px 0', background: '#1e1e2e', border: '1px solid #333', borderRadius: 5, color: '#aaa', cursor: 'pointer', fontSize: 12 },
  btnDanger:   { background: '#3a1a1a', borderColor: '#7a3030', color: '#e06c4a' },

  removeBtn:   { position: 'absolute', top: 6, left: 6, width: 22, height: 22, background: 'rgba(0,0,0,0.7)', border: 'none', borderRadius: '50%', color: '#fff', cursor: 'pointer', fontSize: 14, display: 'flex', alignItems: 'center', justifyContent: 'center', lineHeight: 1 },

  errorBox:    { position: 'relative', background: '#2a1010', border: '1px solid #7a3030', borderRadius: 8, padding: '10px 40px 10px 14px', marginBottom: 16, color: '#e06c4a', fontSize: 13 },
  errorDismiss:{ position: 'absolute', top: 8, right: 10, background: 'none', border: 'none', color: '#e06c4a', cursor: 'pointer', fontSize: 16 },

  thumbHover:     { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: 0 },
  thumbHoverIcon: { fontSize: 32, color: '#fff', textShadow: '0 2px 8px rgba(0,0,0,0.8)' },

  // Attribution — card
  cardAttribution: { display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 6, alignItems: 'center' },
  cardAttrItem:    { fontSize: 10, color: '#777' },
  licenseBadge:    { fontSize: 10, background: '#1e2a1e', border: '1px solid #2a4a2a', color: '#6cb86e', padding: '1px 6px', borderRadius: 3 },
  sourceLink:      { fontSize: 10, color: '#4a9eff', textDecoration: 'none' },

  // Inline edit form
  editForm:  { marginTop: 8, borderTop: '1px solid #2a2a3a', paddingTop: 8, display: 'flex', flexDirection: 'column', gap: 4 },
  editRow:   { display: 'flex', flexDirection: 'column', gap: 2 },
  editLabel: { fontSize: 10, color: '#666' },
  editInput: { padding: '4px 8px', background: '#0f0f17', border: '1px solid #333', borderRadius: 4, color: '#e0e0e0', fontSize: 12, outline: 'none' },

  modalOverlay:       { position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.85)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '2rem' },
  modalBox:           { position: 'relative', background: '#16161f', borderRadius: 12, overflow: 'hidden', maxWidth: '90vw', maxHeight: '90vh', display: 'flex', flexDirection: 'column', boxShadow: '0 24px 80px rgba(0,0,0,0.8)' },
  modalClose:         { position: 'absolute', top: 12, right: 14, zIndex: 10, background: 'rgba(0,0,0,0.6)', border: 'none', color: '#fff', width: 32, height: 32, borderRadius: '50%', cursor: 'pointer', fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center' },
  modalMedia:         { flex: 1, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#0a0a12', minHeight: 200 },
  modalVideo:         { maxWidth: '90vw', maxHeight: '75vh', display: 'block' },
  modalImage:         { maxWidth: '90vw', maxHeight: '75vh', objectFit: 'contain', display: 'block' },
  modalAudioWrap:     { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 20, padding: '3rem 4rem' },
  modalAudioIcon:     { fontSize: 64, opacity: 0.3 },
  modalInfo:          { padding: '14px 18px', borderTop: '1px solid #2a2a3a', display: 'flex', flexDirection: 'column', gap: 6 },
  modalFilename:      { fontWeight: 600, fontSize: 15, color: '#e0e0e0', wordBreak: 'break-all' },
  // Attribution — modal
  modalAttribution:   { display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'center', marginTop: 4, paddingTop: 8, borderTop: '1px solid #2a2a3a', fontSize: 12, color: '#888' },
  modalLicenseBadge:  { background: '#1e2a1e', border: '1px solid #2a4a2a', color: '#6cb86e', padding: '2px 8px', borderRadius: 4, fontSize: 12 },
  modalSourceLink:    { color: '#4a9eff', textDecoration: 'none', fontWeight: 500 },
};
