refactor: centralize brand, company info, assets and Persian strings

Phase 1 of turning the game into the company landing page.

- Add src/config/company.js with name, tagline, contact, about and the
  product line, plus a brand palette built around #00a693 (contrast
  checked); placeholders are marked TODO(company).
- Add src/config/assets.js listing every loaded file with its expected
  format; placeholders are marked TODO(asset).
- Move all Persian interface text, dialogue, missions and scenery text
  into src/i18n/fa.js; components and game code read from it.
- Expose the palette as CSS variables (--color-primary and shades) and
  Tailwind colours, and use it for 3D materials and map drawings.
- Fix the arrival line that still called the manager's car a white
  pickup.
- Add tests that block hard-coded Persian text and low-contrast colours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 08:13:00 +03:30
co-authored by Claude Opus 5.5
parent e02347142b
commit 8dbaf3d97e
54 changed files with 1184 additions and 486 deletions
+10 -13
View File
@@ -1,4 +1,6 @@
import { GameNode } from '@/components/shared/GameNode.jsx';
import { strings } from '@/i18n/fa.js';
import { robotFace } from '@/config/assets.js';
/** @typedef {{nodes:object,actions:object}} RealIntroDialogProps */
/** Presents the RealIntroDialog view using plain models and semantic native elements.
* @param {RealIntroDialogProps} props - Interface snapshots and callbacks.
@@ -13,18 +15,13 @@ export function RealIntroDialog({ nodes, actions }) {
model={nodes['real-intro']}
onClose={() => actions.close('real-intro')}
>
<img src="./robot/serious.webp" alt="" width="72" height="68" />
<h2>{'بازی در دنیای واقعی'}</h2>
<p>
{
'با روشن کردن این حالت، موقعیت گوشی شما (GPS) روی نقشهٔ بازی نمایش داده می‌شود. وقتی واقعاً به محل یک دستگاه روبات مارکت برسید، می‌توانید خرید کنید و ۲۰۰ امتیاز اضافه بگیرید.'
}
</p>
<img src={robotFace('serious')} alt="" width="72" height="68" />
<h2>{strings.realIntro.title}</h2>
<p>{strings.realIntro.body}</p>
<ul>
<li>{'هنگام راه رفتن به خیابان و ماشین‌ها نگاه کنید، نه به صفحه.'}</li>
<li>{'بچه‌ها فقط همراه یک بزرگ‌تر بازی کنند.'}</li>
<li>{'هنگام رانندگی از این حالت استفاده نکنید؛ در سرعت بالا خرید غیرفعال می‌شود.'}</li>
<li>{'موقعیت شما فقط روی همین گوشی می‌ماند و جایی ارسال نمی‌شود.'}</li>
{strings.realIntro.safety.map((line) => (
<li key={line}>{line}</li>
))}
</ul>
<div className="actions">
<GameNode
@@ -34,7 +31,7 @@ export function RealIntroDialog({ nodes, actions }) {
model={nodes['real-go']}
onAction={() => actions.emit('real-go')}
>
{'قبول دارم، شروع کن'}
{strings.realIntro.accept}
</GameNode>
<GameNode
as="button"
@@ -44,7 +41,7 @@ export function RealIntroDialog({ nodes, actions }) {
model={nodes['real-cancel']}
onAction={() => actions.emit('real-cancel')}
>
{'انصراف'}
{strings.common.cancel}
</GameNode>
</div>
</GameNode>