// cast-screens.jsx — Cast Library, Cast Detail, Video Detail
// Plus a Smart Collections strip used by Library.

const { useState, useMemo } = React;

// ─────────────────────────────────────────────────────────────
// Compute derived per-user casts from the live videos list.
// Used as fallback when `casts` collection is empty (legacy/sample).
// ─────────────────────────────────────────────────────────────
function deriveCastsFromVideos(items) {
  const m = new Map();   // key -> cast object
  for (const v of items || []) {
    for (const name of (v.actresses || [])) {
      const key = window.VHCast.normalizeCastName(name);
      if (!key) continue;
      if (!m.has(key)) {
        m.set(key, {
          id: 'derived:' + key,
          displayName: name,
          normalizedName: key,
          aliases: [],
          avatarUrl: '',
          favorite: false,
          note: '',
          videoCount: 0, favoriteCount: 0, watchedCount: 0, wantCount: 0,
          _videos: [],
        });
      }
      const c = m.get(key);
      c._videos.push(v);
      c.videoCount++;
      if (v.status === 'favorite') c.favoriteCount++;
      if (v.status === 'watched')  c.watchedCount++;
      if (v.status === 'want' || v.status === 'want_to_watch') c.wantCount++;
    }
  }
  return [...m.values()].sort((a,b) => b.videoCount - a.videoCount);
}

// Given a stored casts collection + video list, return enriched casts
// (with `_videos` attached) suitable for rendering.
function enrichCasts(storedCasts, items) {
  if (!storedCasts || storedCasts.length === 0) return deriveCastsFromVideos(items);
  const byId = new Map(storedCasts.map(c => [c.id, { ...c, _videos: [] }]));
  const byKey = new Map(storedCasts.map(c => [c.normalizedName, c.id]));
  for (const v of items || []) {
    const ids = new Set(v.castIds || []);
    // also resolve via name fallback
    for (const name of (v.actresses || [])) {
      const k = window.VHCast.normalizeCastName(name);
      if (byKey.has(k)) ids.add(byKey.get(k));
    }
    for (const id of ids) {
      const c = byId.get(id);
      if (c) c._videos.push(v);
    }
  }
  return [...byId.values()].sort((a,b) => (b._videos.length || b.videoCount || 0) - (a._videos.length || a.videoCount || 0));
}

// ═══════════════════════════════════════════════════════════════
// CAST LIBRARY — grid of cast cards
// ═══════════════════════════════════════════════════════════════
function CastLibraryScreen({ items, casts, locked, accent, onOpenCast }) {
  const enriched = useMemo(() => enrichCasts(casts, items), [casts, items]);
  const [filter, setFilter] = useState('all');  // all | favorite | want

  const filtered = useMemo(() => {
    if (filter === 'all') return enriched;
    if (filter === 'favorite') return enriched.filter(c => c.favorite || c.favoriteCount > 0);
    if (filter === 'want')     return enriched.filter(c => c.wantCount > 0);
    return enriched;
  }, [enriched, filter]);

  return (
    <div style={{ paddingBottom: 140 }}>
      <window.TopBar
        topPad={locked.topPad}
        title="Cast"
        subtitle={`${enriched.length} saved`}
        locked={locked.value}
        onToggleLock={locked.toggle}
        accent={accent}
      />

      <div style={{ display: 'flex', gap: 8, padding: '4px 16px 14px', overflowX: 'auto', scrollbarWidth: 'none' }}>
        {[
          { id: 'all',      label: `All · ${enriched.length}` },
          { id: 'favorite', label: `Favorite` },
          { id: 'want',     label: `With wants` },
        ].map(f => (
          <window.Chip key={f.id} active={filter === f.id} onClick={() => setFilter(f.id)} accent={accent}>
            {f.label}
          </window.Chip>
        ))}
      </div>

      {filtered.length === 0 ? (
        <div style={{ padding: '60px 24px', textAlign: 'center', color: window.VH_DIM }}>
          <div style={{ color: window.VH_TEXT, fontSize: 15, fontWeight: 600, marginBottom: 4 }}>
            {locked.signedIn ? 'No cast yet' : 'Sign in to see your cast'}
          </div>
          <div style={{ fontSize: 13, lineHeight: 1.5 }}>
            {locked.signedIn ? 'Save a video — cast appear here automatically.' : 'Your cast list is private.'}
          </div>
        </div>
      ) : (
        <div className="vh-cast-grid">
          {filtered.map(c => (
            <CastCard key={c.id} cast={c} locked={locked.value} accent={accent}
              onClick={() => onOpenCast(c.id)}/>
          ))}
        </div>
      )}
    </div>
  );
}

function CastCard({ cast, locked, accent, onClick }) {
  const hue = window.hashHue(cast.normalizedName || cast.displayName || cast.id);
  const grad = `radial-gradient(120% 90% at 25% 20%, oklch(0.55 0.18 ${hue}), oklch(0.18 0.06 ${(hue+30)%360}))`;
  const initials = (cast.displayName || '?').split(' ').slice(0,2).map(s => s[0]).join('').toUpperCase();
  const total = cast._videos?.length ?? cast.videoCount ?? 0;
  return (
    <button onClick={onClick} className="vh-tap vh-card" style={{
      position: 'relative', textAlign: 'left',
      borderRadius: 14, padding: 12, cursor: 'pointer',
      background: window.VH_SURFACE, border: `0.5px solid ${window.VH_HAIRLINE}`,
      fontFamily: 'inherit', color: window.VH_TEXT,
      display: 'flex', flexDirection: 'column', gap: 10,
    }}>
      {/* avatar */}
      <div style={{
        width: '100%', aspectRatio: '1 / 1', borderRadius: 12,
        background: cast.avatarUrl && !locked ? `#000 url(${cast.avatarUrl}) center/cover` : grad,
        position: 'relative', overflow: 'hidden',
        filter: locked ? 'blur(8px)' : 'none',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: 'rgba(255,255,255,0.85)', fontSize: 30, fontWeight: 600,
      }}>
        {!cast.avatarUrl && initials}
        {cast.favorite && !locked && (
          <div style={{
            position: 'absolute', top: 6, right: 6,
            width: 22, height: 22, borderRadius: 99,
            background: 'rgba(0,0,0,0.55)', backdropFilter: 'blur(6px)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <svg width="11" height="10" viewBox="0 0 11 10" fill={accent}>
              <path d="M5.5 9.2S.5 6.2.5 3.2C.5 1.7 1.7.5 3.2.5c.9 0 1.7.4 2.3 1.1C6.1.9 6.9.5 7.8.5c1.5 0 2.7 1.2 2.7 2.7 0 3-5 6-5 6z"/>
            </svg>
          </div>
        )}
      </div>
      <div>
        <div style={{
          fontSize: 14, fontWeight: 600,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          filter: locked ? 'blur(5px)' : 'none',
        }}>{cast.displayName}</div>
        <div style={{ fontSize: 11.5, color: window.VH_DIM, marginTop: 3, display: 'flex', gap: 8 }}>
          <span><strong style={{ color: window.VH_TEXT, fontWeight: 700 }}>{total}</strong> saved</span>
          {cast.favoriteCount > 0 && <span>· {cast.favoriteCount} fav</span>}
        </div>
      </div>
    </button>
  );
}

// ═══════════════════════════════════════════════════════════════
// CAST DETAIL — header + stats + filterable list
// ═══════════════════════════════════════════════════════════════
function CastDetailScreen({ castId, items, casts, locked, accent, uid, onBack, onOpenVideo }) {
  const enriched = useMemo(() => enrichCasts(casts, items), [casts, items]);
  const cast = enriched.find(c => c.id === castId) || enriched[0];
  if (!cast) {
    return <div style={{ padding: 40, color: window.VH_DIM, textAlign: 'center' }}>Cast not found.</div>;
  }

  const [filter, setFilter] = useState('all');
  const [sort, setSort]     = useState('added');

  const filtered = useMemo(() => {
    let list = [...(cast._videos || [])];
    if (filter !== 'all') list = list.filter(v => v.status === filter || (filter === 'want' && v.status === 'want_to_watch'));
    if (sort === 'rating') list.sort((a,b) => (b.rating||0) - (a.rating||0));
    if (sort === 'release') list.sort((a,b) => (b.releaseDate||'').localeCompare(a.releaseDate||''));
    if (sort === 'added')   list.sort((a,b) => (b.createdAt||0) - (a.createdAt||0));
    return list;
  }, [cast, filter, sort]);

  const ratings = (cast._videos || []).filter(v => v.rating);
  const avgRating = ratings.length ? (ratings.reduce((s,v) => s + v.rating, 0) / ratings.length).toFixed(1) : '—';
  const total = cast._videos?.length || 0;

  const hue = window.hashHue(cast.normalizedName || cast.displayName);
  const grad = `radial-gradient(120% 90% at 25% 20%, oklch(0.55 0.18 ${hue}), oklch(0.18 0.06 ${(hue+30)%360}))`;
  const initials = (cast.displayName || '?').split(' ').slice(0,2).map(s => s[0]).join('').toUpperCase();

  const [popping, setPopping] = useState(false);
  const toggleFavorite = async () => {
    if (!uid || cast.id.startsWith('derived:')) return;
    setPopping(true);
    setTimeout(() => setPopping(false), 450);
    await window.VHFirebase.updateCast(uid, cast.id, { favorite: !cast.favorite });
  };

  return (
    <div style={{ paddingBottom: 140, animation: 'vhFadeIn 240ms ease-out' }}>
      {/* Back row */}
      <div style={{ paddingTop: locked.topPad - 4, padding: `${locked.topPad - 4}px 12px 6px`, display: 'flex', alignItems: 'center', gap: 8 }}>
        <button onClick={onBack} style={{
          width: 36, height: 36, borderRadius: 99, border: 'none', cursor: 'pointer',
          background: 'rgba(255,255,255,0.07)', color: window.VH_TEXT,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="13" height="13" viewBox="0 0 14 14"><path d="M9 2L3 7l6 5" stroke="currentColor" strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </button>
        <div style={{ flex: 1, fontSize: 12, color: window.VH_DIM, letterSpacing: 0.5, textTransform: 'uppercase', fontWeight: 600 }}>
          Cast detail
        </div>
        <button onClick={locked.toggle} style={{
          width: 36, height: 36, borderRadius: 99, border: 'none', cursor: 'pointer',
          background: locked.value ? accent : 'rgba(255,255,255,0.07)',
          color: locked.value ? '#fff' : window.VH_TEXT,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="13" height="15" viewBox="0 0 14 16" fill="none">
            <rect x="2" y="7" width="10" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.6"/>
            <path d={locked.value ? "M4 7V4.5a3 3 0 016 0V7" : "M4 7V4.5a3 3 0 016 0"} stroke="currentColor" strokeWidth="1.6"/>
          </svg>
        </button>
      </div>

      {/* Hero */}
      <div style={{ padding: '0 16px' }}>
        <div style={{
          position: 'relative', borderRadius: 18, overflow: 'hidden',
          padding: 18,
          background: `linear-gradient(135deg, ${window.VH_SURFACE_HI} 0%, ${window.VH_SURFACE} 100%)`,
          border: `0.5px solid ${window.VH_HAIRLINE}`,
        }}>
          <div style={{
            position: 'absolute', inset: 0,
            background: `radial-gradient(60% 60% at 100% 0%, oklch(0.55 0.12 ${hue} / 0.30), transparent 65%)`,
            pointerEvents: 'none',
          }}/>
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, position: 'relative' }}>
            <div style={{
              width: 72, height: 72, borderRadius: 99,
              background: cast.avatarUrl && !locked.value ? `#000 url(${cast.avatarUrl}) center/cover` : grad,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#fff', fontSize: 24, fontWeight: 600, flexShrink: 0,
              filter: locked.value ? 'blur(10px)' : 'none',
            }}>{!cast.avatarUrl && initials}</div>
            <div style={{ minWidth: 0, flex: 1 }}>
              <div style={{ fontSize: 11, letterSpacing: 1.2, textTransform: 'uppercase', color: window.VH_DIM2, fontWeight: 600 }}>Cast</div>
              <div style={{
                fontSize: 22, fontWeight: 700, color: window.VH_TEXT, marginTop: 2,
                letterSpacing: -0.3, filter: locked.value ? 'blur(8px)' : 'none',
                overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
              }}>{cast.displayName}</div>
              <div style={{ fontSize: 12, color: window.VH_DIM, marginTop: 3 }}>
                Avg rating <span style={{ color: window.VH_TEXT, fontWeight: 600 }}>{avgRating}</span>
                {cast.aliases?.length > 0 && <> · {cast.aliases.length} alias{cast.aliases.length > 1 ? 'es' : ''}</>}
              </div>
            </div>
            <button onClick={toggleFavorite} disabled={cast.id.startsWith('derived:')}
              className={popping ? 'vh-heart-pop vh-tap' : 'vh-tap'}
              style={{
                width: 38, height: 38, borderRadius: 99,
                cursor: cast.id.startsWith('derived:') ? 'default' : 'pointer',
                background: cast.favorite ? `${accent}22` : 'rgba(255,255,255,0.06)',
                border: `0.5px solid ${cast.favorite ? accent + '88' : window.VH_HAIRLINE}`,
                color: cast.favorite ? accent : window.VH_DIM,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                flexShrink: 0,
              }}>
              <svg width="15" height="14" viewBox="0 0 11 10" fill="currentColor">
                <path d="M5.5 9.2S.5 6.2.5 3.2C.5 1.7 1.7.5 3.2.5c.9 0 1.7.4 2.3 1.1C6.1.9 6.9.5 7.8.5c1.5 0 2.7 1.2 2.7 2.7 0 3-5 6-5 6z"/>
              </svg>
            </button>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 8, marginTop: 16, position: 'relative' }}>
            <Stat label="Total"   value={total}/>
            <Stat label="Watched" value={cast.watchedCount || 0}/>
            <Stat label="Want"    value={cast.wantCount || 0}/>
            <Stat label="Fav"     value={cast.favoriteCount || 0}/>
          </div>
        </div>
      </div>

      {/* filter + sort */}
      <div style={{ display: 'flex', gap: 8, padding: '14px 16px 10px', overflowX: 'auto', scrollbarWidth: 'none' }}>
        {[
          { id: 'all',           label: 'All' },
          { id: 'want_to_watch', label: 'Want' },
          { id: 'favorite',      label: 'Favorite' },
          { id: 'watched',       label: 'Watched' },
          { id: 'rewatch',       label: 'Rewatch' },
        ].map(f => (
          <window.Chip key={f.id} active={filter === f.id} onClick={() => setFilter(f.id)} accent={accent}>
            {f.label}
          </window.Chip>
        ))}
        <window.Chip onClick={() => {
          const order = ['added', 'release', 'rating'];
          setSort(order[(order.indexOf(sort) + 1) % order.length]);
        }} accent={accent} active>
          Sort: {{ added: 'Added', release: 'Release', rating: 'Rating' }[sort]}
        </window.Chip>
      </div>

      {filtered.length === 0 ? (
        <div style={{ padding: '40px 24px', textAlign: 'center', color: window.VH_DIM, fontSize: 13 }}>
          No items match.
        </div>
      ) : (
        <window.RowList items={filtered} locked={locked.value} accent={accent} onClick={onOpenVideo}/>
      )}
    </div>
  );
}

function Stat({ label, value }) {
  return (
    <div style={{
      padding: '10px 8px', borderRadius: 12,
      background: 'rgba(255,255,255,0.03)',
      border: `0.5px solid ${window.VH_HAIRLINE}`,
      textAlign: 'center',
    }}>
      <div style={{ fontSize: 19, fontWeight: 700, color: window.VH_TEXT, letterSpacing: -0.3 }}>{value}</div>
      <div style={{ fontSize: 10, color: window.VH_DIM, textTransform: 'uppercase', letterSpacing: 0.8, marginTop: 2, fontWeight: 600 }}>{label}</div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// CATEGORY DETAIL — header + filterable list
// ═══════════════════════════════════════════════════════════════
function CategoryDetailScreen({ categoryId, categoryName, items, categories, locked, accent, onBack, onOpenVideo }) {
  const normCat = (n) => window.VHCast.normalizeCollectionName(n);

  // Find category info
  const cat = (categories || []).find(c => c.id === categoryId || c.normalizedName === categoryId);
  const displayName = cat?.displayName || categoryName || categoryId;

  // Filter videos with this category
  const catNorm = cat ? cat.normalizedName : normCat(categoryId);
  const catVideos = useMemo(() => {
    return (items || []).filter(v =>
      (v.categoryIds || []).includes(cat?.id) ||
      (v.categories || []).some(c => normCat(c) === catNorm)
    );
  }, [items, cat, catNorm]);

  const [filter, setFilter] = useState('all');
  const [sort, setSort] = useState('added');

  const filtered = useMemo(() => {
    let list = [...catVideos];
    if (filter !== 'all') list = list.filter(v => v.status === filter || (filter === 'want' && v.status === 'want_to_watch'));
    if (sort === 'rating')  list.sort((a,b) => (b.rating||0) - (a.rating||0));
    if (sort === 'release') list.sort((a,b) => (b.releaseDate||'').localeCompare(a.releaseDate||''));
    if (sort === 'added')   list.sort((a,b) => (b.createdAt||0) - (a.createdAt||0));
    return list;
  }, [catVideos, filter, sort]);

  return (
    <div style={{ paddingBottom: 140, animation: 'vhFadeIn 240ms ease-out' }}>
      <div style={{ paddingTop: locked.topPad - 4, padding: `${locked.topPad - 4}px 12px 6px`, display: 'flex', alignItems: 'center', gap: 8 }}>
        <button onClick={onBack} style={{
          width: 36, height: 36, borderRadius: 99, border: 'none', cursor: 'pointer',
          background: 'rgba(255,255,255,0.07)', color: window.VH_TEXT,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="13" height="13" viewBox="0 0 14 14"><path d="M9 2L3 7l6 5" stroke="currentColor" strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </button>
        <div style={{ flex: 1, fontSize: 12, color: window.VH_DIM, letterSpacing: 0.5, textTransform: 'uppercase', fontWeight: 600 }}>
          Category
        </div>
      </div>

      {/* Hero */}
      <div style={{ padding: '0 16px' }}>
        <div style={{
          borderRadius: 18, padding: 18,
          background: `linear-gradient(135deg, ${window.VH_SURFACE_HI} 0%, ${window.VH_SURFACE} 100%)`,
          border: `0.5px solid ${window.VH_HAIRLINE}`,
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <div style={{
              width: 48, height: 48, borderRadius: 14, flexShrink: 0,
              background: 'rgba(168,85,247,0.18)', border: '0.5px solid rgba(168,85,247,0.4)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <svg width="22" height="22" viewBox="0 0 22 22" fill="none">
                <rect x="2" y="5" width="18" height="13" rx="3" stroke="#a855f7" strokeWidth="1.5"/>
                <path d="M7 5V3.5a2 2 0 014 0V5" stroke="#a855f7" strokeWidth="1.5"/>
                <path d="M6 11h10M6 14.5h7" stroke="#a855f7" strokeWidth="1.3" strokeLinecap="round"/>
              </svg>
            </div>
            <div style={{ minWidth: 0, flex: 1 }}>
              <div style={{ fontSize: 11, letterSpacing: 1.2, textTransform: 'uppercase', color: window.VH_DIM2, fontWeight: 600 }}>Category</div>
              <div style={{ fontSize: 22, fontWeight: 700, color: window.VH_TEXT, marginTop: 2, letterSpacing: -0.3 }}>{displayName}</div>
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, marginTop: 16 }}>
            <Stat label="Total"   value={catVideos.length}/>
            <Stat label="Watched" value={catVideos.filter(v => v.status === 'watched').length}/>
            <Stat label="Fav"     value={catVideos.filter(v => v.status === 'favorite').length}/>
          </div>
        </div>
      </div>

      <div style={{ display: 'flex', gap: 8, padding: '14px 16px 10px', overflowX: 'auto', scrollbarWidth: 'none' }}>
        {[
          { id: 'all',           label: 'All' },
          { id: 'want_to_watch', label: 'Want' },
          { id: 'favorite',      label: 'Favorite' },
          { id: 'watched',       label: 'Watched' },
          { id: 'rewatch',       label: 'Rewatch' },
        ].map(f => (
          <window.Chip key={f.id} active={filter === f.id} onClick={() => setFilter(f.id)} accent={accent}>{f.label}</window.Chip>
        ))}
        <window.Chip onClick={() => {
          const order = ['added', 'release', 'rating'];
          setSort(order[(order.indexOf(sort) + 1) % order.length]);
        }} accent={accent} active>
          Sort: {{ added: 'Added', release: 'Release', rating: 'Rating' }[sort]}
        </window.Chip>
      </div>

      {filtered.length === 0 ? (
        <div style={{ padding: '40px 24px', textAlign: 'center', color: window.VH_DIM, fontSize: 13 }}>ไม่มีรายการ</div>
      ) : (
        <window.RowList items={filtered} locked={locked.value} accent={accent} onClick={onOpenVideo}/>
      )}
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// STUDIO DETAIL — header + filterable list
// ═══════════════════════════════════════════════════════════════
function StudioDetailScreen({ studioId, studioName, items, studios, locked, accent, onBack, onOpenVideo }) {
  const normStudio = (n) => window.VHCast.normalizeCollectionName(n);

  const studio = (studios || []).find(s => s.id === studioId || s.normalizedName === studioId);
  const displayName = studio?.displayName || studioName || studioId;
  const sNorm = studio ? studio.normalizedName : normStudio(studioId);

  const studioVideos = useMemo(() => {
    return (items || []).filter(v =>
      (v.studioId && v.studioId === studio?.id) ||
      normStudio(v.studio) === sNorm
    );
  }, [items, studio, sNorm]);

  const [filter, setFilter] = useState('all');
  const [sort, setSort] = useState('added');

  const filtered = useMemo(() => {
    let list = [...studioVideos];
    if (filter !== 'all') list = list.filter(v => v.status === filter || (filter === 'want' && v.status === 'want_to_watch'));
    if (sort === 'rating')  list.sort((a,b) => (b.rating||0) - (a.rating||0));
    if (sort === 'release') list.sort((a,b) => (b.releaseDate||'').localeCompare(a.releaseDate||''));
    if (sort === 'added')   list.sort((a,b) => (b.createdAt||0) - (a.createdAt||0));
    return list;
  }, [studioVideos, filter, sort]);

  const hue = window.hashHue(sNorm);

  return (
    <div style={{ paddingBottom: 140, animation: 'vhFadeIn 240ms ease-out' }}>
      <div style={{ paddingTop: locked.topPad - 4, padding: `${locked.topPad - 4}px 12px 6px`, display: 'flex', alignItems: 'center', gap: 8 }}>
        <button onClick={onBack} style={{
          width: 36, height: 36, borderRadius: 99, border: 'none', cursor: 'pointer',
          background: 'rgba(255,255,255,0.07)', color: window.VH_TEXT,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <svg width="13" height="13" viewBox="0 0 14 14"><path d="M9 2L3 7l6 5" stroke="currentColor" strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </button>
        <div style={{ flex: 1, fontSize: 12, color: window.VH_DIM, letterSpacing: 0.5, textTransform: 'uppercase', fontWeight: 600 }}>Studio</div>
      </div>

      <div style={{ padding: '0 16px' }}>
        <div style={{
          position: 'relative', borderRadius: 18, padding: 18, overflow: 'hidden',
          background: `linear-gradient(135deg, ${window.VH_SURFACE_HI} 0%, ${window.VH_SURFACE} 100%)`,
          border: `0.5px solid ${window.VH_HAIRLINE}`,
        }}>
          <div style={{
            position: 'absolute', inset: 0,
            background: `radial-gradient(60% 60% at 100% 0%, oklch(0.55 0.12 ${hue} / 0.25), transparent 65%)`,
            pointerEvents: 'none',
          }}/>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, position: 'relative' }}>
            <div style={{
              width: 48, height: 48, borderRadius: 14, flexShrink: 0,
              background: `radial-gradient(120% 90% at 25% 20%, oklch(0.55 0.18 ${hue}), oklch(0.18 0.06 ${(hue+30)%360}))`,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#fff', fontSize: 18, fontWeight: 700,
            }}>
              {(displayName || '?')[0].toUpperCase()}
            </div>
            <div style={{ minWidth: 0, flex: 1 }}>
              <div style={{ fontSize: 11, letterSpacing: 1.2, textTransform: 'uppercase', color: window.VH_DIM2, fontWeight: 600 }}>Studio</div>
              <div style={{ fontSize: 22, fontWeight: 700, color: window.VH_TEXT, marginTop: 2, letterSpacing: -0.3 }}>{displayName}</div>
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 8, marginTop: 16, position: 'relative' }}>
            <Stat label="Total"   value={studioVideos.length}/>
            <Stat label="Watched" value={studioVideos.filter(v => v.status === 'watched').length}/>
            <Stat label="Fav"     value={studioVideos.filter(v => v.status === 'favorite').length}/>
          </div>
        </div>
      </div>

      <div style={{ display: 'flex', gap: 8, padding: '14px 16px 10px', overflowX: 'auto', scrollbarWidth: 'none' }}>
        {[
          { id: 'all',           label: 'All' },
          { id: 'want_to_watch', label: 'Want' },
          { id: 'favorite',      label: 'Favorite' },
          { id: 'watched',       label: 'Watched' },
        ].map(f => (
          <window.Chip key={f.id} active={filter === f.id} onClick={() => setFilter(f.id)} accent={accent}>{f.label}</window.Chip>
        ))}
        <window.Chip onClick={() => {
          const order = ['added', 'release', 'rating'];
          setSort(order[(order.indexOf(sort) + 1) % order.length]);
        }} accent={accent} active>
          Sort: {{ added: 'Added', release: 'Release', rating: 'Rating' }[sort]}
        </window.Chip>
      </div>

      {filtered.length === 0 ? (
        <div style={{ padding: '40px 24px', textAlign: 'center', color: window.VH_DIM, fontSize: 13 }}>ไม่มีรายการ</div>
      ) : (
        <window.RowList items={filtered} locked={locked.value} accent={accent} onClick={onOpenVideo}/>
      )}
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// VIDEO DETAIL — full info + "More from this cast"
// ═══════════════════════════════════════════════════════════════
function VideoDetailScreen({ videoId, items, casts, categories, studios, locked, accent, uid, onBack, onOpenCast, onOpenVideo, onOpenCategory, onOpenStudio }) {
  const it = items.find(v => v.id === videoId);
  if (!it) {
    return (
      <div style={{ padding: '60px 24px', textAlign: 'center', color: window.VH_DIM }}>
        Item not found. <button onClick={onBack} style={{ marginLeft: 8, color: accent, background: 'transparent', border: 'none', cursor: 'pointer', fontFamily: 'inherit' }}>Back</button>
      </div>
    );
  }

  const normCat = (n) => window.VHCast.normalizeCollectionName(n);

  const enriched = useMemo(() => enrichCasts(casts, items), [casts, items]);
  const linkedCasts = useMemo(() => {
    const ids = new Set(it.castIds || []);
    const byKey = new Map(enriched.map(c => [c.normalizedName, c]));
    const out = [];
    for (const cid of ids) {
      const c = enriched.find(x => x.id === cid);
      if (c) out.push(c);
    }
    for (const name of it.actresses || []) {
      const c = byKey.get(window.VHCast.normalizeCastName(name));
      if (c && !out.includes(c)) out.push(c);
    }
    return out;
  }, [it, enriched]);

  const related = useMemo(() => {
    const set = new Map();
    for (const c of linkedCasts) {
      for (const v of c._videos || []) {
        if (v.id !== it.id) set.set(v.id, v);
      }
    }
    return [...set.values()].slice(0, 12);
  }, [linkedCasts, it]);

  // Category links
  const linkedCategories = useMemo(() => {
    const catList = categories || [];
    const catIds = new Set(it.categoryIds || []);
    const out = [];
    for (const cid of catIds) {
      const c = catList.find(x => x.id === cid);
      if (c) out.push(c);
    }
    // Fallback by name
    for (const name of (it.categories || [])) {
      const norm = normCat(name);
      const c = catList.find(x => x.normalizedName === norm);
      if (c && !out.includes(c)) out.push(c);
      else if (!c) out.push({ id: 'derived:' + norm, displayName: name, normalizedName: norm, videoCount: 0 });
    }
    return out;
  }, [it, categories]);

  // Studio link
  const linkedStudio = useMemo(() => {
    if (!it.studioId && !it.studio) return null;
    const studioList = studios || [];
    return studioList.find(s => s.id === it.studioId || normCat(s.displayName) === normCat(it.studio)) || null;
  }, [it, studios]);

  // More in same category
  const relatedByCategory = useMemo(() => {
    if (!linkedCategories.length) return [];
    const catIds = new Set(linkedCategories.map(c => c.id));
    const catNorms = new Set(linkedCategories.map(c => c.normalizedName));
    const set = new Map();
    for (const v of items) {
      if (v.id === it.id) continue;
      const matches = (v.categoryIds || []).some(cid => catIds.has(cid)) ||
        (v.categories || []).some(c => catNorms.has(normCat(c)));
      if (matches) set.set(v.id, v);
    }
    return [...set.values()].slice(0, 12);
  }, [linkedCategories, items, it]);

  const setStatus = async (status) => {
    if (!uid) return;
    await window.VHFirebase.updateVideo(uid, it.id, {
      status,
      watchedAt: status === 'watched' ? Date.now() : it.watchedAt || null,
    });
  };
  const setRating = async (n) => {
    if (!uid) return;
    await window.VHFirebase.updateVideo(uid, it.id, { rating: n === it.rating ? 0 : n });
  };

  const bg = window.coverGradient(it.code || 'NONE');

  return (
    <div style={{ paddingBottom: 60, animation: 'vhFadeIn 240ms ease-out' }}>
      {/* Hero cover (full width) */}
      <div style={{ position: 'relative', height: 340, overflow: 'hidden' }}>
        <div style={{
          position: 'absolute', inset: 0,
          background: it.coverUrl && !locked.value ? `#000 url(${it.coverUrl}) center/cover` : bg,
        }}/>
        <div style={{
          position: 'absolute', inset: 0,
          background: 'linear-gradient(180deg, rgba(10,10,12,0.55) 0%, rgba(10,10,12,0.15) 35%, rgba(10,10,12,1) 100%)',
        }}/>
        {locked.value && (
          <div style={{ position: 'absolute', inset: 0, backdropFilter: 'blur(14px)', WebkitBackdropFilter: 'blur(14px)' }}/>
        )}
        {/* top bar over cover */}
        <div style={{ position: 'absolute', top: 56, left: 12, right: 12, display: 'flex', gap: 8 }}>
          <button onClick={onBack} style={{
            width: 36, height: 36, borderRadius: 99, border: 'none', cursor: 'pointer',
            background: 'rgba(0,0,0,0.55)', color: '#fff',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            backdropFilter: 'blur(10px)',
          }}>
            <svg width="13" height="13" viewBox="0 0 14 14"><path d="M9 2L3 7l6 5" stroke="currentColor" strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </button>
          <div style={{ flex: 1 }}/>
          <button onClick={locked.toggle} style={{
            width: 36, height: 36, borderRadius: 99, border: 'none', cursor: 'pointer',
            background: 'rgba(0,0,0,0.55)', color: '#fff',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            backdropFilter: 'blur(10px)',
          }}>
            <svg width="13" height="15" viewBox="0 0 14 16" fill="none">
              <rect x="2" y="7" width="10" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.6"/>
              <path d={locked.value ? "M4 7V4.5a3 3 0 016 0V7" : "M4 7V4.5a3 3 0 016 0"} stroke="currentColor" strokeWidth="1.6"/>
            </svg>
          </button>
        </div>
      </div>

      <div style={{ padding: '0 20px', marginTop: -56, position: 'relative' }}>
        <div style={{
          fontFamily: 'ui-monospace, "SF Mono", Menlo, monospace',
          fontSize: 12, fontWeight: 600, letterSpacing: 1,
          color: window.VH_DIM,
        }}>{locked.value ? '••••••' : it.code}</div>
        <div style={{
          fontSize: 24, fontWeight: 700, color: window.VH_TEXT, marginTop: 4,
          letterSpacing: -0.4, lineHeight: 1.2,
          filter: locked.value ? 'blur(8px)' : 'none',
        }}>{it.title}</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 10 }}>
          <window.StatusPill status={it.status}/>
          <window.RatingDots value={it.rating || 0} accent={accent}/>
        </div>

        {/* Studio chip */}
        {it.studio && (
          <div style={{ marginTop: 10 }}>
            <button onClick={() => onOpenStudio?.(linkedStudio?.id || normCat(it.studio), it.studio)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '5px 10px 5px 8px', borderRadius: 99,
              background: `${accent}12`, border: `0.5px solid ${accent}44`,
              color: window.VH_TEXT, fontSize: 12, fontWeight: 500,
              fontFamily: 'inherit', cursor: 'pointer',
              filter: locked.value ? 'blur(5px)' : 'none',
            }}>
              <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
                <rect x="1" y="4" width="8" height="5" rx="1" stroke={accent} strokeWidth="1.2"/>
                <path d="M3 4V3a2 2 0 014 0v1" stroke={accent} strokeWidth="1.2"/>
              </svg>
              {it.studio}
              {linkedStudio && (
                <span style={{
                  padding: '1px 6px', borderRadius: 99,
                  background: `${accent}22`, color: accent, fontSize: 10.5, fontWeight: 600,
                }}>{linkedStudio.videoCount || 0}</span>
              )}
            </button>
          </div>
        )}

        {/* Cast chips */}
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 10 }}>
          {linkedCasts.map(c => (
            <button key={c.id} onClick={() => onOpenCast(c.id)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 7,
              padding: '5px 5px 5px 9px', borderRadius: 99,
              background: 'rgba(255,255,255,0.06)',
              border: `0.5px solid ${window.VH_HAIRLINE}`,
              color: window.VH_TEXT, fontSize: 12, fontWeight: 500,
              fontFamily: 'inherit', cursor: 'pointer',
              filter: locked.value ? 'blur(5px)' : 'none',
            }}>
              <CastDot name={c.displayName}/>
              {c.displayName}
              <span style={{
                marginLeft: 2, padding: '2px 7px', borderRadius: 99,
                background: `${accent}22`, color: accent, fontSize: 10.5, fontWeight: 600,
              }}>{(c._videos?.length || c.videoCount || 0)}</span>
            </button>
          ))}
        </div>

        {/* Category chips */}
        {linkedCategories.length > 0 && (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
            {linkedCategories.map(c => (
              <button key={c.id} onClick={() => onOpenCategory?.(c.id, c.displayName)} style={{
                display: 'inline-flex', alignItems: 'center', gap: 5,
                padding: '4px 8px 4px 7px', borderRadius: 99,
                background: 'rgba(168,85,247,0.12)', border: '0.5px solid rgba(168,85,247,0.35)',
                color: window.VH_TEXT, fontSize: 11.5, fontWeight: 500,
                fontFamily: 'inherit', cursor: 'pointer',
                filter: locked.value ? 'blur(5px)' : 'none',
              }}>
                <span style={{ width: 6, height: 6, borderRadius: 99, background: '#a855f7', flexShrink: 0 }}/>
                {c.displayName}
                {(c.videoCount || 0) > 0 && (
                  <span style={{
                    padding: '1px 5px', borderRadius: 99,
                    background: 'rgba(168,85,247,0.25)', color: '#c084fc',
                    fontSize: 10, fontWeight: 600,
                  }}>{c.videoCount}</span>
                )}
              </button>
            ))}
          </div>
        )}

        {/* status + rating actions */}
        <window.SectionHeader>Status</window.SectionHeader>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 6, padding: '0 0' }}>
          {[
            { id: 'want_to_watch', label: 'Want' },
            { id: 'favorite',      label: 'Fav' },
            { id: 'watched',       label: 'Watched' },
            { id: 'rewatch',       label: 'Rewatch' },
            { id: 'skip',          label: 'Skip' },
          ].map(s => (
            <button key={s.id} onClick={() => setStatus(s.id)} style={{
              padding: '10px 0', borderRadius: 10, border: 'none', cursor: 'pointer',
              background: it.status === s.id ? accent : 'rgba(255,255,255,0.05)',
              color: it.status === s.id ? '#fff' : window.VH_TEXT,
              fontSize: 11.5, fontWeight: 600, fontFamily: 'inherit',
            }}>{s.label}</button>
          ))}
        </div>

        <window.SectionHeader>Rating</window.SectionHeader>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          {[1,2,3,4,5].map(i => (
            <button key={i} onClick={() => setRating(i)} style={{
              border: 'none', background: 'transparent', cursor: 'pointer', padding: 0,
            }}>
              <div style={{
                width: 18, height: 18, borderRadius: 99,
                background: i <= (it.rating || 0) ? accent : 'rgba(255,255,255,0.16)',
              }}/>
            </button>
          ))}
        </div>

        {it.note && (<>
          <window.SectionHeader>Note</window.SectionHeader>
          <div style={{
            padding: 12, borderRadius: 12,
            background: 'rgba(255,255,255,0.03)',
            border: `0.5px solid ${window.VH_HAIRLINE}`,
            fontSize: 13, color: window.VH_TEXT, lineHeight: 1.55,
            filter: locked.value ? 'blur(5px)' : 'none',
          }}>{it.note}</div>
        </>)}

        {!locked.value && it.gallery && it.gallery.length > 0 && (<>
          <window.SectionHeader>Gallery</window.SectionHeader>
          <div style={{
            display: 'grid', gridAutoFlow: 'column', gridAutoColumns: '52%',
            gap: 10, overflowX: 'auto', scrollbarWidth: 'none', minHeight: 100,
          }}>
            {it.gallery.slice(0, 16).map((url, idx) => (
              <div key={url + idx} style={{
                aspectRatio: '16/10', borderRadius: 10, overflow: 'hidden',
                background: window.VH_SURFACE_HI, border: `0.5px solid ${window.VH_HAIRLINE}`,
              }}>
                <img src={url} alt="" loading="lazy" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}/>
              </div>
            ))}
          </div>
        </>)}

        {!locked.value && it.trailerUrl && (
          <TrailerDetail video={it} accent={accent}/>
        )}

        {!locked.value && (it.sourceUrl || it.missavUrl) && (<>
          <window.SectionHeader>Source</window.SectionHeader>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {it.sourceUrl && (
              <div style={{
                padding: '10px 12px', borderRadius: 12,
                background: 'rgba(255,255,255,0.03)',
                border: `0.5px solid ${window.VH_HAIRLINE}`,
                fontSize: 12.5, color: window.VH_DIM,
                wordBreak: 'break-all',
              }}>{it.sourceUrl}</div>
            )}
            {it.missavUrl && (
              <div style={{ display: 'flex', gap: 8 }}>
                <a href={it.missavUrl} target="_blank" rel="noreferrer" style={{
                  flex: 1, height: 40, borderRadius: 10,
                  background: `${accent}18`, border: `0.5px solid ${accent}55`,
                  color: accent, textDecoration: 'none', fontSize: 12.5, fontWeight: 700,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>Open MissAV</a>
              </div>
            )}
          </div>
        </>)}

        {/* More from this cast */}
        <window.SectionHeader right={
          related.length > 0 && <span style={{ fontSize: 11.5, color: window.VH_DIM }}>{related.length}</span>
        }>More from this cast</window.SectionHeader>
        {related.length === 0 ? (
          <div style={{ padding: '18px 16px', borderRadius: 12,
            background: 'rgba(255,255,255,0.03)', border: `0.5px solid ${window.VH_HAIRLINE}`,
            color: window.VH_DIM, fontSize: 12.5, textAlign: 'center',
          }}>
            Nothing else saved with this cast yet.
          </div>
        ) : (
          <HScrollPosterRow items={related} locked={locked.value} accent={accent} onOpenVideo={onOpenVideo}/>
        )}

        {/* More in this category */}
        {relatedByCategory.length > 0 && (<>
          <window.SectionHeader right={<span style={{ fontSize: 11.5, color: window.VH_DIM }}>{relatedByCategory.length}</span>}>
            More in this category
          </window.SectionHeader>
          <HScrollPosterRow items={relatedByCategory} locked={locked.value} accent={accent} onOpenVideo={onOpenVideo}/>
        </>)}
      </div>
    </div>
  );
}

function TrailerDetail({ video, accent }) {
  const [open, setOpen] = useState(false);
  const [failed, setFailed] = useState(false);
  const videoRef = useRef(null);

  useEffect(() => {
    if (!open || !video.trailerUrl || !videoRef.current) return;
    let hls = null;
    const el = videoRef.current;
    const attach = async () => {
      try {
        if (video.trailerType === 'hls' && !el.canPlayType('application/vnd.apple.mpegurl')) {
          if (!window.Hls) {
            await new Promise((resolve, reject) => {
              const s = document.createElement('script');
              s.src = 'https://cdn.jsdelivr.net/npm/hls.js@1.5.18/dist/hls.min.js';
              s.onload = resolve; s.onerror = reject;
              document.head.appendChild(s);
            });
          }
          if (!window.Hls?.isSupported()) throw new Error('HLS unsupported');
          hls = new window.Hls({ enableWorker: true });
          hls.loadSource(video.trailerUrl);
          hls.attachMedia(el);
        } else {
          el.src = video.trailerUrl;
        }
      } catch {
        setFailed(true);
      }
    };
    attach();
    return () => { if (hls) hls.destroy(); el.removeAttribute('src'); el.load(); };
  }, [open, video.trailerUrl, video.trailerType]);

  return (
    <>
      <window.SectionHeader right={<span style={{ fontSize: 11, color: accent, fontWeight: 700 }}>FOUND</span>}>Trailer</window.SectionHeader>
      <button onClick={() => setOpen(v => !v)} className="vh-tap" style={{
        width: '100%', height: 42, borderRadius: 10, border: `0.5px solid ${accent}55`,
        background: `${accent}18`, color: accent, cursor: 'pointer',
        fontSize: 13, fontWeight: 700, fontFamily: 'inherit',
      }}>{open ? 'Hide Trailer' : 'Watch Trailer'}</button>
      {open && !failed && (
        <div style={{ marginTop: 10, borderRadius: 12, overflow: 'hidden', background: '#000', aspectRatio: '16/9' }}>
          <video ref={videoRef} controls muted playsInline preload="none" poster={video.trailerPoster || video.coverUrl || ''}
            onError={() => setFailed(true)}
            style={{ width: '100%', height: '100%', display: 'block' }}/>
        </div>
      )}
      {open && failed && video.sourceUrl && (
        <a href={video.sourceUrl} target="_blank" rel="noreferrer" style={{
          display: 'block', marginTop: 10, padding: 11, borderRadius: 10,
          background: 'rgba(255,255,255,0.04)', border: `0.5px solid ${window.VH_HAIRLINE}`,
          color: window.VH_TEXT, textDecoration: 'none', fontSize: 12.5, textAlign: 'center',
        }}>Open source page</a>
      )}
    </>
  );
}

function HScrollPosterRow({ items, locked, accent, onOpenVideo }) {
  return (
    <div style={{
      display: 'grid', gap: 10,
      gridAutoFlow: 'column', gridAutoColumns: '46%',
      overflowX: 'auto', scrollbarWidth: 'none',
      paddingBottom: 4,
    }}>
      {items.map(v => (
        <button key={v.id} onClick={() => onOpenVideo(v.id)} style={{
          background: 'transparent', border: 'none', padding: 0, textAlign: 'left', cursor: 'pointer',
          fontFamily: 'inherit', color: window.VH_TEXT,
        }}>
          <window.PosterTile code={v.code} status={v.status} locked={locked} accent={accent} coverUrl={v.coverUrl}/>
          <div style={{ marginTop: 6, fontSize: 11.5, fontFamily: 'ui-monospace, "SF Mono", Menlo, monospace', color: window.VH_DIM }}>
            {locked ? '••••••' : v.code}
          </div>
          <div style={{ fontSize: 12.5, color: window.VH_TEXT, fontWeight: 600,
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            filter: locked ? 'blur(5px)' : 'none',
          }}>{v.title}</div>
        </button>
      ))}
    </div>
  );
}

function CastDot({ name }) {
  const hue = window.hashHue(name || '');
  return (
    <div style={{
      width: 16, height: 16, borderRadius: 99,
      background: `radial-gradient(120% 90% at 25% 20%, oklch(0.55 0.18 ${hue}), oklch(0.18 0.06 ${(hue+30)%360}))`,
    }}/>
  );
}

// ═══════════════════════════════════════════════════════════════
// SMART COLLECTIONS — horizontal pill rail used at top of Library
// ═══════════════════════════════════════════════════════════════
const SMART_COLLECTIONS = [
  { id: 'all',         label: 'All' },
  { id: 'new',         label: 'New' },
  { id: 'want',        label: 'Want to watch' },
  { id: 'favorite',    label: 'Favorites' },
  { id: 'must_watch',  label: 'Must watch' },
  { id: 'rewatch',     label: 'Rewatch' },
  { id: 'recent',      label: 'Recently watched' },
  { id: 'top_rated',   label: 'Top rated' },
  { id: 'no_cover',    label: 'No cover' },
  { id: 'missing',     label: 'Missing details' },
];

function applySmartCollection(items, id) {
  switch (id) {
    case 'new':        return [...items].sort((a,b) => (b.createdAt||0) - (a.createdAt||0)).slice(0, 24);
    case 'want':       return items.filter(i => i.status === 'want' || i.status === 'want_to_watch');
    case 'favorite':   return items.filter(i => i.status === 'favorite');
    case 'must_watch': return items.filter(i => i.bookmarkLevel === 'must_watch' || (i.status === 'favorite' && (i.rating||0) >= 4));
    case 'rewatch':    return items.filter(i => i.status === 'rewatch');
    case 'recent':     return [...items].filter(i => i.watchedAt).sort((a,b) => (b.watchedAt||0) - (a.watchedAt||0)).slice(0, 24);
    case 'top_rated':  return [...items].filter(i => (i.rating||0) >= 4).sort((a,b) => (b.rating||0) - (a.rating||0));
    case 'no_cover':   return items.filter(i => !i.coverUrl);
    case 'missing':    return items.filter(i => !i.title || !(i.actresses||[]).length || !i.studio);
    default:           return items;
  }
}

Object.assign(window, {
  CastLibraryScreen, CastDetailScreen, VideoDetailScreen,
  CategoryDetailScreen, StudioDetailScreen,
  enrichCasts, deriveCastsFromVideos,
  SMART_COLLECTIONS, applySmartCollection,
});
