# Plan: Background Image Upload for CSS Matrix Calculator ## Overview Add ability to load a background image onto the main `#field` element for visual reference when positioning corners. The image is stored as a data URL in memory (no server). Three upload methods: Ctrl+V paste, file picker, drag & drop onto the field. Adjustable via `object-fit` options. ## Files to Modify ### 1. `js/state.js` — Add background state - Add `bgImage: null` (data URL string) and `objectFit: 'contain'` to `defaultState` and `state` - Reset these in `resetState()` ### 2. `index.html` — New "Background" panel + hidden file input Add a new panel in `right-col` (between Field and Widget panels, after line 78): ```html

Background

``` Add drag & drop hint overlay on `#fieldContainer` (drop zone indicator). ### 3. `style.css` — New styles - `.bg-controls` — flex row layout for controls - `#bgObjectFit` — styled select matching existing dark theme - `#fieldContainer.drag-over` — dashed border highlight for drop feedback - `#field` — add `background-size`, `background-position`, `background-repeat` properties - `.bg-hint` — overlay text on field when no image loaded ("Drop image or Ctrl+V") ### 4. `js/ui.js` — Event handlers - `btnBgLoad` click → trigger hidden file input - `bgFileInput` change → read file as data URL via `FileReader` → `state.bgImage = dataUrl` - `document` paste event → detect image in `clipboardData.files` → read as data URL - `#fieldContainer` dragover/drop → read dropped file as data URL - `btnBgRemove` click → clear `state.bgImage` - `bgObjectFit` change → `state.objectFit = value` - Toggle remove button visibility based on whether image is loaded - On state change: call `updateAll()` ### 5. `js/preview.js` — Apply background to field - If `state.bgImage`: set `field.style.backgroundImage = url(...)`, `field.style.backgroundSize`, `field.style.backgroundPosition`, `field.style.backgroundRepeat` based on objectFit - If no image: clear background properties ### 6. `js/svg-renderer.js` — Show background in SVG editor - If `state.bgImage`: add an `` element as first child of SVG (behind grid) with `href`, `width`, `height`, and `preserveAspectRatio` matching the objectFit mapping ### 7. `js/main.js` — No changes needed (updateAll already propagates) ## Implementation Details ### Image loading flow 1. User triggers upload (paste/file/drop) → get `File` object 2. `FileReader.readAsDataURL(file)` → get data URL string 3. Store in `state.bgImage` 4. Call `updateAll()` to propagate ### object-fit mapping to SVG preserveAspectRatio | objectFit | SVG preserveAspectRatio | |---------------|------------------------| | contain | xMidYMid meet | | cover | xMidYMid slice | | fill | none | | none | xMinYMin meet | | scale-down | xMidYMid meet | ### Keyboard shortcut - Ctrl+V paste listener on `document` — check for image in clipboard items - Only active when no input/textarea is focused (to avoid conflicts) ### Drag & drop - Listen on `#fieldContainer` for `dragover` (prevent default, show visual hint) and `drop` (read file) ## Verification 1. Open `index.html` in browser 2. **File picker**: Click "Load Image" → select image → verify it appears as background on the field in both edit (SVG) and preview modes 3. **Ctrl+V**: Copy an image to clipboard → press Ctrl+V → verify it loads 4. **Drag & drop**: Drag an image file onto the field area → verify it loads 5. **object-fit**: Change dropdown → verify background resizes correctly (contain fits, cover fills, etc.) 6. **Remove**: Click "Remove" → verify background clears 7. **Reset**: Click "Reset" → verify background clears along with other state 8. **Corner drag**: Load background → drag corners → verify background stays in place, corners move independently