diff --git a/assets/ui/tool_poke.png b/assets/ui/tool_poke.png index 6afa389..a63c6b0 100644 Binary files a/assets/ui/tool_poke.png and b/assets/ui/tool_poke.png differ diff --git a/css/styles.css b/css/styles.css index c79b88b..0b413e8 100644 --- a/css/styles.css +++ b/css/styles.css @@ -106,17 +106,63 @@ h1 { border-radius: calc(var(--radius) + 8px); overflow: hidden; box-shadow: 0 16px 42px rgba(42, 45, 80, 0.12), inset 0 0 0 1px rgba(255,255,255,0.24); - min-height: 620px; + min-height: var(--field-min-height, 620px); } #gameCanvas { width: 100%; - height: calc(100vh - 140px); - min-height: 620px; + height: var(--field-height, calc(100vh - 140px)); + min-height: var(--field-min-height, 620px); display: block; cursor: crosshair; } +.field-dialog { + position: fixed; + inset: 0; + z-index: 30; + display: grid; + place-items: center; + padding: 18px; + background: rgba(34, 29, 22, 0.38); + backdrop-filter: blur(3px); +} +.field-dialog.hidden { display: none; } +.field-dialog-panel { + width: min(440px, 100%); + border-radius: 16px; + padding: 16px; + background: rgba(255, 252, 245, 0.96); + border: 1px solid rgba(84,68,48,0.16); + box-shadow: 0 18px 46px rgba(40, 32, 24, 0.22); +} +.field-dialog-panel h2 { + margin: 0 0 12px; + font-size: 17px; +} +.field-choice-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 8px; +} +.field-choice { + min-height: 74px; + border: 1px solid rgba(84,68,48,0.16); + border-radius: 12px; + background: linear-gradient(180deg, rgba(255,255,255,0.86), rgba(241,235,221,0.72)); + cursor: pointer; + color: var(--ink); +} +.field-choice:hover { border-color: rgba(112,178,66,0.45); } +.field-choice strong, .field-choice span { display: block; } +.field-choice strong { font-size: 15px; } +.field-choice span { margin-top: 4px; color: var(--muted); font-size: 12px; } +.field-dialog-actions { + margin-top: 12px; + display: flex; + justify-content: flex-end; +} + .toast { position: absolute; left: 50%; @@ -378,8 +424,9 @@ meter { .topbar { align-items: flex-start; flex-direction: column; } .layout { grid-template-columns: 1fr; } .panel { max-height: none; overflow: visible; } - #gameCanvas { height: 66vh; min-height: 460px; } - .stage-wrap { min-height: 460px; } + #gameCanvas { height: var(--field-mobile-height, 66vh); min-height: var(--field-mobile-min-height, 460px); } + .stage-wrap { min-height: var(--field-mobile-min-height, 460px); } + .field-choice-grid { grid-template-columns: 1fr; } } @@ -415,7 +462,7 @@ meter { max-height: 560px; min-height: 320px; overflow: auto; - overscroll-behavior: contain; + overscroll-behavior: auto; padding: 8px 4px 16px; background: rgba(255,250,244,0.48); border-radius: 14px; @@ -497,13 +544,13 @@ body::before { } .family-node { display: grid; - grid-template-columns: 26px minmax(0, 1fr); + grid-template-columns: 22px minmax(0, 1fr); align-items: center; - gap: 6px; + gap: 5px; min-width: 0; - min-height: 42px; - padding: 5px 7px; - border-radius: 11px; + min-height: 34px; + padding: 4px 6px; + border-radius: 10px; background: linear-gradient(180deg, rgba(255,253,248,0.96), rgba(248,241,229,0.90)); border: 1px solid rgba(84,68,48,0.14); box-shadow: 0 3px 8px rgba(64,48,32,0.045); @@ -539,7 +586,7 @@ body::before { .family-node[data-family-tarinai-id]:hover { transform: translateY(-1px); border-color: rgba(112,178,66,0.42); box-shadow: 0 5px 12px rgba(64,48,32,0.08); } .family-node.dead { opacity: 0.68; filter: grayscale(0.35); } .family-node.missing { opacity: 0.48; border-style: dashed; } -.family-node img { width: 26px; height: 26px; object-fit: contain; } +.family-node img { width: 22px; height: 22px; object-fit: contain; } .family-copy { min-width: 0; line-height: 1.12; } .family-copy strong, .family-copy span { display: block; @@ -551,11 +598,12 @@ body::before { white-space: normal; overflow: visible; text-overflow: clip; - line-height: 1.18; + line-height: 1.12; + margin-top: 1px; color: rgba(126, 80, 64, 0.92); } -.family-copy strong { font-size: 12px; } -.family-copy span { color: var(--muted); font-size: 9px; margin-top: 2px; } +.family-copy strong { font-size: 11px; } +.family-copy span { color: var(--muted); font-size: 8.5px; margin-top: 1px; } @media (max-width: 760px) { .family-grid { grid-template-columns: 1fr; } .family-cluster { min-height: 102px; } @@ -653,8 +701,8 @@ body::before { align-items: stretch; } .family-node.lineage-node { - width: 154px; - min-height: 76px; + width: 132px; + min-height: 54px; align-items: flex-start; } .lineage-children { @@ -698,8 +746,8 @@ body::before { .lineage-links .child-link { stroke-width: 1.9; stroke: rgba(107, 88, 61, 0.54); } .tree-node { position: absolute; - width: 154px; - min-height: 76px; + width: 132px; + min-height: 54px; align-items: flex-start; z-index: 2; } @@ -712,3 +760,111 @@ body::before { z-index: 1; } .lineage-family { overflow-x: auto; } + +.lineage-family-readable { + overflow: visible; +} +.lineage-readable-grid { + display: grid; + grid-template-columns: minmax(300px, 1.05fr) minmax(280px, 0.95fr); + gap: 12px; + align-items: start; +} +.lineage-member-column, +.lineage-reproduction-column { + min-width: 0; +} +.lineage-generation-block { + padding: 8px 0; + border-top: 1px dashed rgba(84,68,48,0.12); +} +.lineage-generation-block:first-child { border-top: 0; padding-top: 0; } +.lineage-generation-block > b, +.lineage-column-title { + display: block; + margin: 0 0 7px; + color: rgba(84,68,48,0.72); + font-size: 11px; +} +.lineage-person-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); + gap: 7px; +} +.family-node.lineage-person { + width: auto; + min-height: 46px; +} +.lineage-pair-list { + display: grid; + gap: 8px; +} +.lineage-pair-card { + padding: 8px; + border-radius: 12px; + border: 1px solid rgba(84,68,48,0.12); + background: rgba(255,253,248,0.70); +} +.lineage-pair-parents, +.lineage-pair-children { + display: flex; + flex-wrap: wrap; + gap: 5px; + align-items: center; +} +.lineage-pair-parents { + padding-bottom: 5px; +} +.lineage-pair-children { + padding-top: 5px; + border-top: 1px solid rgba(84,68,48,0.08); +} +.lineage-plus { + color: rgba(84,68,48,0.44); + font-weight: 700; + line-height: 28px; +} +.lineage-birth-arrow { + color: rgba(107, 88, 61, 0.62); + font-size: 14px; + line-height: 1; + padding: 1px 0 3px 13px; +} +.lineage-mini { + display: inline-grid; + grid-template-columns: 20px minmax(0, 1fr); + grid-template-rows: auto auto; + gap: 0 4px; + align-items: center; + max-width: 132px; + min-width: 88px; + padding: 4px 6px; + border-radius: 9px; + border: 1px solid rgba(84,68,48,0.12); + background: rgba(255,255,255,0.64); +} +.lineage-mini.child { + border-color: rgba(103,178,44,0.28); + background: rgba(246,255,235,0.62); +} +.lineage-mini.dead { opacity: 0.64; filter: grayscale(0.25); } +.lineage-mini img { + grid-row: 1 / span 2; + width: 20px; + height: 20px; + object-fit: contain; +} +.lineage-mini b, +.lineage-mini small { + display: block; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.lineage-mini b { font-size: 10px; line-height: 1.1; } +.lineage-mini small { color: var(--muted); font-size: 8px; line-height: 1.1; } + +@media (max-width: 760px) { + .lineage-readable-grid { grid-template-columns: 1fr; } +} diff --git a/docs/code_map.md b/docs/code_map.md new file mode 100644 index 0000000..2ba87a2 --- /dev/null +++ b/docs/code_map.md @@ -0,0 +1,29 @@ +# Code Map + +Use this map to open the smallest relevant file first. + +## Simulation +- `js/sim_core.js`: shared simulation helpers, personality definitions, `Effect`, `SpatialGrid`, and small drawing helpers used by simulation classes. +- `js/items.js`: `Item` lifecycle, item save/load restore, grass and zunchi behavior, and item drawing. +- `js/tarinai.js`: `Tarinai` state, AI, movement, eating, fighting, panic, reproduction-adjacent behavior, and drawing. +- `js/world.js`: `World` state, save/load, spawning, family registry normalization, spatial queries, tools, weather, and update loop coordination. +- `js/sim.js`: compatibility export for `window.TarinaiSim`. + +## UI And Rendering +- `js/render.js`: canvas scene rendering, lighting, weather visuals, HUD, and selected-card overlay. +- `js/ui.js`: DOM references, selected/log panels, labels, save/load buttons, tool controls, canvas input, and UI event binding. +- `js/ui_charts.js`: colony history aggregation and chart rendering. +- `js/ui_family.js`: family tree components, layout, archive rendering, and validation helper. +- `js/ui_exports.js`: compatibility export for `window.TarinaiUI`. + +## Common Tasks +- Change hunger, sleep, fighting, panic, eating, or movement: start with `js/tarinai.js`. +- Change item growth, zunchi lifecycle, grass spread, or item visuals: start with `js/items.js`. +- Change save/load, population, spawning, weather, tools, or family data correctness: start with `js/world.js`. +- Change family tree display only: start with `js/ui_family.js`. +- Change colony charts: start with `js/ui_charts.js`. +- Change buttons, selected info, logs, or input handling: start with `js/ui.js`. +- Change the garden canvas visuals: start with `js/render.js`. + +## Loading Order +`index.html` loads plain browser scripts in dependency order. Do not convert to ES modules or add a build step unless the project intentionally adopts one later. diff --git a/docs/design_notes.md b/docs/design_notes.md index aa580fe..2b1c1e8 100644 --- a/docs/design_notes.md +++ b/docs/design_notes.md @@ -101,7 +101,7 @@ 繁殖で生まれた子は `childGrowTime` の間、親のどちらか近い方を追従する。成長すると通常AIへ移行する。 ### 系譜 -系譜は `family` レジストリで保持し、親子関係を樹状図で表示する。二親制のため、同じ子が複数枝に表示される場合がある。 +系譜は `family` レジストリで保持し、親子関係を樹状図で表示する。表示時は同じ個体を重複させず、共有された親子関係は複数の接続線で表す。 ### 食事エフェクト 食事パーティクルは表示頻度を抑え、対象アイテムの色を反映する。 diff --git a/index.html b/index.html index fc5f1fc..7cef262 100644 --- a/index.html +++ b/index.html @@ -56,7 +56,7 @@