# Architecture Build target: static browser page. No bundler. Globals and ordered deferred scripts are intentional. Current inspected version: `15.24.33`. ## Load order `app_manifest.json` owns CSS/JS order. Regenerate `index.html` and `service-worker.js` with `python3 scripts/generate_app_files.py` after version/order changes. `js/version.js` exposes `TARINAI_APP.version`, cache name, and query helper. The old `css/styles.css` compatibility shim and `js/ui_family.js` split marker have been removed. The family tree entry point now starts at `ui_family_data.js` and continues through async/layout/path/render modules. ## Runtime objects - `World`: constructor in `js/world.js`; methods split into view, family/social, combat/effects, environment, spatial/budget, ants, update, placement/log, bootstrap. - `Tarinai`: constructor in `js/tarinai.js`; methods split into identity/social, disease/nest, item effects, needs/items, social/move/life, render. - Behavior text is composed from `behavior`, needs, tied needs, ActionSpec metadata, and forced-request cause metadata; stored explicit live text remains the display fallback to avoid player-visible wording churn. - `Item`: item state, lifecycle, scaling, and field rendering in `js/items.js`. - `Effect`: transient visuals in `js/sim_core.js`; combat/weather/food effects are spawned through `World` helpers. - `TarinaiEvents`: global event bus for logs, terrain dirtiness, audio failures, phase/performance changes. - `TarinaiPerformance`: FPS quality manager; provides effect caps, ant stride, terrain redraw cadence, UI intervals. - `TarinaiInputMode`: input classification and mobile-mode state. UI code reads this manager instead of duplicating touch heuristics. - `TarinaiWeatherSystem`: weather transitions and rain-spawned water item creation. Rain overlay drawing remains in `render.js`. ## Startup path `main.js` owns the user-visible boot sequence: 1. Start the loading showcase and preload the initial sprite/image set through `loadImages`. 2. Bind UI, apply the default `garden` field layout, reset the world, and select `observe`. 3. Render logs, family archive, first frame, and stats. 4. Start deferred background image loading, enter `requestAnimationFrame(loop)`, and hide the loading screen. 5. Register `service-worker.js` with `updateViaCache: "none"` after window load. ## Data ownership - `js/data.js`: base item/tool definitions, `TOOL_CATEGORIES`, config, image metrics, field presets. - `js/item_visual_registry.js`: canonical item visual descriptors used by field drawing and generated tool-icon previews. - `js/food_registry.js`: food/medicine semantics such as labels, serving classes, decay multipliers, and hygiene penalties. - `js/disease_registry.js`: disease labels, flags, display metadata, cure-rule notes, and mystery-drug eligibility. - `js/input_mode_manager.js`: touch/mobile classification, mobile mode persistence, and gesture capability policy. - `js/weather_system.js`: weather state transitions and rain-water item spawning. - `js/text_catalog.js`: Japanese UI copy/tooltips. Keep JS strings escaped where existing style uses escapes. - `js/effect_registry.js`: item-effect labels, colors, modifiers, exclusivity/removal metadata, behavior callbacks (`onApply`, `onTick`, `onRemove`), direct eating context, and random-effect candidates. - `js/sound_pack.js`: canonical sound metadata: IDs, categories, gain multipliers, cooldowns, optional sample paths, and ID-to-category mapping. - `FIELD_TYPES` in `js/data.js`: cage/garden/park field labels, responsive heights, world scale, starting population, and initial grass. ## State loops `main.js` starts asset preload, world bootstrap, animation loop, deferred image loading, service-worker registration. `World.update(dt)` advances time, weather, items, ants, Tarinai, effects, budgets, terrain dirtiness. `render()` draws cached background/terrain, visible entities, weather overlay, cards, HUD, and debug overlays. World time is `CONFIG.dayLength` seconds per day. Version `15.24.33` uses 120 seconds/day and weather changes every 46-96 seconds. The phase boundary rules live in `World.phaseName()`. Domain events are emitted at central mutation points: placement, eating, decay, effect apply/remove, disease infect/cure, damage/death/birth, fight hit/loss/end, ant spawn/grab/carry/death, weather changes, and rain item drops. Logs/audio still use direct calls where they already existed; do not add duplicate log or sound side effects when subscribing to these events. Ant behavior remains intentionally conservative. `ANT_EXTENSION_HOOKS` names future ecology slots for nest hunger, nest growth, queen reproduction, worker lifecycle, carrying success, and territorial behavior, but this pass does not rebalance those mechanics. ## Spatial/performance rules Use `World.nearby*` helpers rather than full-array scans in hot paths. Terrain cache uses dirty/version flags; do not reintroduce every-frame full terrain hashing. Performance degradation should be centralized in `performance_manager.js`. Family tree rendering is intentionally asynchronous and cached. `ui_family_async.js` chunks component discovery with `requestIdleCallback` when available; `ui_family_render.js` hydrates cached HTML, keeps archive dirty/version state, and exposes `validateFamilyTree()` plus `familyTreeDiagnostics()` for browser-console checks. ## Basic ActionSpec migration Version `15.24.33` keeps low-risk need actions, social/fear/combat/mate/birth actions, and sunbath registered through ActionSpec factories. The former configureTarinaiNeedActions late-binding bridge has been removed; the existing sunbath subsystem remains as the body-level timer implementation called by the ActionSpec. ## Runtime diagnostics `World.runtimeDiagnostics()` exposes spatial rebuild counters, draw-list status, item bucket counts, and behavior counts. `?debug=1` renders these values in the existing debug overlay for manual browser regression checks. ## Social balance guards Version `15.24.33` adds explicit guardrails around combat-heavy social behavior. Normal conflict must be dominant over bond/mate/family pressure before `fight_rival` can start, and `World.startFight()` / `startConflict()` / `startForcedFight()` use pair-level cooldowns plus already-fighting checks to prevent burst re-entry. Fight mochi remains a strong forced exception, but ordinary proximity conflict is intentionally lower than mate/friend pressure. ## Pre-save runtime polish Version `15.24.33` keeps item type buckets and item id lookup as runtime caches owned by `World.updateItemCounts()`. Runtime item additions should go through `World.addItem(item, reason)` when practical so spatial, terrain, and item-bucket invalidation stay synchronized. Save migration is still intentionally deferred until this runtime shape has been browser-observed.