# Panel System — Pact Rules

## Functional rules (MUST)

```
F-Panel-Create-001: PanelSystem.createPanel(spec) MUST return a panel object with id, state, dockEdge, size, tabs, isFocused.
F-Panel-Destroy-001: PanelSystem.destroyPanel(id) MUST remove the panel and emit panel:destroyed.
F-Panel-Float-001: PanelSystem.float(id) MUST change state to 'floating' and emit panel:float.
F-Panel-Pin-001: PanelSystem.pin(id, edge) MUST change state to 'pinned-L' or 'pinned-R' and emit panel:pin.
F-Panel-Dock-001: PanelSystem.dock(id, edge) MUST change state to 'docked-T', 'docked-B', 'docked-L', or 'docked-R' and emit panel:dock.
F-Panel-Min-001: PanelSystem.minimize(id) MUST change state to 'minimized' and emit panel:minimize, UNLESS operatingMode === 'pro' (then return pro_mode_locked).
F-Panel-Max-001: PanelSystem.maximize(id) MUST change state to 'maximized' and emit panel:maximize.
F-Panel-Resize-001: PanelSystem.resize(id, opts) MUST update size and emit panel:resize.
F-Panel-List-001: PanelSystem.list() MUST return an array of all panels with their current state.
F-Panel-Event-001: PanelSystem.on(event, cb) MUST register an event listener.
F-Pro-Lock-001: When operatingMode === 'pro', panel-system.minimize() MUST return { ok: false, reason: 'pro_mode_locked' }.
```

## Invariant rules (MUST NOT violate)

```
I-Panel-001: No panel may be in an invalid state (e.g. 'floating' with a dockEdge).
I-Panel-002: No panel may exceed viewport bounds.
I-Panel-003: No panel may overlap another docked panel on the same edge.
I-Panel-004: Pill state MUST match panel state (if panel is minimized, pill is visible; if panel is open, pill is hidden).
I-Panel-005: Tabs inside a panel MUST reference modules, NOT other panels.
I-Panel-006: No panel may be created without a unique id.
```

## Mobile rules

```
F-Panel-Mobile-001: When window.innerWidth < 600 and a panel is pinned L or R, the panel MUST reveal at 45% of viewport width (capped at 600px).
I-Panel-Mobile-001: No panel may exceed 95% of viewport width on mobile.
```
