# Copilot Instructions — fvtt-chroniques-de-l-etrange

FoundryVTT v13 game system for *Les Chroniques de l'Étrange* (Antre-Monde Éditions). The codebase is entirely in **ES modules** (`"type": "module"`) bundled with esbuild. There are no tests.

## Build commands

```bash
npm run build          # compile LESS → CSS and bundle src/system.js → dist/system.js
npm run build:css      # LESS only
npm run build:js       # esbuild bundle only
npm run build:watch    # rebuild on file changes
npm run build:full     # compile compendiums then build

npm run pack:compile   # compile packs-src/ → packs/ (LevelDB)
npm run pack:extract   # extract packs/ → packs-src/ (YAML source)
```

The built output goes to `dist/system.js` (sourced via the unbuilt `src/system.js` in `system.json` `esmodules`).

## Architecture

The entry point is `src/system.js`, which wires up all FoundryVTT hooks (`init`, `ready`, `renderChatLog`, etc.).

### Layer structure

| Layer | Path | Purpose |
|---|---|---|
| **Config** | `src/config/` | Constants, i18n pre-localization, runtime config, settings |
| **Data Models** | `src/data/` | `TypeDataModel` subclasses defining actor/item schemas |
| **Documents** | `src/documents/` | `CDEActor`, `CDEItem`, `CDEMessage` — thin document class overrides |
| **UI / Sheets** | `src/ui/sheets/` | ApplicationV2 sheets for actors and items |
| **UI / Apps** | `src/ui/apps/` | Standalone apps: `CDELoksyuApp`, `CDETinjiApp` (singletons) |
| **UI / Core** | `src/ui/` | Rolling engine, dice registration, Handlebars helpers, initiative |

### Key domain concepts

- **Wu Xing cycle**: Five aspects (metal, water, earth, fire, wood) drive all dice resolution. Each aspect maps to two d10 faces (see `ASPECT_FACES` in `constants.js`). `WU_XING_CYCLE` maps an active aspect to the five result categories: successes / auspicious / noxious / **loksyu** / **tinji**.
- **Loksyu / Tin Ji**: Persistent world-level counters stored in game settings (`loksyuData`, `tinjiData`). Managed via `CDELoksyuApp` / `CDETinjiApp` singleton apps; updated from roll results in `ui/apps/singletons.js`.
- **Three Treasures** (`threetreasures`): The character's Hei-Yang and Hei-Yin pools plus dice-level branches — used as the primary/secondary token attribute.
- **Magics**: Five schools (`internalcinnabar`, `alchemy`, `masteryoftheway`, `exorcism`, `geomancy`), each with five specialities. Fully defined in `MAGICS` constant.

### Data model pattern

All data models live in `src/data/` and extend `foundry.abstract.TypeDataModel`. Schema fields are defined with local factory helpers (`numberField`, `stringField`, `boolField`, `htmlField`) — prefer reusing these helpers when adding new fields.

### Sheet pattern

Actor and item sheets extend `HandlebarsApplicationMixin(ActorSheetV2)` via `CDEBaseActorSheet` (`src/ui/sheets/actors/base.js`). Key conventions:
- `static DEFAULT_OPTIONS` with `form: { submitOnChange: true }` — forms auto-save on every change.
- Tab state is manually restored in `_onRender` by iterating `this.tabGroups` and calling `this.changeTab()` (AppV2 does not persist tab state natively).
- Sheet actions (create/edit/delete item, editImage) are static private methods registered in `DEFAULT_OPTIONS.actions`.
- `_prepareContext()` exposes both `system` and `systemData` (same reference) for template compatibility.

### Compendium source

Human-editable compendium content lives in `packs-src/` as YAML. Use `npm run pack:compile` before building when pack content has changed, and `npm run pack:extract` after importing new data in Foundry.

## Key conventions

- All user-visible strings go through i18n with the `CDE.` prefix namespace. New labels must be added to `lang/fr-cde.json`.
- Handlebars templates live in `templates/` and are referenced by their full system path (`systems/fvtt-chroniques-de-l-etrange/templates/...`). Partials are pre-registered from `TEMPLATE_PARTIALS` in `constants.js`.
- The system ID constant (`SYSTEM_ID = "fvtt-chroniques-de-l-etrange"`) is used everywhere — never hardcode the string.
- CSS is authored in LESS (`css/cde-theme.less`) and compiled to `css/cde-theme.css`. Do not edit the `.css` file directly.
- Global macro access is via `game.cde` (exposes `CDELoksyuApp` and `CDETinjiApp`).
- The `dist/` directory is generated — do not commit it manually; it is rebuilt by `npm run build`.
