feat(gallery+db): character page gallery UX overhaul + Sculpt/Classic estimated bodies - #29
Conversation
- 24 brands, 233 classified body profiles across 6 ZELEX families - SQLite DB with competitor_rows, brand_summary, brand_geographic, market_tiers, market_regions, inventory_only tables - Pricing, quality signals, geographic metadata per brand - Irontech official + Tayu sitemap + Dollstudio multi-brand crawl - RealDoll 13-model inventory captured (classification pending) - Approved PDR-010 design spec added
Tayu is scraped via scrape_tayu() in main(); listing it as pending-source in UNAVAILABLE_COMPETITORS made every generated report mark Tayu as both covered and a gap simultaneously. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The two independent-catalog heatmap PNGs were force-added in e137d22 despite *.png being in .gitignore. The CI hygiene guard rejects image files in the tree. Removing them from the index; local copies remain. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… estimated bodies Gallery / character page (character.html): - Remove "· Slot N" from series eyebrow — series name only - Backdrop image now uses gallery[1] to differ from the hero - Image count derived from gallery.length (not stale static field) - Auto-rotate every 4.5 s with gold progress bar; pauses on hover - Lightbox with prev/next buttons, keyboard nav (←/→/Esc), click-outside close DB — estimated hero bodies for new families: - db/family_taxonomy.json: ZS165D (Sculpt) + ZC165D (Classic) added; member_counts set to 1 - db/body_profiles.json: full profile entries for ZS165D + ZC165D - db/body_measurements.json: estimated spec-cards (PDR-005/007 design targets) - db/character_profiles.json: persona entries for The Athlete + The Standard All four HTML pages (browse, contact, quiz, series) carry forward minor polish edits from prior session. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces two new body profiles (ZS165D and ZC165D) with their corresponding measurements, taxonomy, and character profile details. It also adds interactive gallery features to character.html (including auto-rotation, a progress bar, and a lightbox modal), updates border-radius values to use CSS variables, refactors event listeners in series.html, and refines the quiz fallback logic in quiz.html. Feedback on these changes highlights two issues: a bug in quiz.html where fallback characters break the splitAt divider placement, and a race condition in character.html where the gallery progress bar can animate even when auto-rotation is paused.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Pull request overview
This PR improves the character page browsing experience (gallery auto-rotation + lightbox + cleaner metadata) and extends the catalog database with two new estimated body SKUs for the Sculpt and Classic families.
Changes:
- Refactors character.html gallery UX: series-only eyebrow, non-duplicate backdrop image, gallery-length-derived image counts, auto-rotate with progress bar, and a lightbox overlay with keyboard navigation.
- Adds estimated DB entries for ZS165D (The Sculpt) and ZC165D (The Classic) across taxonomy, profiles, measurements, and character/persona copy.
- Small UI/CSS consistency tweaks (button wiring in
series.html, shared button styling inquiz.html, border-radius variables inbrowse.html/contact.html, and contact form error message structure).
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| series.html | Removes inline onclick and wires view toggle buttons via addEventListener. |
| quiz.html | Makes “Begin” use shared .btn styling and tweaks match fallback logic. |
| db/family_taxonomy.json | Adds ZS165D/ZC165D into family membership + body taxonomy list (estimated). |
| db/character_profiles.json | Adds persona/positioning copy for ZS165D and ZC165D. |
| db/body_profiles.json | Adds full estimated profile rows for ZS165D and ZC165D. |
| db/body_measurements.json | Adds estimated measurement records for ZS165D and ZC165D. |
| contact.html | Uses --r-md radius tokens; improves error message text update without clobbering the email link; hides chip area on success. |
| character.html | Implements the character gallery UX overhaul (auto-rotate/progress + lightbox + metadata tweaks). |
| browse.html | Uses --r-md for search input border radius consistency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- assets/site.css: add isolation:isolate to .btn.concierge to contain
the z-index:-1 ::before pseudo-element within the button stacking context
- scripts/analyze_independent_groupings.py: use .as_posix() for
generated_from so the path uses forward slashes on Windows
- scripts/scrape_competitors.js: wrap scraping loop in try…finally so
browser.close() is guaranteed even on exception
- scripts/build_competitor_catalog_taxonomy.py:
- use `or ""` (not default "") on body_html/title/handle to guard
against explicit null values returned by the Shopify API
- add height sanity check (50–250 cm) in scrape_supplier to drop
mis-parsed values like 16 cm (Game Lady regression)
- include "hybrid" material in tpe_share_pct calculation
- wrap every network scrape call in main() with try/except so one
supplier failure does not abort the entire run
- docs/pdr/PDR-010-competitor-family-coverage-roi-validation.md:
- fix market concentration band table (90–100% header; correct
WM/XT/SE/6YE/AS Doll to 60–69% band; move Game Lady/Tayu/Jiusheng
out of <60% into 60–69%)
- recalculate ROI composites using the stated weight formula
(avail×2, conv×2, roadmap×1.5, others×1, total 10.5):
Muse 3.5→3.7, Icon 4.0→3.9, Siren 3.8→3.7,
Empress 2.3→2.0, Classic 3.4→3.1, Sculpt 2.3→2.0
- db/independent_catalog_groupings.json: fix Windows backslash in
generated_from path
- docs/research/source-log.md: correct Irontech URL to
https://www.irontechdoll.com/ (matches scraper endpoint)
- docs/research/competitor-family-coverage-matrix.md: fix Game Lady
height range from 16-171 cm to 156-171 cm (scraper mis-parse)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9cc4536af3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- quiz.html: recalculate fromSecond after fallback block so splitAt divider stays anchored to first runner-up character index - character.html resetBar(): guard inner rAF callback against autoTimer being cleared during the two-frame delay - character.html goTo(): set lbImgEl.alt dynamically using p.name and photo index for screen-reader accessibility - character.html openLightbox/closeLightbox: save lightboxAutoWasRunning before stopAuto() so auto-rotation only restarts if it was running - contact.html showError(): remove dead msgEl variable (assigned, never used) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b432425baf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "estimated": true, | ||
| "est_basis": "Interpolated from ZX172E / ZG175E (E-cup) slim build (no published spec card)" | ||
| }, | ||
| "ZS165D": { |
There was a problem hiding this comment.
Teach the generators the new prefixes
When scripts/build_profiles.py is rerun (it is the documented generator for db/body_profiles.json), I checked that its prefix normalization only recognizes ZGX, ZX, ZK, and ZF, and otherwise falls back to ZG; adding this ZS165D source row therefore regenerates the profile as line ZG / series Inspiration instead of ZS / Sculpt (and the same happens to the new ZC165D row). Please update the generator’s prefix map/normalization before adding these generated DB entries so the new bodies round-trip correctly.
Useful? React with 👍 / 👎.
…ke) (#34) * research(pdr-010): competitor family taxonomy + apples-to-apples DB - 24 brands, 233 classified body profiles across 6 ZELEX families - SQLite DB with competitor_rows, brand_summary, brand_geographic, market_tiers, market_regions, inventory_only tables - Pricing, quality signals, geographic metadata per brand - Irontech official + Tayu sitemap + Dollstudio multi-brand crawl - RealDoll 13-model inventory captured (classification pending) - Approved PDR-010 design spec added * PDR-010: expand competitor coverage and add independent grouping heatmaps * PDR-010: add full-body heatmap and normalize ZELEX line grouping * PDR-010: add PNG heatmaps, top10 matrices, and lineup brief * PDR-010: track independent catalog heatmap PNG artifacts * fix(taxonomy): remove Tayu from UNAVAILABLE_COMPETITORS Tayu is scraped via scrape_tayu() in main(); listing it as pending-source in UNAVAILABLE_COMPETITORS made every generated report mark Tayu as both covered and a gap simultaneously. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): untrack PNG heatmap artifacts that trip the image guard The two independent-catalog heatmap PNGs were force-added in e137d22 despite *.png being in .gitignore. The CI hygiene guard rejects image files in the tree. Removing them from the index; local copies remain. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(gallery+db): character page gallery UX overhaul + Sculpt/Classic estimated bodies Gallery / character page (character.html): - Remove "· Slot N" from series eyebrow — series name only - Backdrop image now uses gallery[1] to differ from the hero - Image count derived from gallery.length (not stale static field) - Auto-rotate every 4.5 s with gold progress bar; pauses on hover - Lightbox with prev/next buttons, keyboard nav (←/→/Esc), click-outside close DB — estimated hero bodies for new families: - db/family_taxonomy.json: ZS165D (Sculpt) + ZC165D (Classic) added; member_counts set to 1 - db/body_profiles.json: full profile entries for ZS165D + ZC165D - db/body_measurements.json: estimated spec-cards (PDR-005/007 design targets) - db/character_profiles.json: persona entries for The Athlete + The Standard All four HTML pages (browse, contact, quiz, series) carry forward minor polish edits from prior session. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(pdr-010): address all PR #28 Copilot/Gemini review findings - assets/site.css: add isolation:isolate to .btn.concierge to contain the z-index:-1 ::before pseudo-element within the button stacking context - scripts/analyze_independent_groupings.py: use .as_posix() for generated_from so the path uses forward slashes on Windows - scripts/scrape_competitors.js: wrap scraping loop in try…finally so browser.close() is guaranteed even on exception - scripts/build_competitor_catalog_taxonomy.py: - use `or ""` (not default "") on body_html/title/handle to guard against explicit null values returned by the Shopify API - add height sanity check (50–250 cm) in scrape_supplier to drop mis-parsed values like 16 cm (Game Lady regression) - include "hybrid" material in tpe_share_pct calculation - wrap every network scrape call in main() with try/except so one supplier failure does not abort the entire run - docs/pdr/PDR-010-competitor-family-coverage-roi-validation.md: - fix market concentration band table (90–100% header; correct WM/XT/SE/6YE/AS Doll to 60–69% band; move Game Lady/Tayu/Jiusheng out of <60% into 60–69%) - recalculate ROI composites using the stated weight formula (avail×2, conv×2, roadmap×1.5, others×1, total 10.5): Muse 3.5→3.7, Icon 4.0→3.9, Siren 3.8→3.7, Empress 2.3→2.0, Classic 3.4→3.1, Sculpt 2.3→2.0 - db/independent_catalog_groupings.json: fix Windows backslash in generated_from path - docs/research/source-log.md: correct Irontech URL to https://www.irontechdoll.com/ (matches scraper endpoint) - docs/research/competitor-family-coverage-matrix.md: fix Game Lady height range from 16-171 cm to 156-171 cm (scraper mis-parse) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: apply PR #29 review comment fixes - quiz.html: recalculate fromSecond after fallback block so splitAt divider stays anchored to first runner-up character index - character.html resetBar(): guard inner rAF callback against autoTimer being cleared during the two-frame delay - character.html goTo(): set lbImgEl.alt dynamically using p.name and photo index for screen-reader accessibility - character.html openLightbox/closeLightbox: save lightboxAutoWasRunning before stopAuto() so auto-rotation only restarts if it was running - contact.html showError(): remove dead msgEl variable (assigned, never used) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: ship compare funnel and analytics sanity guardrails * feat(pdr-010): add Howie CEO package — strategic briefs + interactive dashboard Adds the full CEO package for Howie's leadership review use: - docs/howie-ceo-package/howie-ceo-dashboard.html — standalone interactive Family Activation Simulator: 6 family cards with live KPI recalculation, health pill (HEALTHY/AT RISK/CRITICAL), scenario ROI, and decision brief links. All data labeled as analyst estimates; no server dependency. - docs/howie-ceo-package/00–05 — command brief, dedicated brief library, team execution guide, KPI scoreboard, deep-dive guide, decision log template. All files carry prominent ESTIMATES NOTICES (competitive research, not actuals). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(pdr-010): add like-kind manufacturing & cross-family tooling interdependency analyses 03-like-kind-manufacturing-scenarios.md: identifies ZE T168E (dist 0.96 to Sculpt centroid) and ZG S155C/ZG162D as zero-to-minimal-tooling paths to seed Classic and Sculpt families. 04-cross-family-tooling-interdependencies.md: maps bridge frames across all 6 families, defines the convergence frame concept (H160, W57 activates Classic + Sculpt from one commission), identifies Sculpt/Icon bridge zone, and models the ~$200-350K cascade that eliminates both dead-end families while reinforcing Icon and Empress. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(pdr-010): add manufacturing intelligence matrix brief for CEO package Introduces the Build-to-Stage framework: Family × Component Layer × Demand Confidence Tier matrix showing how market intelligence (family centroids, dimensional distance scores, market gap coverage) feeds directly into pre-staged work orders. Distinguishes what current data enables vs. what requires customer/order data, and identifies Tier 1 pre-stage actions (ZE T168E for Sculpt, ZG S155C for Classic) that can start immediately. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(pdr-010): add full PDR with Mermaid path analysis across all epic phases Covers 5 decision points — family activation paths, tooling investment options, manufacturing model (MTO vs. Build-to-Stage), data signal maturity, and family expansion sequence — each with Mermaid flowcharts showing pros/cons per path. Includes investment summary across Immediate / Q3 / Q3-Q4 / 2027 horizons and a single-table decision summary for Howie. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(pdr-010): embed Mermaid decision charts into CEO dashboard Adds interactive PDR-010 decision path section to howie-ceo-dashboard.html: - Mermaid v10.9.0 CDN + dark-theme initialization - Phase Map (full-width): P0 done → P1 active → P2-P4 planned/future - DP-1: Classic/Sculpt activation paths (A/B/C with verdicts) - DP-2: Q3 tooling investment options (Convergence/Bridge/Both) - DP-3: Make-to-Order → Build-to-Stage transition - DP-4: Family expansion sequence (Zone A/B, Empress, Siren) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Import PDR recovery pack and enforce explicit PDR path gating * Add CI PDR_PATH guard and complete recovery-task traceability * Apply PDR-001 status primitives in shared card components * Use shared status primitives on homepage family tiles * Continue PDR-001 rollout and add PDR-002 homepage intent router * Advance PDR-003 compare workflow with decision summaries * Unify compare-entry UX and remove remaining homepage inline layout styles * Implement PDR-004 ranked quiz funnel and handoff CTAs * feat: add customization options guide with body/head tracks * feat: add options deep-links, filter analytics, and noscript fallback * chore: package latest root HTML set into v2 HTML * feat: add community hub, SWOT gap review, and v2 packaging automation * chore: harden validation and v2 packaging best practices * feat: enforce v2 freshness in CI and data-drive community hub * feat: tie community hub to KB with schema guard and events page * chore: add community-events schema guard and KB sync utility * chore: add check-mode sync guard and community data contract * chore: refresh v2 package checksum artifact * chore: add community provenance UI and event scaffold utility * docs: finalize community data operations and CI sync policy guidance * fix: repair validate-site metadata gate after main merge * fix: resolve main merge conflicts and add required page metadata * HZZ-FE-002: Refine luxury design system v2 (assets/site.css) Distinct 5-state trust chips, consistent accessible focus rings, reusable .panel / .field-* / .opt / .progress-* primitives, sticky compare-table, unified mobile spacing rhythm, extended reduced-motion coverage. PDR: docs/pdr/PDR-FE-002-luxury-design-system-v2.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add Claude Design frontend PDRs and tickets Adds governed PDRs (PDR-FE-000..009), tickets (HZZ-FE-000..009), Claude Design prompts, and Command Center frontend queue JSON for the HowieZZ frontend rebuild. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-001: Redesign homepage as Concierge Atlas landing Single clear primary action (Find your match), three parallel buyer paths, canonical data-driven six-family rail (honest in-development for Classic/Sculpt), compare-bodies preview at first decision block, concierge closing CTA. Removed redundant .doors block and duplicate static family-chooser. PDR: docs/pdr/PDR-FE-001-homepage-concierge-landing.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-003: Body compare UX Non-dead-end empty state (quiz/browse CTAs), selected-body chip strip with per-body remove + 0-4 counter, two-line plain-language buyer-read & handling rows, softened gold to atelier-neutral. Reuses FE-002 compare-table primitives. PDR: docs/pdr/PDR-FE-003-body-compare-ux.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-003: Align compare buyer-read & handling to real DB data Replace hardcoded family/weight maps with lookups into the loaded model (profiles + families): handling tiers derive from real weight_kg (28-39.9kg spread, dead >42kg bucket removed), buyer-read cites each body's silhouette/ target_buyer + WHR/BWR vs its family range, surfaces family_confidence wording (exact/near/loose) and "Estimated dimensions" note. Measurement-led per docs/body-family-method.md and body-family-copy-guide.md. PDR: docs/pdr/PDR-FE-003-body-compare-ux.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-005: Quiz match results funnel Ranked top-3 family results with match %, measurement-led "why this matched" panel citing the winning family's real WHR/BWR ranges + user axis leaning, copy-guide voice, recommended character cards with per-body WHR/BWR, honest in-development routing (no dead-ends; nearest active family via the method's normalized-distance metric), concierge CTAs. PDR: docs/pdr/PDR-FE-005-quiz-match-results.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-007: Browse and family UX Explicit family/series/character taxonomy explainer; family availability derived from real characters.json membership (Available / Limited / In Development) rather than assumed; honest in-development cards for Classic & Sculpt and a limited-release note for Empress (n=1) instead of empty/dimmed grids; premium % + target buyer surfaced (measurement-led); concierge CTA paths from both pages into compare/contact with ?family= context. PDR: docs/pdr/PDR-FE-007-browse-family-ux.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-004: Character detail premium conversion At-a-glance decision panel (silhouette, premium tier, match confidence, ratios vs family band), best-for + worth-knowing modules, weight-based handling meter (real weight_kg over 28-39.9kg), and compare/build-similar/ask-concierge routing cluster. Self-fetches character_profiles.json; copy synthesized from real data (positioning/energy/target_buyer); estimated + shoot-pending states stay honest. PDR: docs/pdr/PDR-FE-004-character-detail-conversion.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-006: Concierge intake UX Private-consultation framing; context summary card adapting to ?id=/?family=/ ?b=/compare-handoff routes with WHR/BWR stats + family premium % from DB; silhouette-family intent field auto-selected from context; trust/discretion sidebar; made-to-order no-pressure copy; consultation-framed success/error. 18+ consent required, mailto fallback, and PII-free analytics all preserved. PDR: docs/pdr/PDR-FE-006-concierge-intake.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: add Claude Design premium intake & buyer-fit package (reference) Guided intake + live configurator prototypes from Claude Design, with porting plan into the ZX/site.css stack. Reference material for the contact.html intake port and the new configurator page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(intake): port Claude Design guided buyer-fit UX into contact.html Audience switch (New buyer / Collector) re-tailoring copy depth; six interactive buyer-fit fields (intended use, timeline, gradient realism scale, handling, shipping/privacy, customization swatches) writing non-PII hidden inputs to the existing submit payload; live "Your fit so far" sidebar. Reuses ZX prefill + family-premium framing; 18+ consent, mailto fallback, and PII-free analytics preserved. Prototype hex mapped to site.css variables. PDR: docs/pdr/PDR-FE-006-concierge-intake.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(configurator): port Claude Design live configurator as new page New configurator.html: parametric SVG silhouette redrawn live from each family's published WHR/BWR ranges (clamped to the family envelope), realism scale, skin/ hair/eye tinting, concierge tip popouts, live build summary, and a concierge handoff CTA to contact.html (?family= + non-PII config_summary). Classic & Sculpt labelled in-development (derived from zero live bodies). Boots via ZX like the other pages; site.js nav/footer gain a "Configure" link. PDR: docs/pdr/PDR-FE-006-concierge-intake.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-008: Mobile navigation and CTA pass Off-canvas hamburger drawer below 860px for the 9-link nav (desktop unchanged; same .links markup so active/focus/scroll-elevation keep working; no-JS safe); aria-expanded + Esc + scrim + scroll-lock. Hero and concierge/intent action clusters stack full-width with primary on top; tap targets >=44px. Reduced-motion disables drawer/scrim animation. PDR: docs/pdr/PDR-FE-008-mobile-navigation-cta-pass.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * HZZ-FE-009: Visual QA review findings Auditor pass over all funnel pages (desktop + mobile Chrome screenshots). Verdict: PASS - 0 blockers, 0 major, 5 minor. Verified missing-image .monotile fallback, honest Classic/Sculpt in-development states, estimated- dimension disclosure, 18+/privacy, and the FE-008 mobile drawer. Minor issues logged as follow-up tickets HZZ-FE-010..013. Screenshots kept local (gitignored) to avoid the repo image guard. PDR: docs/pdr/PDR-FE-009-visual-qa-screenshot-review.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(qa): resolve FE-009 minor findings (HZZ-FE-010..013) - M-1/FE-010: verified browse renders 76 cards (headless screenshot artifact, not a bug); add html[data-zx-loaded] CI readiness signal in ZX.load(). - M-2/FE-011: body overflow-x:hidden guard + quiz h1 mobile floor 36->28px. - M-3/FE-012: footer reconciled to "six silhouette families across four series". - M-4/FE-013: --muted #9a9a9a -> #ababab for small-label contrast comfort. PDR: docs/pdr/PDR-FE-009-visual-qa-screenshot-review.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(qa): add reconciliation analysis + live interaction QA evidence Reconciliation: worktree-agent branches (782b510) are stale ancestors; fe-design vs feat/pdr-010 merges clean (0 conflicts); only PR #27 (pdr-001-design-system-v2) genuinely diverges. Recommends landing #34 as canonical design, salvaging #27's competitor-analysis data only. Live QA (real Chrome CDP @390px): overflow PASS all pages (canScrollX=no), mobile nav drawer PASS (open/Esc/scrim/close + active link), navToggle 44px. Closes FE-009 M-2 and M-5 with evidence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ci): community-data validator tolerates gitignored _local/ provenance refs The required "Validate site + data + scripts" check hard-failed because db/community_channels.json cites _local/reference/zelexdoll-theme as a source_ref, but _local/ is gitignored (machine-local reference material) and never exists in CI -- so the check blocked every PR off this base. Validate shape only (not on-disk existence) for _local/ provenance refs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(v2): refresh v2 HTML package after frontend redesign Regenerate the v2 HTML bundle + manifest/checksums from the updated source pages (includes new configurator.html). Satisfies the CI "v2 HTML package is refreshed" guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ci): make v2 HTML package deterministic across environments Remove volatile fields (generated_utc, source_root, destination, per-file modified_utc) from manifest.json and write all output files with explicit LF line endings via [IO.File]::WriteAllText. The guard runs the script and checks git diff — this ensures the committed artifacts are byte-identical to what CI regenerates on Linux. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): set ErrorActionPreference=Continue in analytics suite script GitHub Actions pwsh steps default to Stop, which turns Write-Error into a terminating throw (exit 1) before the explicit exit 2 can run. This broke the analytics config guardrail check that expects exit code 2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): add ErrorActionPreference=Continue to guardrail steps GitHub Actions pwsh steps run as pwsh -command ". '{0}'" with ErrorActionPreference=Stop in the outer context. When the analytics script subprocess exits with code 2 (non-zero), the outer step throws before $LASTEXITCODE can be checked. Setting Continue at the top of the inline run script prevents the non-zero exit code from being treated as a fatal error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): use [Environment]::Exit(2) for config validation failures Replace Write-Error+exit 2 with Write-Host+[Environment]::Exit(2) for all config-validation early-exits. [Environment]::Exit() calls the OS exit function directly via .NET, bypassing all PowerShell error-handling machinery and guaranteeing the subprocess reports exit code 2 regardless of the runner environment. Also adds a diagnostic Write-Host to confirm the attribute values being compared. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): add exit 0 after successful guardrail checks Without explicit exit 0, the step ends with $LASTEXITCODE=2 still set from the subprocess. GitHub Actions' pwsh wrapper treats any non-zero $LASTEXITCODE at step end as failure and exits with code 1, even though the check passed. Adding exit 0 explicitly signals success. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
character.html): five improvements to the character pagegallery[1](a different image from the hero) so the background and hero aren't identicalgallery[]array length, not the staleimage_countfielddb/): estimated body profiles for two new SKUsfamily_taxonomy.json,body_profiles.json,body_measurements.json,character_profiles.json"estimated": truepending manufactureTest plan
/character.html?id=<any-id-with-gallery>— verify eyebrow shows series only (no slot number)gallery[1]existsgallery.lengthfor characters with multiple imagesestimated: true🤖 Generated with Claude Code