# RongBerong AI — Editor Redesign Spec (UI change, functionality preserved)

> Redesign the **RongBerong AI Product Studio** UI into a Fotor-style 3-zone editor shell **without breaking any existing functionality**. Reference for *layout only*: Fotor AI editor (`fotor.com/photo-editor-app/editor/ai`).
>
> **For Claude Code:** This is a **re-skin + restructure**, not a rewrite. The backend, the AI logic, the 65 KB front-end engine, the voice system, the i18n, and the prompt/preset features must all keep working exactly as they do today. Read **§A (Functionality Preservation Contract) FIRST** — it is the hard requirement. §B onward is the visual target.
>
> Companion file: `mockup-editor-shell.html` (the approved visual target — open it to see the intended look).

---

# PART A — FUNCTIONALITY PRESERVATION CONTRACT  ⚠️ (read first, non-negotiable)

The current app works. Your job is to change **how it looks and how zones are arranged**, while keeping **what it does** identical. Treat everything in this part as MUST-NOT-BREAK.

## A.1 Architecture you must respect

- **Stack:** Laravel 12 + Blade + Tailwind v4 (`@theme` in `resources/css/app.css`) + Vite. **No React, no Vue, no build-system change.**
- **The brain is `public/js/rongberong.js` (~65 KB).** It is vanilla JS that binds to the DOM by **element IDs and CSS classes** and holds all logic: state, voice parsing (EN+BN), option selection, prompt building, generate/video calls, presets, prompt library. **Do not rewrite this file's logic.** You may reorganize *where elements live in the DOM*, but the IDs/classes/`data-*` it queries must still exist and still behave the same.
- **`public/js/hero-particles.js`** drives the hero particle canvas (only needed if you keep the hero).
- **Bootstrap (in Blade, keep it):**
  ```html
  <script>
    window.__trans   = @json($jsTrans);   // i18n strings for JS
    window.__hasApiKey = true;
    window.__base    = '{{ rtrim(request()->getSchemeAndHttpHost() . request()->getBasePath(), '/') }}';
  </script>
  <script src="{{ asset('js/hero-particles.js') }}?v=..."></script>
  <script src="{{ asset('js/rongberong.js') }}?v=..."></script>
  ```
  These globals (`window.__trans`, `window.__base`, `window.__hasApiKey`) and the CSRF meta tag `<meta name="csrf-token">` are **required** — the JS reads them. Keep them.

## A.2 Backend endpoints — DO NOT CHANGE (routes, controller, payloads)

Routes in `routes/web.php` → `RongBerongController`. The front-end calls these via `fetch(window.__base + '<path>')`. Keep paths, methods, field names, and JSON response shapes **exactly**.

| Method | Path | Purpose | Request fields (must keep names) | Response |
|---|---|---|---|---|
| GET | `/` | render editor | — | view with `$jsTrans` |
| GET | `/lang/{locale}` | switch EN/BN | `locale` ∈ `en,bn` | redirect back, sets `session('locale')` |
| POST | `/fetch-image` | load image from URL | `url` (required, url, ≤2048) | `{success, data(base64), mime, data_url}` |
| POST | `/transcribe-voice` | voice → transcript+parse | `audio` (base64 string), `mime` | `{success, ...}` from GeminiService |
| POST | `/parse-voice` | text transcript → fields | `transcript` (≤1000) | `{success, ...}` |
| POST | `/generate` | make photo/video direction | full field set ↓ | `{success, ...}` (Gemini) |
| POST | `/generate-video` | submit video job | full field set, `output:'video'` | `{success, operation?, ...}` |
| GET | `/video-status?op=...` | poll video job | query `op` (operation id) | `{success, done?, video?, ...}` |

**Generate / generate-video request field set (every name must remain — the JS sends these and the validator expects them):**
`output` (`image`|`video`), `garment`, `fabric`, `color`, `model` (array), `pose`, `bg`, `lighting`, `camera`, `frame`, `occasion`, `aesthetic`, `vibe`, `accessories`, `motion`, `pattern`, `fit`, `sleeve`, `neckline`, `embellishment` (array), `model_age`, `body_type`, `hair`, `makeup`, `expression`, `footwear`, `season`, `product_focus`, `image_style`, `platform`, `aspect_ratio`, `branding_space`, `text_overlay`, `image_data`, `image_mime`.

> If you rename any of these in the HTML/JS, validation fails and generation breaks. Don't.

## A.3 The `state` object (in `rongberong.js`) — the single source of truth

The UI is a view over this object. Every control writes into it; generate serializes it. Keep all keys:
```js
const state = {
  output:'image',
  garment,fabric,pattern,fit,sleeve,neckline,embellishment:[],color,        // Garment
  model:[],model_age,body_type,hair,makeup,expression,footwear,             // Model
  bg,lighting,camera,frame,pose,season,occasion,product_focus,             // Shot
  aesthetic,vibe,image_style,accessories,                                   // Style
  platform,aspect_ratio,branding_space,text_overlay,                       // Output
  motion,                                                                   // Video
  uploaded:false,imageData,imageMime,approved:false                        // Upload/flow
};
```

## A.4 DOM contract — IDs the JS binds to (these IDs MUST exist in the new markup)

`rongberong.js` calls `getElementById(...)` / `querySelector('#...')` on these. **Keep every ID on an element that plays the same role.** You may move it to a different zone (rail/panel/canvas), restyle it, or wrap it — but it must exist and be the same kind of control.

```
mic              transcript        vlabel            toggle            outputTypeLabel
file             upload            uploadClear       uph               go
imageUrlInput    imageUrlLoad      imageUrlErr       colorInput        accessoriesInput
chips            req               err               stage             stageEmpty
motionField      advancedToggle    advancedLabel     advancedContent
presetSave       presets           promptToggle      promptToggleLabel promptArea
promptText       promptCopy        promptCopyLabel   promptLib         promptLibSave
approveContainer approveBtn        hintTip           elapsedVal        guideToggle  guideContent
```

Role reference (so you place them correctly in the new layout):
- `mic` voice record button · `transcript` voice text area · `vlabel` voice status label
- `toggle` = the Photo/Video segmented control container; JS does `querySelectorAll('#toggle button')` — keep **two `<button>`s inside `#toggle`**. `outputTypeLabel` shows current output.
- `file` hidden file input · `upload` dropzone · `uploadClear` remove button · `uph` upload placeholder/preview
- `imageUrlInput`/`imageUrlLoad`/`imageUrlErr` = paste-URL flow
- `chips` container for quick presets · `colorInput`/`accessoriesInput` free-text fields
- `go` = main **Generate** button · `req` required/validation banner · `err` error display
- `stage` = the result/canvas area · `stageEmpty` = empty state inside it
- `motionField` = video-motion picker (show only when output=video)
- `advancedToggle`/`advancedLabel`/`advancedContent` = the Advanced (extra fields) expander
- `presetSave`/`presets` = save/list configs · `prompt*` = prompt preview/copy/library · `approve*` = approve step · `hintTip` = `?` tooltips · `elapsedVal` = generation timer · `guide*` = how-to.

## A.5 CSS-class & data-attribute contract (the JS also binds to these)

Keep these class/attribute hooks on the option controls — the selection engine depends on them:
- Option buttons use class **`.opt`**, grouped in **`.opts`** containers; selected = **`.opt.sel`**; each carries **`data-v="<value>"`** (JS reads `querySelectorAll('.opts [data-v]')` and toggles `.sel`).
- Field groups use **`.field-group`** with **`.field-group-label`** and a **`.fg-sel-count`** counter; fields use **`.field`**; text inputs use **`.text-input`**.
- Required category headers use **`.req-cat-hdr`**.
- You may restyle all of these freely (colors, spacing, radius), but **keep the class names and `data-v`**.

## A.6 Voice system — keep intact
- Uses Web Speech API + the `/transcribe-voice` and `/parse-voice` endpoints, plus a large EN+Bangla keyword map (`SAY`) inside `rongberong.js` that maps spoken words → `[stateKey, value]` (e.g. `'শাড়ি'→['garment','Saree']`, `'রিল'→['output','video']`). **Don't touch this map.** Just keep `#mic`, `#transcript`, `#vlabel` present.

## A.7 i18n — keep intact
- All UI text comes from `lang/en.json` + `lang/bn.json` via `{{ __('key') }}` (Blade) and `window.__trans[key]` / `__(key)` (JS).
- **Never hardcode user-facing strings.** New labels → add keys to *both* json files and the `$jsKeys` array in `RongBerongController@index` (so they reach JS).
- Test every screen in EN and বাংলা; Bangla text is longer — allow wrapping.

## A.8 Acceptance checklist (must all pass after redesign)
1. Page loads, no console errors; `rongberong.js` initializes.
2. Voice: mic records → transcript fills → fields auto-select (try EN and a Bangla phrase).
3. Upload by file AND by URL both populate the preview and set `state.uploaded`.
4. Photo/Video toggle switches `state.output`; motion field appears only for video.
5. All option chips select/deselect and update `.fg-sel-count`.
6. Advanced section expands and its fields work.
7. Prompt preview builds; copy + save to library work; presets save/load.
8. **Generate (photo)** calls `/generate` and renders the result in `#stage`.
9. **Generate (video)** calls `/generate-video`, then polls `/video-status?op=` until done, then plays the reel.
10. Validation banner (`#req`) and errors (`#err`) still show when appropriate.
11. EN/বাংলা switch still works and persists.
12. Mobile layout usable; Generate reachable.

---

# PART B — THE NEW UI (visual target)

## B.0 The decision (Fotor vs RongBerong)
**Hybrid.** Adopt Fotor's **3-zone editor shell** (icon rail + config panel + always-visible canvas) — it fixes the current long-scroll where merchants lose sight of the result. Keep RongBerong's **brand** (sky-blue, Syne/Manrope/Fraunces, doodles, bilingual, voice-first). Reject a pure Fotor-clean clone and reject keeping the long form.

## B.1 Layout
```
┌──────────────────────────────────────────────────────────┐
│ TOP BAR 64px:  logo · ●badge          EN|বাংলা · Guide · Download · ⋯ │
├──────┬────────────────────┬───────────────────────────────┤
│ RAIL │  CONFIG PANEL      │   CANVAS (#stage)              │
│ 72px │  ~320px scroll     │   empty(#stageEmpty)→result    │
│      │  the step's fields │   + action bar (Generate #go)  │
└──────┴────────────────────┴───────────────────────────────┘
```
Grid: `grid-template-columns: 72px 320px 1fr; grid-template-rows: 64px 1fr;` top bar spans all.

**Rail items → which existing controls they reveal in the panel:**
| Rail | Reveals (existing IDs/sections) |
|---|---|
| Upload | `#upload`, `#file`, `#uploadClear`, `#uph`, `#imageUrlInput`/`#imageUrlLoad` |
| Describe | `#mic`, `#transcript`, `#vlabel`, `#chips` (quick presets) |
| Product | garment `.opts` + advanced garment fields (`fabric,pattern,fit,sleeve,neckline,embellishment,#colorInput`) |
| Model | `model` opts + `model_age,body_type,hair,makeup,expression,footwear` |
| Output | `#toggle` (Photo/Video), `#motionField`, `platform,aspect_ratio,branding_space,text_overlay`, `#promptToggle`/`#promptArea` |
| Generate | `#req`, `#approveContainer`, `#go` (or keep `#go` persistently in the canvas action bar) |

> Implementation tip: keep all panel sections in the DOM (so JS bindings exist); the rail just toggles which section is **visible** (`hidden` class / `display`), not whether it exists. This is the safest way to restructure without breaking bindings.

## B.2 Design tokens (RongBerong brand — keep)
```css
@theme {
  --color-accent:#0EA5E9; --color-accent-light:#38BDF8; --color-primary-light:#3B82F6;
  --color-bg:#F0F4FF; --color-bg-subtle:#F8FAFC; --color-surface:#FFFFFF;
  --color-text:#0F172A; --color-muted:#4A5568;
  --color-border:#DBEAFE; --color-border-strong:#BFDBFE;
  --color-success:#059669; --color-danger:#DC2626;
  --radius-xs:6px; --radius-sm:9px; --radius:12px;
  --shadow-sm:0 1px 2px rgba(30,64,175,.06),0 1px 3px rgba(30,64,175,.04);
  --shadow-md:0 4px 16px rgba(30,64,175,.09),0 2px 6px rgba(30,64,175,.05);
  --shadow-lg:0 8px 32px rgba(30,64,175,.11),0 4px 10px rgba(30,64,175,.06);
  --glow:0 0 0 3px rgba(29,78,216,.15); --ease-expo:cubic-bezier(.16,1,.3,1);
  --rainbow:linear-gradient(135deg,#FF6B6B,#FFA94D,#FFD43B,#69DB7C,#4DABF7,#9775FA,#E6007E);
  --font-display:"Syne",sans-serif; --font-sans:"Manrope",sans-serif; --font-serif:"Fraunces",serif;
}
```
Typography: Syne for logo/headings; Manrope for UI/body; Fraunces for editorial accents. Section headers = 12px/700 uppercase with a leading `●` dot. Match the approved `mockup-editor-shell.html`.

## B.3 Components (style to match the mockup)
- **Top bar:** rainbow logo mark + "RongBerong **AI**" (Syne) + `●` badge; right: EN|বাংলা pill switch, Guide, Download (disabled until result), `⋯`.
- **Icon rail:** 72px, Lucide line icons + 11px labels; active item = accent-tinted rounded square; completed steps get a ✓.
- **Config panel:** white, scrollable, `●`-prefixed section headers; reuse existing controls restyled — voice card (circular accent mic), preset chips, Photo/Video segmented toggle (active segment accent), dashed upload box + paste-URL, wrapping garment chips, Advanced expander, prompt preview, presets.
- **Canvas (`#stage`):** soft-blue bg with low-opacity doodles; empty state (`#stageEmpty`) = dashed frame + accent `+`, "Upload a product photo to start your AI studio shoot", upload button, sample thumbs; states: empty → uploaded → generating (skeleton + `#elapsedVal` timer) → result (photo `<img>` / reel `<video>`). Bottom **action bar** with `#go` Generate (gradient accent), zoom/before-after, download.
- **Buttons / inputs / chips:** per tokens; focus ring `--glow`; selected chip = accent outline+tint.

## B.4 Responsive (merchants are often mobile)
- ≥1280: all zones. 1024–1280: panel narrows.
- <1024: panel → slide-over drawer from rail; canvas full-width.
- <768: rail → bottom tab bar; panel → bottom sheet; **`#go` Generate sticky at bottom**; keep mic prominent.

## B.5 Motion
150ms hover, 200–250ms step/panel, 300ms drawer. `--ease-expo` for entrances. Result cross-fades into `#stage`. Honor `prefers-reduced-motion` (disable particles/ticker/transforms, keep fades). Keep the editor feeling instant — no scroll-reveal inside the editor.

---

# PART C — BUILD PLAN FOR CLAUDE CODE

**Recommended approach: restructure-in-place (lowest risk).**

1. **Read first:** `resources/views/rongberong/index.blade.php`, `public/js/rongberong.js`, `lang/en.json`, `lang/bn.json`, `RongBerongController.php`, `routes/web.php`. Build a map of every ID/class the JS uses (see §A.4–A.5).
2. **Tokens:** extend `resources/css/app.css` `@theme` with §B.2 (accent/fonts/shadows already partly exist).
3. **Componentize Blade** into partials under `resources/views/rongberong/partials/` (`topbar`, `rail`, `canvas`, `empty-state`, `config/{upload,describe,product,model,output,generate}.blade.php`) and compose them in `index.blade.php` inside the new grid shell. **Carry every existing ID/class/`data-v`/`__()` call into the new partials unchanged.**
4. **Keep the bootstrap `<script>` and both JS includes** (§A.1) and the CSRF meta tag.
5. **Rail↔panel visibility (tiny new JS, separate file e.g. `public/js/editor-shell.js`):** show/hide panel sections on rail click; persist current step in `localStorage`. **Do not modify `rongberong.js`.** If a binding *must* change, prefer adding a wrapper/alias over editing the engine.
6. **Move `#stage`/`#go` into the canvas zone** so results are always visible; ensure `#go` still triggers the existing generate handler (same element/id).
7. **Restyle** `.opt/.opts/.field-group/.text-input/#toggle button` etc. via CSS only — keep class names.
8. **i18n:** any new copy → add to both json + `$jsKeys`. No hardcoded strings.
9. **Run the §A.8 acceptance checklist** end-to-end in EN and বাংলা, desktop and mobile. Verify network calls hit `/generate`, `/generate-video`, `/video-status`, `/fetch-image`, `/transcribe-voice` with unchanged payloads.

**Do**
- ✅ Change layout, colors, spacing, structure, partials.
- ✅ Preserve every ID/class/`data-v`, endpoint, payload field, the `state` shape, voice map, and i18n.
- ✅ Match `mockup-editor-shell.html` visually.

**Don't**
- ❌ Rewrite `rongberong.js` logic, rename IDs/fields, or change endpoints/payloads.
- ❌ Introduce React/Vue or a new build system.
- ❌ Hardcode strings or use Fotor's green/logo/assets.
- ❌ Remove `window.__trans`/`__base`/`__hasApiKey` or the CSRF meta.

---

# PART D — Reference summary
- **Fotor** (layout ref only): 64px bar, 72px rail, ~290px panel, fluid canvas; pill buttons; card thumbnails; dashed empty state.
- **RongBerong** (preserve): Laravel 12 + Blade + Tailwind v4 + Vite; `rongberong.js` engine (state, EN/BN voice map, prompt builder, presets, prompt library); endpoints `/generate /generate-video /video-status /fetch-image /transcribe-voice /lang`; Gemini-powered; sky-blue brand; Syne/Manrope/Fraunces; bilingual; 20+ garments + deep advanced fashion fields.
- **This redesign:** Fotor's 3-zone shell, RongBerong's brand and *all* current functionality, achieved by restructuring the Blade markup around the existing JS contract — not by rewriting the engine.
```
