#!/usr/bin/env python3
"""Build Monster High picker v4.
v3 + Sam's adjustments:
- each burst collapses to ONE grid cell (animated first frame, gold highlight, "GIF xN")
- tapping a burst cell opens its group view: all frames, tap one to enlarge + favorite
- lightbox arrows/swipe navigate the full sequence (singles + burst frames in order)
- static fallback (FBQ, no JS): all photos shown individually with GIF badges
Usage: python3 build_picker_v4.py bursts.json
"""
import json, sys
from pathlib import Path
SHOOT = Path("/Volumes/Sam Storage/YellowMellow/2026/Monster High Theme (10:01:2026)")
PRE = SHOOT / "ClientPicker" / "Previews"
OUT = SHOOT / "Monster High - Photo Picker.html"
ids = sorted(p.stem for p in PRE.glob("*.jpg") if not p.name.startswith("._"))
assert ids, "no previews"
blur_manifest = SHOOT / "BlurReview" / "BlurManifest.json"
if blur_manifest.exists():
blur_ids = set(json.loads(blur_manifest.read_text()).get("confirmed", []))
ids = [pid for pid in ids if pid not in blur_ids]
idset = set(ids)
bursts = json.load(open(sys.argv[1]))
# per burst: existing frame ids in order; lead = first
burst_frames, frame_burst = {}, {}
for k, v in bursts.items():
a, b = int(v["first"][4:]), int(v["last"][4:])
fr = ["7O9A%04d" % n for n in range(a, b + 1) if "7O9A%04d" % n in idset]
if not fr:
continue
burst_frames[k] = fr
for f in fr:
frame_burst[f] = k
cells, n_singles, n_leads = [], 0, 0
for i in ids:
chip, attrs = "", ""
if i in frame_burst:
k = frame_burst[i]
if burst_frames[k][0] == i: # lead cell = the whole sequence
chip = 'GIF ×%d' % len(burst_frames[k])
attrs = ' data-burst="%s"' % k
n_leads += 1
else:
chip = 'GIF'
attrs = ' data-burstframe="%s"' % k
else:
n_singles += 1
src = ("ClientPicker/Bursts/%s.webp" % k) if attrs.startswith(" data-burst=") else ("ClientPicker/Thumbs/%s.jpg" % i)
cells.append(
'