# Code Standards - Night Ninja: Twilight Voyage
## Naming Conventions
### Files
- **Svelte components**: PascalCase (`Game.svelte`, `GameBoard.svelte`, `PlayerSprite.svelte`)
- **JS modules**: kebab-case (`grid-system.js`, `turn-manager.js`, `level-manager.js`)
- **JSON/config**: kebab-case (`en.json`, `vi.json`, `theme.css`)
### Variables & Functions
- **Classes**: PascalCase (`GridSystem`, `Player`, `RotatingGuard`)
- **Methods & Functions**: camelCase (`updateLight()`, `nextTurn()`, `getText()`)
- **Constants**: UPPER_CASE for arrays (`LEVELS`), camelCase for others
- **Svelte state**: camelCase (`renderVersion`, `isPaused`, `detected`)
- **Props**: camelCase (`cellSize`, `oncellclick`, `onplayagain`)
### Grid Coordinates
- **row**: Vertical axis (0 = top, increases downward)
- **col**: Horizontal axis (0 = left, increases rightward)
- **Position objects**: `{ row: num, col: num }`
## Code Organization
### Directory Structure
```
src/
├── main.js # Entry point, mounts App.svelte
├── App.svelte # Scene router ({#key} + fade)
│
├── scenes/ # Full-page scene components
│ ├── MainMenu.svelte
│ ├── StoryIntro.svelte
│ ├── LevelIntro.svelte
│ ├── LevelSelect.svelte
│ ├── Game.svelte # Main gameplay (state owner)
│ ├── GameOver.svelte
│ ├── Settings.svelte
│ └── Guide.svelte
│
├── components/ # Reusable UI components
│ ├── Button.svelte
│ ├── GameBoard.svelte # Grid of pixel tiles
│ ├── GameHud.svelte # Pixel hearts + pixel icons + level/turns
│ ├── PlayerSprite.svelte # Pixel rabbit
│ ├── GuardSprite.svelte # Pixel veggie dispatched by guard.type
│ ├── PauseMenu.svelte
│ ├── DetectionPopup.svelte
│ ├── LevelCompletePopup.svelte
│ └── ControlsOverlay.svelte
│
├── lib/
│ ├── game/ # Pure JS game engine (no framework)
│ │ ├── grid-system.js
│ │ ├── player.js
│ │ ├── guards.js # Base + 6 guard subclasses; capture()/apply() contract
│ │ ├── turn-manager.js # Uses guard.capture()/apply() for non-destructive preview
│ │ ├── level-manager.js # GUARD_REGISTRY factory pattern
│ │ ├── game-history.js # Undo/redo system
│ │ ├── princess-mechanic.js # Level 12 escalating detection; capture()/apply()
│ │ └── touch-controls.js # Mobile swipe support
│ │
│ ├── pixel/ # Pixel-art rendering pipeline
│ │ ├── Pixel.svelte # String-art + palette → SVG rects
│ │ ├── palette.js # NNTV color constants
│ │ ├── art-characters.js # Rabbit, princess, 6 veggie guards
│ │ ├── art-tiles.js # 16×16 board tiles
│ │ ├── art-ui.js # Hearts, moon, logo, icons
│ │ └── art-scenes.js # 80×N act backdrops + sceneForLevel(n)
│ │
│ ├── levels/
│ │ └── levels.js # 12 level definitions
│ │
│ ├── locales/
│ │ ├── en.json
│ │ └── vi.json
│ ├── audio.js # Web Audio API sounds
│ ├── localization.js
│ └── progress.js
│
└── styles/
└── theme.css # CSS variables (colors, fonts)
```
### File Size Limits
- **Maximum 200 lines per file** before considering split
- Scenes with heavy logic → extract to `lib/game/`
- Shared UI → extract to `components/`
## Svelte 5 Patterns
### State Management
```javascript
// Primitive state
let isPaused = $state(false);
// Class instances (NOT auto-proxied — use renderVersion pattern)
let grid = $state(null);
let player = $state(null);
let renderVersion = $state(0);
// Derived values depend on renderVersion to pick up class mutations
let cells = $derived((renderVersion, grid ? grid.getAllCells() : []));
```
### Props
```javascript
let { navigate, level = 1, lives = 3 } = $props();
```
### Event Handlers
```svelte