# MPS-7: Sandbox Mode — Client-Side Creative Filter System

## Problem

Creators want visitors to interact with their media beyond passive viewing.
Existing tools require downloading, editing in external software, and
re-uploading. The friction kills experimentation. Creators need an in-browser
creative toolkit that lets visitors play with filters, export artifacts, and
optionally upload results — all without leaving the shop.

## Solution

A client-side filter engine that runs entirely in the browser. The server stores
a single boolean (`shop.sandbox_mode`). When enabled, every page in the shop
renders a floating toolbar with 32 filter presets, 7 adjustment sliders, SVG
filter effects, canvas export (image + video), and optional face detection via
MediaPipe.

Full architecture and filter reference: [docs/sandbox-mode.md](../sandbox-mode.md)

### Server-side (minimal)

- `sandbox_mode` Boolean column on Shop model
- Toggle in ribbon-settings form section (same form as announcement ribbon,
  default theme, grid lanes, show_dates, watch_mode, color_filter)
- `base.j2` conditionally renders toolbar HTML, inline SVG filter definitions,
  and loads `sandbox.js` only when `shop.sandbox_mode` is true
- Watch mode SPA integration: `watch.js` calls `window.sandboxReapply()` after
  DOM swap to re-apply filters to newly loaded media

### Client-side (sandbox.js, ~700 lines)

- 32 CSS filter presets (4 basic, 4 warm, 4 cool, 4 dramatic, 5 color, 7
  Instagram-style, 4 SVG)
- 7 adjustment sliders (brightness, contrast, saturation, hue, blur, sepia,
  grayscale)
- Image export via canvas `toBlob()` (requires CORS from CDN)
- Video export via `MediaRecorder` + `captureStream(30fps)`
- Face detection via MediaPipe Face Mesh (4MB WASM, on-demand load)
- localStorage persistence of preset, slider values, panel state
- Upload-to-bucket via presigned POST (see MPS-8)

## Files Changed

| File | Change |
|------|--------|
| `models/shop.py` | `sandbox_mode` Boolean column |
| `views/shop.py` | Toggle handler in `ribbon-settings` form section |
| `templates/shop_settings.j2` | Enable/disable radio buttons |
| `templates/base.j2` | Conditional toolbar HTML + inline SVG defs |
| `static/js/sandbox.js` | Client-side filter engine (IIFE) |
| `static/js/watch.js` | `sandboxReapply()` hook in `updatePageContent()` |
| `static/css/common.css` | Toolbar layout (CSS Grid), mobile responsive |
| `scripts/alembic/versions/a2c13d3117f2_*.py` | Migration: `sandbox_mode` |
| `tests/test_functional.py` | Sandbox toggle, toolbar rendering, script tag tests |

## Depends On

Nothing. Independent feature.

## Blocks

MPS-8 (user S3 bucket for artifact upload)
