# Plan: Fire Show Calculator (mardis_calc)

## Context

New project: a single-page web calculator for fire show budgeting. The page must calculate one unknown variable from all known ones using the formula `S = Pz + Tz + (Lz * Nl) + Rom + Rop + Rot + Rok + (Na * Z)`. Royalties are fixed percentages calculated from the net amount after material costs (`Base = S - Pz - Tz - Lz*Nl`). The UI must be built with `gnexus-ui-kit` (added as a git submodule). The page is a plain static HTML+JS app (no build system). Artists are stored in a local JSON file (names only). The calculator should show how much each assigned artist receives (salary + any assigned royalties). State must be persisted to `localStorage`, plus export/import as JSON.

## Key clarifications

- UI kit: add as git submodule (`https://git.gnexus.space/root/gnexus-ui-kit`).
- Royalties base: `Rom/Rop/Rot/Rok` are percentages of `Base = S - Pz - Tz - Lz*Nl`.
- One unknown at a time: when all fields but one are filled, auto-calculate the missing variable.
- Artists can have multiple roles: e.g. one person can be both an artist (gets `Z`) and a director (gets `Rop`), etc.
- Rounding: to 2 decimal places (cents).
- Persistence: `localStorage` + JSON export/import.
- Artists JSON: array of objects with at least `{ "name": "..." }`.

## Architecture

Single static page. No bundler. Use vanilla JS.

### Files

1. **`.gitmodules`** (via `git submodule add`) — link `gnexus-ui-kit`.
2. **`index.html`** — main page, loads UI kit assets from submodule path, app CSS/JS.
3. **`css/styles.css`** — minimal custom styles on top of UI kit.
4. **`js/app.js`** — all calculator logic.
5. **`data/artists.json`** — embedded artist list.

### UI layout

- **Header**: project title.
- **Inputs section**: numeric inputs for `S`, `Pz`, `Tz`, `Lz`, `Nl`, `Z`. `Na` and royalty fields (`Rom`, `Rop`, `Rot`, `Rok`) are **read-only / computed**.
  - `Na` auto-updates from the artist roster table (count of rows with "Artist" role checked).
  - Royalties auto-calculate from `Base`.
  - When 5 of the 6 editable fields are filled, the 6th is computed on blur/change.
- **Artist roster section**:
  - Add-artist dropdown (populated from `data/artists.json`).
  - Table of added artists with role checkboxes: Artist, Director (`Rop`), Technician (`Rot`), Commissioner (`Rok`), Organizer (`Rom`).
  - Each row shows the individual payout (sum of applicable shares).
- **Actions**: Export JSON, Import JSON, Reset.
- **Summary**: total show cost `S`, total material costs, total artist salaries, total royalties.

### Calculation logic

**Definitions:**
- `Materials = Pz + Tz + Lz * Nl`
- `Base = S - Materials`
- `Rom = 0.10 * Base`
- `Rop = 0.05 * Base`
- `Rot = 0.05 * Base`
- `Rok = 0.10 * Base`
- `TotalRoyalties = Rom + Rop + Rot + Rok = 0.30 * Base`
- `ArtistSalaries = Na * Z`

**Identity:**
`S = Materials + TotalRoyalties + ArtistSalaries`
=> `S = Materials + 0.30 * (S - Materials) + Na * Z`
=> `0.70 * S = 0.70 * Materials + Na * Z`
=> `S = Materials + (Na * Z) / 0.70`

**Solving for each variable (when all others are known):**
- `S = Materials + (Na * Z) / 0.70`
- `Z = (0.70 * (S - Materials)) / Na` (if `Na > 0`)
- `Na = (0.70 * (S - Materials)) / Z` (displayed as decimal guidance)
- `Pz = S - (Tz + Lz*Nl) - (Na*Z)/0.70`
- `Tz = S - (Pz + Lz*Nl) - (Na*Z)/0.70`
- `Lz = (S - Pz - Tz - (Na*Z)/0.70) / Nl` (if `Nl > 0`)
- `Nl = (S - Pz - Tz - (Na*Z)/0.70) / Lz` (if `Lz > 0`)

**Validation / guardrails:**
- Negative results are flagged as errors (real-world values must be non-negative).
- Division-by-zero protected.
- If more than one field is empty, show a message like "Заполните все поля кроме одного" instead of computing.

**Roster payout per person:**
- If role "Artist" checked: add `Z`.
- If role "Organizer" (`Rom`) checked and only one such person: add `Rom`. If multiple organizers, split equally (or assign full to each? To be safe, split equally; UI can note this).
- Same splitting logic for `Rop`, `Rot`, `Rok` if multiple persons share the same role.

### Persistence

- On every change, serialize the state (all input values + artist roster table) to `localStorage` key `mardis_calc_state`.
- On page load, restore from `localStorage` if present.
- **Export**: trigger browser download of a `.json` file containing the serialized state.
- **Import**: read a `.json` file via `<input type="file">`, validate structure, replace current state.

## Verification

1. Open `index.html` in a browser.
2. Fill in `Pz=100`, `Tz=50`, `Lz=30`, `Nl=2`, `Na=2`, leave `S` empty. `S` should auto-calculate to `100 + 50 + 60 + (2*Z)/0.70` depending on `Z`.
3. Add artists from the dropdown, assign roles, verify individual payouts sum up to `ArtistSalaries + TotalRoyalties`.
4. Refresh the page; values should restore from `localStorage`.
5. Click Export, save JSON, clear fields, click Import with that file, verify restoration.

## Risks / open questions

- `gnexus-ui-kit` submodule path and exact CSS/JS files to include are unknown until the submodule is fetched; may need minor path adjustments in `index.html` after adding it.
- Splitting royalties among multiple persons with the same role: plan assumes equal split. User can adjust later if needed.
