# Backdrop

A 3D-only *environment / atmosphere* component shaped as a 6-sided box
(4 walls + floor + ceiling). It establishes the **visual setting** of the
scene — warehouse hall, cleanroom, showroom, etc. — by surrounding the
viewing camera with inside-facing surfaces.

Backdrop is **not** a structural container; it does not manage children.
Its sole purpose is visual. Place real components freely *inside* the
backdrop's volume — the backdrop is just the wallpaper.

## Visibility

Backdrop is **3D-only**. It is invisible and non-selectable on the 2D
canvas by design. To work with a backdrop, switch the modeler to 3D mode.

- 2D canvas — no paint, no click target
- 3D mode — a 6-faced envelope visible from inside; a small *editor
  selection handle* sphere is the click target. The envelope faces
  themselves are non-raycastable so contents inside stay selectable.

## Per-face state — `state.faces`

Each of the six faces is configured independently:

```
state.faces = {
  east:    { fillStyle, visible, alpha, rotation, mirror },
  west:    { fillStyle, visible, alpha, rotation, mirror },
  north:   { ... },
  south:   { ... },
  floor:   { ... },
  ceiling: { ... },
}
```

| field        | meaning                                                                                                            |
| ------------ | ------------------------------------------------------------------------------------------------------------------ |
| `fillStyle`  | Face color or texture (`#RGB` / `rgba(...)` / pattern / image url). rgba alpha is reflected in material opacity.   |
| `visible`    | Toggle the face on/off without losing its settings.                                                                |
| `alpha`      | Per-face opacity multiplier (0–1). Combined with `fillStyle.alpha`.                                                |
| `rotation`   | Texture rotation (0 / 90 / 180 / 270). Default `0`.                                                                |
| `mirror`     | Horizontal mirror (boolean). Combined with `rotation` covers all 8 dihedral orientations.                          |

The engine automatically applies an *inside-view U-flip* to every face so
that `rotation=0, mirror=false` reads as "right-side-up from inside the
box". Three.js `BoxGeometry` 's default UV is outside-oriented and would
otherwise look horizontally flipped when viewed from inside.

### Compass mapping (things-scene 2D → 3D)

```
2D left → 3D +x   ⇒  east  = +X
2D top  → 3D +z   ⇒  south = +Z   (= "down on screen" = south)
                      north = −Z
```

This matches map convention — "top of the 2D plan" is north.

## Component-level state

| property      | meaning                                                                                                            |
| ------------- | ------------------------------------------------------------------------------------------------------------------ |
| `fitToBoard`  | If `true`, envelope auto-fits to the rootModel's `width / height` and pins the plan position to the world origin. Board resize is listened to and the mesh rebuilds. |
| `seeThrough`  | If `true` (default), back faces are culled — useful when the camera is *outside* the backdrop looking in. Set `false` for sealed 360° virtual environments. |
| `alpha`       | Global opacity multiplier on top of per-face alpha.                                                                |
| `width / height / depth` | Envelope size when `fitToBoard` is off.                                                                |

Vertical position follows the scene-level `state.placement` (`'floor'` /
`'space'` / `'inverted'`) — backdrop is anchored consistently with all
other components of the same placement.

## fit-to-board

`fitToBoard = true` is the typical setup: the backdrop becomes a *wallpaper
envelope* that wraps the entire board. You can leave board size as the
single source of truth and the backdrop adapts.

- Initial depth on `OFF → ON` transition: `min(width, height)`.
- After that, depth is left alone so manual edits via the property panel
  stick.

## Edge outline

A guide-only edge outline is drawn while `app.isEditMode === true` to help
identify the envelope during editing. At runtime the outline disappears —
the face fills alone communicate the volume.

## Tips

- If a face texture looks mirrored after assigning an image, flip the
  `mirror` boolean on that face (or rotate 180°).
- For a semi-transparent atmospheric tint (e.g. a subtle warehouse
  ambience), use `rgba(...)` directly in `fillStyle` instead of touching
  the global `alpha` — keeps colour and translucency under one knob.
- Set `seeThrough = false` only when you genuinely want a sealed
  environment (e.g. inside a virtual room with no outside view).
- Use one backdrop per scene. Stacking backdrops is allowed but typically
  obscures parts of each other.
